diff --git a/.ruby-version b/.ruby-version index f13c6f4..fa7adc7 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-3.3.5 +3.3.5 diff --git a/app/models/concerns/translatable_name.rb b/app/models/concerns/translatable_name.rb new file mode 100644 index 0000000..800c9cc --- /dev/null +++ b/app/models/concerns/translatable_name.rb @@ -0,0 +1,22 @@ +# app/models/concerns/translatable_name.rb +module TranslatableName + extend ActiveSupport::Concern + + def localized_name(default_locale = "en") + return name unless translations.present? + + translations_hash = translations.is_a?(String) ? JSON.parse(translations) : translations + + # 尝试完全匹配当前语言设置 + current_locale = I18n.locale.to_s + return translations_hash[current_locale] if translations_hash[current_locale].present? + + # 尝试匹配语言的基础部分(例如 'zh-CN' => 'zh') + base_locale = current_locale.split("-").first + matching_key = translations_hash.keys.find { |k| k.start_with?(base_locale) } + return translations_hash[matching_key] if matching_key.present? + + # 如果没有匹配,返回默认语言的翻译或原始名称 + translations_hash[default_locale] || name + end +end diff --git a/app/models/country.rb b/app/models/country.rb index d9000dd..2647ddc 100644 --- a/app/models/country.rb +++ b/app/models/country.rb @@ -1,8 +1,9 @@ class Country < ApplicationRecord + include TranslatableName extend FriendlyId friendly_id :name, use: :slugged - before_save :format_timezones + # before_save :format_json_attributes, :timezones, :translations belongs_to :region, optional: true belongs_to :subregion, optional: true @@ -13,14 +14,15 @@ class Country < ApplicationRecord validates :code, presence: true, uniqueness: true validates :iso2, uniqueness: true, allow_blank: true + serialize :translations, coder: JSON def to_s name end - def localized_name - I18n.t("countries.#{code}") - end + # def localized_name + # I18n.t("countries.#{code}") + # end def self.ransackable_attributes(auth_object = nil) [ "code", "created_at", "id", "id_value", "name", "region_id", "slug", "updated_at" ] @@ -32,26 +34,26 @@ class Country < ApplicationRecord private - def format_timezones - return unless timezones.is_a?(String) - - # 使用正则替换 => 为 : - json_string = timezones.gsub(/=>/, ":") - - # 清理多余的空格 - json_string = json_string.gsub(/\s+/, " ").strip - - begin - # 验证是否为有效的 JSON - parsed_json = JSON.parse(json_string) - self.timezones = parsed_json.to_json - rescue JSON::ParserError - # 如果转换失败,可以选择: - # 1. 保持原值 - # 2. 设置为空数组 - # 3. 记录错误日志 - Rails.logger.error("Invalid JSON format for country #{id}: #{timezones}") - self.timezones = "[]" - end - end + # def format_timezones + # return unless timezones.is_a?(String) + # + # # 使用正则替换 => 为 : + # json_string = timezones.gsub(/=>/, ":") + # + # # 清理多余的空格 + # json_string = json_string.gsub(/\s+/, " ").strip + # + # begin + # # 验证是否为有效的 JSON + # parsed_json = JSON.parse(json_string) + # self.timezones = parsed_json.to_json + # rescue JSON::ParserError + # # 如果转换失败,可以选择: + # # 1. 保持原值 + # # 2. 设置为空数组 + # # 3. 记录错误日志 + # Rails.logger.error("Invalid JSON format for country #{id}: #{timezones}") + # self.timezones = "[]" + # end + # end end diff --git a/app/models/region.rb b/app/models/region.rb index b5461e0..aea379c 100644 --- a/app/models/region.rb +++ b/app/models/region.rb @@ -1,4 +1,6 @@ class Region < ApplicationRecord + include TranslatableName + extend FriendlyId friendly_id :name, use: :slugged @@ -9,13 +11,15 @@ class Region < ApplicationRecord validates :name, presence: true, uniqueness: true validates :code, presence: true, uniqueness: true + serialize :translations, coder: JSON + def to_s name end - def localized_name - I18n.t("regions.#{code}") - end + # def localized_name + # I18n.t("regions.#{code}") + # end # 模型中允许被搜索的关联 def self.ransackable_associations(auth_object = nil) diff --git a/app/views/arts/index.html.erb b/app/views/arts/index.html.erb index cbead18..67d34c3 100644 --- a/app/views/arts/index.html.erb +++ b/app/views/arts/index.html.erb @@ -26,7 +26,7 @@ <% if featured_art %>
- <%= art.city.country.name %> + <%= "#{art.city&.country&.emoji + " " || ""}#{art.city&.country&.localized_name}" %>
<%= @weather_art.prompt %>
diff --git a/config/initializers/locale.rb b/config/initializers/locale.rb
index 37d0f4b..5138b08 100644
--- a/config/initializers/locale.rb
+++ b/config/initializers/locale.rb
@@ -5,7 +5,7 @@ require "i18n/backend/fallbacks"
I18n.load_path += Dir[Rails.root.join("config", "locales", "*.{rb,yml}")]
# Permitted locales available for the application
-I18n.available_locales = [ :en, :"zh-CN" ]
+I18n.available_locales = [ :en, :"zh-CN", :ja, :ko ]
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
# I18n::Backend::Simple.include I18n::Backend::Fallbacks
diff --git a/config/locales/countries.en.yml b/config/locales/countries.en.yml
deleted file mode 100644
index 7c0b858..0000000
--- a/config/locales/countries.en.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-en:
- countries:
- # East Asia
- CN: 'China'
- JP: 'Japan'
- KR: 'South Korea'
- TW: 'Taiwan'
- HK: 'Hong Kong'
-
- # South Asia
- IN: 'India'
- PK: 'Pakistan'
- BD: 'Bangladesh'
-
- # Southeast Asia
- ID: 'Indonesia'
- VN: 'Vietnam'
- TH: 'Thailand'
- MM: 'Myanmar'
- SG: 'Singapore'
-
- # Middle East
- TR: 'Turkey'
- IR: 'Iran'
- SA: 'Saudi Arabia'
- IQ: 'Iraq'
-
- # Africa
- NG: 'Nigeria'
- EG: 'Egypt'
- CD: 'Democratic Republic of the Congo'
- TZ: 'Tanzania'
- ZA: 'South Africa'
- KE: 'Kenya'
- AO: 'Angola'
- ML: 'Mali'
- CI: 'Ivory Coast'
-
- # Europe
- RU: 'Russia'
- GB: 'United Kingdom'
- DE: 'Germany'
-
- # North America
- US: 'United States'
- MX: 'Mexico'
-
- # South America
- BR: 'Brazil'
- PE: 'Peru'
- CO: 'Colombia'
- CL: 'Chile'
-
- # Oceania
- AU: 'Australia'
\ No newline at end of file
diff --git a/config/locales/countries.zh-CN.yml b/config/locales/countries.zh-CN.yml
deleted file mode 100644
index 0547529..0000000
--- a/config/locales/countries.zh-CN.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-zh-CN:
- countries:
- # East Asia
- CN: '中国'
- JP: '日本'
- KR: '韩国'
- TW: '台湾'
- HK: '香港'
-
- # South Asia
- IN: '印度'
- PK: '巴基斯坦'
- BD: '孟加拉国'
-
- # Southeast Asia
- ID: '印度尼西亚'
- VN: '越南'
- TH: '泰国'
- MM: '缅甸'
- SG: '新加坡'
-
- # Middle East
- TR: '土耳其'
- IR: '伊朗'
- SA: '沙特阿拉伯'
- IQ: '伊拉克'
-
- # Africa
- NG: '尼日利亚'
- EG: '埃及'
- CD: '刚果民主共和国'
- TZ: '坦桑尼亚'
- ZA: '南非'
- KE: '肯尼亚'
- AO: '安哥拉'
- ML: '马里'
- CI: '科特迪瓦'
-
- # Europe
- RU: '俄罗斯'
- GB: '英国'
- DE: '德国'
-
- # North America
- US: '美国'
- MX: '墨西哥'
-
- # South America
- BR: '巴西'
- PE: '秘鲁'
- CO: '哥伦比亚'
- CL: '智利'
-
- # Oceania
- AU: '澳大利亚'
\ No newline at end of file
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f73d8f2..a026f71 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -28,6 +28,11 @@
# enabled: "ON"
en:
+ language:
+ en: "English"
+ zh-CN: "简体中文"
+ ja: "日本語"
+ ko: "한국어"
hello: "Hello world"
brand:
name: "Today AI Weather"
@@ -40,12 +45,17 @@ en:
admin_dashboard: "Admin Dashboard"
latest_weather_art: "Latest Weather Art"
popular_weather_art: "Popular Weather Art"
+ ai_prompt: "AI Prompt"
text:
latest_from: "Latest from"
search_cities: "Search cities..."
all_regions: "All Regions"
+ all_countries: "All Countries"
+ all_in: "All in"
showing: "Showing"
weather_arts: "Weather Arts"
+ newest_first: "Newest First"
+ oldest_first: "Oldest First"
cities:
title: "Explore Cities"
arts:
@@ -62,6 +72,18 @@ en:
view_all_weather_arts: "View All Weather Arts"
back_to_cities: "Back to Cities"
back_to: "Back to"
+ card:
+ temperature: "Temperature"
+ wind: "Wind"
+ humidity: "Humidity"
+ visibility: "Visibility"
+ pressure: "Pressure"
+ cloud_cover: "Cloud Cover"
+ feel_like: "Feels like"
+ relative_humidity: "Relative humidity"
+ clear_view_distance: "Clear view distance"
+ atmospheric_pressure: "Atmospheric pressure"
+ sky_coverage: "Sky coverage"
pagination:
showing_items: "Showing %{from} to %{to} of %{total} %{items}"
items:
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
new file mode 100644
index 0000000..6677335
--- /dev/null
+++ b/config/locales/ja.yml
@@ -0,0 +1,62 @@
+ja:
+ hello: "こんにちは世界"
+ brand:
+ name: "今日のAI天気"
+ title:
+ cities: "都市"
+ arts: "アート"
+ sign_in: "サインイン"
+ sign_out: "サインアウト"
+ settings: "設定"
+ admin_dashboard: "管理者ダッシュボード"
+ latest_weather_art: "最新の天気アート"
+ popular_weather_art: "人気の天気アート"
+ ai_prompt: "AIプロンプト"
+ text:
+ latest_from: "最新情報"
+ search_cities: "都市を検索..."
+ all_regions: "すべての地域"
+ all_countries: "すべての国"
+ all_in: "すべて含む"
+ showing: "表示中"
+ weather_arts: "天気アート"
+ newest_first: "最新順"
+ oldest_first: "古い順"
+ cities:
+ title: "都市を探る"
+ arts:
+ title: "天気アートギャラリー"
+ subtitle: "世界中の都市から生成されたAI天気アートを発見"
+ home:
+ headline_html: 天気が出会う場所
人工知能
+ subtitle:
+ AI生成アートのレンズを通して天気を体験し、
+ 日常の気象現象に新しい視点をもたらします。
+ button:
+ explore_cities: "都市を探る"
+ view_detail: "詳細を見る"
+ view_all_weather_arts: "すべての天気アートを見る"
+ back_to_cities: "都市に戻る"
+ back_to: "戻る"
+ card:
+ temperature: "温度"
+ wind: "風"
+ humidity: "湿度"
+ visibility: "視界"
+ pressure: "圧力"
+ cloud_cover: "雲の覆い"
+ feel_like: "体感温度"
+ relative_humidity: "相対湿度"
+ clear_view_distance: "クリアビュー距離"
+ atmospheric_pressure: "大気圧"
+ sky_coverage: "空の覆い"
+ pagination:
+ showing_items: "合計 %{total} %{items} のうち %{from} から %{to} まで表示"
+ items:
+ weather: "天気記録"
+ default: "アイテム"
+ time:
+ formats:
+ time_only: "%H:%M"
+ with_zone: "%{time} %{zone}"
+ date_and_time: "%{date} %{time}"
\ No newline at end of file
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
new file mode 100644
index 0000000..7f323c3
--- /dev/null
+++ b/config/locales/ko.yml
@@ -0,0 +1,62 @@
+ko:
+ hello: "안녕하세요 세계"
+ brand:
+ name: "오늘의 AI 날씨"
+ title:
+ cities: "도시"
+ arts: "예술"
+ sign_in: "로그인"
+ sign_out: "로그아웃"
+ settings: "설정"
+ admin_dashboard: "관리자 대시보드"
+ latest_weather_art: "최신 날씨 예술"
+ popular_weather_art: "인기 있는 날씨 예술"
+ ai_prompt: "AI 프롬프트"
+ text:
+ latest_from: "최신 소식"
+ search_cities: "도시 검색..."
+ all_regions: "모든 지역"
+ all_countries: "모든 국가"
+ all_in: "모두 포함"
+ showing: "표시 중"
+ weather_arts: "날씨 예술"
+ newest_first: "최신순"
+ oldest_first: "오래된 순"
+ cities:
+ title: "도시 탐험"
+ arts:
+ title: "날씨 예술 갤러리"
+ subtitle: "전 세계 도시에서 생성된 AI 날씨 예술 발견하기"
+ home:
+ headline_html: 날씨가 만나는 곳
인공지능
+ subtitle:
+ AI 생성 예술의 렌즈를 통해 날씨를 경험하세요,
+ 일상적인 기상 현상에 대한 새로운 관점을 제공합니다.
+ button:
+ explore_cities: "도시 탐험"
+ view_detail: "상세 보기"
+ view_all_weather_arts: "모든 날씨 예술 보기"
+ back_to_cities: "도시로 돌아가기"
+ back_to: "돌아가기"
+ card:
+ temperature: "온도"
+ wind: "바람"
+ humidity: "습도"
+ visibility: "가시성"
+ pressure: "압력"
+ cloud_cover: "구름 덮개"
+ feel_like: "체감 온도"
+ relative_humidity: "상대 습도"
+ clear_view_distance: "맑은 시야 거리"
+ atmospheric_pressure: "대기압"
+ sky_coverage: "하늘 덮개"
+ pagination:
+ showing_items: "총 %{total} %{items} 중 %{from}에서 %{to}까지 표시"
+ items:
+ weather: "날씨 기록"
+ default: "항목"
+ time:
+ formats:
+ time_only: "%H:%M"
+ with_zone: "%{time} %{zone}"
+ date_and_time: "%{date} %{time}"
\ No newline at end of file
diff --git a/config/locales/regions.en.yml b/config/locales/regions.en.yml
deleted file mode 100644
index 8558328..0000000
--- a/config/locales/regions.en.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-en:
- regions:
- AS: 'Asia'
- SA: 'South Asia'
- SEA: 'Southeast Asia'
- EA: 'East Asia'
- ME: 'Middle East'
- AF: 'Africa'
- NA: 'North Africa'
- SSA: 'Sub-Saharan Africa'
- EU: 'Europe'
- NAM: 'North America'
- SAM: 'South America'
- CAM: 'Central America'
- OC: 'Oceania'
\ No newline at end of file
diff --git a/config/locales/regions.zh-CN.yml b/config/locales/regions.zh-CN.yml
deleted file mode 100644
index 14f19f9..0000000
--- a/config/locales/regions.zh-CN.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-zh-CN:
- regions:
- AS: '亚洲'
- SA: '南亚'
- SEA: '东南亚'
- EA: '东亚'
- ME: '中东'
- AF: '非洲'
- NA: '北非'
- SSA: '撒哈拉以南非洲'
- EU: '欧洲'
- NAM: '北美洲'
- SAM: '南美洲'
- CAM: '中美洲'
- OC: '大洋洲'
\ No newline at end of file
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 82cb45e..5dca8f9 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -11,12 +11,17 @@ zh-CN:
admin_dashboard: "管理中枢"
latest_weather_art: "气象绘卷·新作"
popular_weather_art: "气象绘卷·佳作"
+ ai_prompt: "天气描述"
text:
latest_from: "新至之城"
search_cities: "寻城觅境…"
all_regions: "寰宇之境"
+ all_countries: "所有国家"
+ all_in: "全部"
showing: "映现"
weather_arts: "气象艺境"
+ newest_first: "最新优先"
+ oldest_first: "最早优先"
cities:
title: "云游四海"
arts:
@@ -32,6 +37,18 @@ zh-CN:
view_all_weather_arts: "尽览天工"
back_to_cities: "继续探索城市"
back_to: "回到"
+ card:
+ temperature: "温度"
+ wind: "风力"
+ humidity: "湿度"
+ visibility: "能见度"
+ pressure: "气压"
+ cloud_cover: "云量"
+ feel_like: "体感温度"
+ relative_humidity: "相对湿度"
+ clear_view_distance: "清晰视距"
+ atmospheric_pressure: "大气压力"
+ sky_coverage: "天空覆盖"
pagination:
showing_items: "显示第 %{from} 到第 %{to} 条,共 %{total} 条%{items}"
items:
diff --git a/lib/tasks/sync_geo_data.rake b/lib/tasks/sync_geo_data.rake
index 6237b66..47c4b64 100644
--- a/lib/tasks/sync_geo_data.rake
+++ b/lib/tasks/sync_geo_data.rake
@@ -32,7 +32,7 @@ namespace :geo do
region.update!(
name: data["name"],
code: data["name"],
- translations: data["translations"],
+ translations: data["translations"].to_json,
flag: data["flag"] || true,
wiki_data_id: data["wikiDataId"]
)
@@ -55,7 +55,7 @@ namespace :geo do
count += 1
subregion.update!(
- translations: data["translations"],
+ translations: data["translations"].to_json,
flag: data["flag"] || true,
wiki_data_id: data["wikiDataId"]
)
@@ -106,8 +106,8 @@ namespace :geo do
tld: data["tld"],
native: data["native"],
nationality: data["nationality"],
- timezones: data["timezones"],
- translations: data["translations"],
+ timezones: data["timezones"].to_json,
+ translations: data["translations"].to_json,
latitude: data["latitude"],
longitude: data["longitude"],
emoji: data["emoji"],