Compare commits
1 Commits
main
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
|
c88d72fdaf |
4
.github/workflows/docker-dev.yml
vendored
4
.github/workflows/docker-dev.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Docker Dev
|
name: Docker
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -45,4 +45,4 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/${{github.actor}}/${{ github.event.repository.name }}_dev:dev
|
${{ env.REGISTRY }}/${{github.actor}}/${{ github.event.repository.name }}:dev
|
2
.github/workflows/docker-main.yml
vendored
2
.github/workflows/docker-main.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Docker Main
|
name: Docker
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -1 +1 @@
|
|||||||
3.3.5
|
ruby-3.3.5
|
||||||
|
4
Gemfile
4
Gemfile
@ -53,7 +53,7 @@ gem "sitemap_generator", "~> 6.3"
|
|||||||
gem "ahoy_matey", "~> 5.2"
|
gem "ahoy_matey", "~> 5.2"
|
||||||
|
|
||||||
# gem "whenever", "~> 1.0"
|
# gem "whenever", "~> 1.0"
|
||||||
gem "ruby-openai", "~> 7.3"
|
gem "ruby-openai", "~> 7.4"
|
||||||
gem "httparty", "~> 0.22.0"
|
gem "httparty", "~> 0.22.0"
|
||||||
gem "down", "~> 5.4"
|
gem "down", "~> 5.4"
|
||||||
gem "aws-sdk-s3", "~> 1.170"
|
gem "aws-sdk-s3", "~> 1.170"
|
||||||
@ -67,8 +67,6 @@ gem "mini_magick", "~> 4.13.2"
|
|||||||
|
|
||||||
gem "redis", "~> 5.3"
|
gem "redis", "~> 5.3"
|
||||||
|
|
||||||
gem "builder", "~> 3.3"
|
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
||||||
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
|
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
|
||||||
|
@ -217,7 +217,7 @@ GEM
|
|||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
jsbundling-rails (1.3.1)
|
jsbundling-rails (1.3.1)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
json (2.9.1)
|
json (2.10.1)
|
||||||
kamal (2.4.0)
|
kamal (2.4.0)
|
||||||
activesupport (>= 7.0)
|
activesupport (>= 7.0)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
@ -242,7 +242,7 @@ GEM
|
|||||||
kaminari-core (= 1.2.2)
|
kaminari-core (= 1.2.2)
|
||||||
kaminari-core (1.2.2)
|
kaminari-core (1.2.2)
|
||||||
language_server-protocol (3.17.0.4)
|
language_server-protocol (3.17.0.4)
|
||||||
logger (1.6.5)
|
logger (1.6.6)
|
||||||
loofah (2.24.0)
|
loofah (2.24.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.12.0)
|
nokogiri (>= 1.12.0)
|
||||||
@ -404,7 +404,7 @@ GEM
|
|||||||
rubocop-minitest
|
rubocop-minitest
|
||||||
rubocop-performance
|
rubocop-performance
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
ruby-openai (7.3.1)
|
ruby-openai (7.4.0)
|
||||||
event_stream_parser (>= 0.3.0, < 2.0.0)
|
event_stream_parser (>= 0.3.0, < 2.0.0)
|
||||||
faraday (>= 1)
|
faraday (>= 1)
|
||||||
faraday-multipart (>= 1)
|
faraday-multipart (>= 1)
|
||||||
@ -523,7 +523,6 @@ DEPENDENCIES
|
|||||||
aws-sdk-s3 (~> 1.170)
|
aws-sdk-s3 (~> 1.170)
|
||||||
bootsnap
|
bootsnap
|
||||||
brakeman
|
brakeman
|
||||||
builder (~> 3.3)
|
|
||||||
bullet (~> 8.0)
|
bullet (~> 8.0)
|
||||||
capybara
|
capybara
|
||||||
cssbundling-rails
|
cssbundling-rails
|
||||||
@ -546,7 +545,7 @@ DEPENDENCIES
|
|||||||
rails (~> 8.0.1)
|
rails (~> 8.0.1)
|
||||||
redis (~> 5.3)
|
redis (~> 5.3)
|
||||||
rubocop-rails-omakase
|
rubocop-rails-omakase
|
||||||
ruby-openai (~> 7.3)
|
ruby-openai (~> 7.4)
|
||||||
selenium-webdriver
|
selenium-webdriver
|
||||||
sidekiq (~> 7.3)
|
sidekiq (~> 7.3)
|
||||||
sidekiq-scheduler (~> 5.0)
|
sidekiq-scheduler (~> 5.0)
|
||||||
|
@ -2,7 +2,6 @@ class ApplicationController < ActionController::Base
|
|||||||
include SeoConcern
|
include SeoConcern
|
||||||
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
||||||
before_action :log_browser_info
|
before_action :log_browser_info
|
||||||
before_action :set_content_type_for_rss, if: -> { request.format.rss? }
|
|
||||||
# allow_browser versions: :modern
|
# allow_browser versions: :modern
|
||||||
# allow_browser versions: :modern,
|
# allow_browser versions: :modern,
|
||||||
# patterns: [
|
# patterns: [
|
||||||
@ -48,7 +47,7 @@ class ApplicationController < ActionController::Base
|
|||||||
# Bot: #{browser.bot?}
|
# Bot: #{browser.bot?}
|
||||||
# BROWSER_INFO
|
# BROWSER_INFO
|
||||||
# }
|
# }
|
||||||
around_action :set_locale
|
before_action :set_locale
|
||||||
after_action :track_action
|
after_action :track_action
|
||||||
|
|
||||||
def log_browser_info
|
def log_browser_info
|
||||||
@ -76,55 +75,7 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_locale(&action)
|
def set_locale
|
||||||
I18n.locale = extract_locale || I18n.default_locale
|
I18n.locale = params[:locale] || I18n.default_locale
|
||||||
I18n.fallbacks[I18n.locale] = [ I18n.locale, I18n.default_locale ].uniq
|
|
||||||
locale = params[:locale] || extract_locale_from_accept_language_header || I18n.default_locale
|
|
||||||
I18n.with_locale(locale, &action)
|
|
||||||
# 重定向到带有语言前缀的相同路径
|
|
||||||
# redirect_to "/#{locale}#{request.fullpath}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def extract_locale_from_accept_language_header
|
|
||||||
return I18n.default_locale.to_s unless request.env["HTTP_ACCEPT_LANGUAGE"]
|
|
||||||
|
|
||||||
available_locales = I18n.available_locales.map(&:to_s)
|
|
||||||
|
|
||||||
accept_language = request.env["HTTP_ACCEPT_LANGUAGE"].to_s
|
|
||||||
# 修改正则表达式以匹配 'zh-CN' 这样的格式
|
|
||||||
if (full_locale = accept_language.scan(/^[a-z]{2}-[A-Z]{2}/).first)
|
|
||||||
locale = full_locale
|
|
||||||
else
|
|
||||||
# 否则只匹配语言代码 (例如 'en')
|
|
||||||
locale = accept_language.scan(/^[a-z]{2}/).first || I18n.default_locale.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
return locale if available_locales.include?(locale)
|
|
||||||
|
|
||||||
# 尝试基础语言匹配(例如:当请求 'zh' 时匹配 'zh-CN')
|
|
||||||
base_language = locale.split("-").first
|
|
||||||
matching_locale = available_locales.find do |available_locale|
|
|
||||||
available_locale.start_with?(base_language)
|
|
||||||
end
|
|
||||||
matching_locale ? matching_locale : I18n.default_locale.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def sanitize_locale(locale)
|
|
||||||
# 直接使用 I18n.available_locales
|
|
||||||
locale = locale.to_sym
|
|
||||||
I18n.available_locales.include?(locale) ? locale : I18n.default_locale
|
|
||||||
end
|
|
||||||
|
|
||||||
def extract_locale
|
|
||||||
parsed_locale = params[:locale]
|
|
||||||
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_url_options
|
|
||||||
{ locale: I18n.locale }
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_content_type_for_rss
|
|
||||||
response.headers["Content-Type"] = "application/rss+xml; charset=utf-8"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -46,7 +46,7 @@ class CitiesController < ApplicationController
|
|||||||
set_meta_tags(
|
set_meta_tags(
|
||||||
title: @city.name,
|
title: @city.name,
|
||||||
description: "Experience #{@city.name}'s weather through AI-generated art. Daily updates of weather conditions visualized through artificial intelligence.",
|
description: "Experience #{@city.name}'s weather through AI-generated art. Daily updates of weather conditions visualized through artificial intelligence.",
|
||||||
keywords: "#{@city.name}, #{@city.country.name}, ai, ai web, ai art, ai weather, weather art, AI visualization",
|
keywords: "#{@city.name}, #{@city.country.name}, weather art, AI visualization",
|
||||||
og: {
|
og: {
|
||||||
image: @city.latest_weather_art&.image&.attached? ? url_for(@city.latest_weather_art.image) : nil
|
image: @city.latest_weather_art&.image&.attached? ? url_for(@city.latest_weather_art.image) : nil
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
class RssController < ApplicationController
|
|
||||||
def feed
|
|
||||||
@weather_arts = WeatherArt.order(created_at: :desc).limit(20)
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.rss { render layout: false }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,126 +1,33 @@
|
|||||||
class SitemapsController < ApplicationController
|
class SitemapsController < ApplicationController
|
||||||
include SitemapsHelper
|
|
||||||
before_action :set_bucket_name
|
|
||||||
|
|
||||||
def index
|
|
||||||
@sitemaps = list_sitemaps
|
|
||||||
respond_to do |format|
|
|
||||||
format.html
|
|
||||||
format.xml { render_sitemap_index }
|
|
||||||
end
|
|
||||||
rescue Aws::S3::Errors::ServiceError => e
|
|
||||||
Rails.logger.error "S3 Error: #{e.message}"
|
|
||||||
render status: :internal_server_error
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
path = params[:path]
|
path = params[:path]
|
||||||
key = "sitemaps/#{path}"
|
bucket_name =
|
||||||
|
Rails.env.production? ?
|
||||||
Rails.logger.info "Requesting sitemap: #{path}"
|
ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws, :bucket)) :
|
||||||
|
ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket))
|
||||||
|
Rails.logger.info "Sitemap: #{path}"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# 检查文件是否存在
|
s3_client = Aws::S3::Client.new
|
||||||
s3_client.head_object(
|
response = s3_client.get_object(
|
||||||
bucket: @bucket_name,
|
bucket: bucket_name,
|
||||||
key: key
|
key: "sitemaps/#{path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 生成预签名URL,设置15分钟有效期
|
expires_in 12.hours, public: true
|
||||||
signer = Aws::S3::Presigner.new(client: s3_client)
|
content_type = response.content_type || "application/xml"
|
||||||
url = signer.presigned_url(
|
|
||||||
:get_object,
|
send_data(
|
||||||
bucket: @bucket_name,
|
response.body.read,
|
||||||
key: key,
|
filename: path,
|
||||||
expires_in: 15 * 60, # 15 minutes
|
type: content_type,
|
||||||
# response_content_type: 'application/xml', # 确保正确的内容类型
|
disposition: "inline"
|
||||||
response_content_disposition: "inline" # 在浏览器中直接显示
|
|
||||||
)
|
)
|
||||||
|
rescue Aws::S3::Errors::NoSuchKey
|
||||||
# 设置缓存头
|
|
||||||
response.headers["Cache-Control"] = "public, max-age=3600" # 1小时缓存
|
|
||||||
|
|
||||||
# 重定向到预签名URL
|
|
||||||
redirect_to url, allow_other_host: true, status: :found
|
|
||||||
|
|
||||||
rescue Aws::S3::Errors::NotFound
|
|
||||||
Rails.logger.error "Sitemap not found: #{path}"
|
|
||||||
render status: :not_found
|
render status: :not_found
|
||||||
rescue Aws::S3::Errors::ServiceError => e
|
rescue Aws::S3::Errors::ServiceError => e
|
||||||
Rails.logger.error "S3 Error: #{e.message}"
|
Rails.logger.error "S3 Error: #{e.message}"
|
||||||
render status: :internal_server_error
|
render status: :internal_server_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# def show
|
|
||||||
# path = params[:path]
|
|
||||||
# Rails.logger.info "Sitemap: #{path}"
|
|
||||||
|
|
||||||
# begin
|
|
||||||
# response = s3_client.get_object(
|
|
||||||
# bucket: @bucket_name,
|
|
||||||
# key: "sitemaps/#{path}"
|
|
||||||
# )
|
|
||||||
|
|
||||||
# expires_in 12.hours, public: true
|
|
||||||
# content_type = response.content_type || "application/xml"
|
|
||||||
|
|
||||||
# send_data(
|
|
||||||
# response.body.read,
|
|
||||||
# filename: path,
|
|
||||||
# type: content_type,
|
|
||||||
# disposition: "inline"
|
|
||||||
# )
|
|
||||||
# rescue Aws::S3::Errors::NoSuchKey
|
|
||||||
# render status: :not_found
|
|
||||||
# rescue Aws::S3::Errors::ServiceError => e
|
|
||||||
# Rails.logger.error "S3 Error: #{e.message}"
|
|
||||||
# render status: :internal_server_error
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_bucket_name
|
|
||||||
@bucket_name = Rails.env.production? ?
|
|
||||||
ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:minio, :bucket)) :
|
|
||||||
ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:minio_dev, :bucket))
|
|
||||||
end
|
|
||||||
|
|
||||||
def s3_client
|
|
||||||
@s3_client ||= Aws::S3::Client.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_sitemaps
|
|
||||||
response = s3_client.list_objects_v2(
|
|
||||||
bucket: @bucket_name,
|
|
||||||
prefix: "sitemaps/"
|
|
||||||
)
|
|
||||||
|
|
||||||
response.contents.map do |object|
|
|
||||||
{
|
|
||||||
key: object.key.sub("sitemaps/", ""),
|
|
||||||
last_modified: object.last_modified,
|
|
||||||
size: object.size,
|
|
||||||
url: sitemap_url(object.key.sub("sitemaps/", ""))
|
|
||||||
}
|
|
||||||
end.reject { |obj| obj[:key].empty? }
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_sitemap_index
|
|
||||||
base_url = "#{request.protocol}#{request.host_with_port}"
|
|
||||||
|
|
||||||
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
|
||||||
xml.sitemapindex(xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9") do
|
|
||||||
@sitemaps.each do |sitemap|
|
|
||||||
xml.sitemap do
|
|
||||||
xml.loc "#{base_url}/sitemaps/#{sitemap[:key]}"
|
|
||||||
xml.lastmod sitemap[:last_modified].iso8601
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
render xml: builder.to_xml
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -17,7 +17,7 @@ class WeatherArtsController < ApplicationController
|
|||||||
set_meta_tags(
|
set_meta_tags(
|
||||||
title: "#{@city.name} Weather Art - #{@weather_art.weather_date.strftime('%B %d, %Y')}",
|
title: "#{@city.name} Weather Art - #{@weather_art.weather_date.strftime('%B %d, %Y')}",
|
||||||
description: "#{@city.name}'s weather visualized through AI art. #{@weather_art.description} at #{@weather_art.temperature}°C.",
|
description: "#{@city.name}'s weather visualized through AI art. #{@weather_art.description} at #{@weather_art.temperature}°C.",
|
||||||
keywords: "#{@city.name}, #{@city.country.name}, ai, ai web, ai art, ai weather, weather art, AI visualization, #{@weather_art.description}",
|
keywords: "#{@city.name}, weather art, #{@weather_art.description}, AI visualization",
|
||||||
og: {
|
og: {
|
||||||
image: @weather_art.image.attached? ? url_for(@weather_art.image) : nil
|
image: @weather_art.image.attached? ? url_for(@weather_art.image) : nil
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
module RssHelper
|
|
||||||
end
|
|
@ -1,5 +1,2 @@
|
|||||||
module SitemapsHelper
|
module SitemapsHelper
|
||||||
def sitemap_url(filename)
|
|
||||||
"/sitemaps/#{filename}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
# 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
|
|
@ -1,9 +1,8 @@
|
|||||||
class Country < ApplicationRecord
|
class Country < ApplicationRecord
|
||||||
include TranslatableName
|
|
||||||
extend FriendlyId
|
extend FriendlyId
|
||||||
friendly_id :name, use: :slugged
|
friendly_id :name, use: :slugged
|
||||||
|
|
||||||
# before_save :format_json_attributes, :timezones, :translations
|
before_save :format_timezones
|
||||||
|
|
||||||
belongs_to :region, optional: true
|
belongs_to :region, optional: true
|
||||||
belongs_to :subregion, optional: true
|
belongs_to :subregion, optional: true
|
||||||
@ -14,15 +13,14 @@ class Country < ApplicationRecord
|
|||||||
validates :code, presence: true, uniqueness: true
|
validates :code, presence: true, uniqueness: true
|
||||||
validates :iso2, uniqueness: true, allow_blank: true
|
validates :iso2, uniqueness: true, allow_blank: true
|
||||||
|
|
||||||
serialize :translations, coder: JSON
|
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
# def localized_name
|
def localized_name
|
||||||
# I18n.t("countries.#{code}")
|
I18n.t("countries.#{code}")
|
||||||
# end
|
end
|
||||||
|
|
||||||
def self.ransackable_attributes(auth_object = nil)
|
def self.ransackable_attributes(auth_object = nil)
|
||||||
[ "code", "created_at", "id", "id_value", "name", "region_id", "slug", "updated_at" ]
|
[ "code", "created_at", "id", "id_value", "name", "region_id", "slug", "updated_at" ]
|
||||||
@ -34,26 +32,26 @@ class Country < ApplicationRecord
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# def format_timezones
|
def format_timezones
|
||||||
# return unless timezones.is_a?(String)
|
return unless timezones.is_a?(String)
|
||||||
#
|
|
||||||
# # 使用正则替换 => 为 :
|
# 使用正则替换 => 为 :
|
||||||
# json_string = timezones.gsub(/=>/, ":")
|
json_string = timezones.gsub(/=>/, ":")
|
||||||
#
|
|
||||||
# # 清理多余的空格
|
# 清理多余的空格
|
||||||
# json_string = json_string.gsub(/\s+/, " ").strip
|
json_string = json_string.gsub(/\s+/, " ").strip
|
||||||
#
|
|
||||||
# begin
|
begin
|
||||||
# # 验证是否为有效的 JSON
|
# 验证是否为有效的 JSON
|
||||||
# parsed_json = JSON.parse(json_string)
|
parsed_json = JSON.parse(json_string)
|
||||||
# self.timezones = parsed_json.to_json
|
self.timezones = parsed_json.to_json
|
||||||
# rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
# # 如果转换失败,可以选择:
|
# 如果转换失败,可以选择:
|
||||||
# # 1. 保持原值
|
# 1. 保持原值
|
||||||
# # 2. 设置为空数组
|
# 2. 设置为空数组
|
||||||
# # 3. 记录错误日志
|
# 3. 记录错误日志
|
||||||
# Rails.logger.error("Invalid JSON format for country #{id}: #{timezones}")
|
Rails.logger.error("Invalid JSON format for country #{id}: #{timezones}")
|
||||||
# self.timezones = "[]"
|
self.timezones = "[]"
|
||||||
# end
|
end
|
||||||
# end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
class Region < ApplicationRecord
|
class Region < ApplicationRecord
|
||||||
include TranslatableName
|
|
||||||
|
|
||||||
extend FriendlyId
|
extend FriendlyId
|
||||||
friendly_id :name, use: :slugged
|
friendly_id :name, use: :slugged
|
||||||
|
|
||||||
@ -11,15 +9,13 @@ class Region < ApplicationRecord
|
|||||||
validates :name, presence: true, uniqueness: true
|
validates :name, presence: true, uniqueness: true
|
||||||
validates :code, presence: true, uniqueness: true
|
validates :code, presence: true, uniqueness: true
|
||||||
|
|
||||||
serialize :translations, coder: JSON
|
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
# def localized_name
|
def localized_name
|
||||||
# I18n.t("regions.#{code}")
|
I18n.t("regions.#{code}")
|
||||||
# end
|
end
|
||||||
|
|
||||||
# 模型中允许被搜索的关联
|
# 模型中允许被搜索的关联
|
||||||
def self.ransackable_associations(auth_object = nil)
|
def self.ransackable_associations(auth_object = nil)
|
||||||
|
@ -79,23 +79,11 @@ class WeatherArt < ApplicationRecord
|
|||||||
ActiveSupport::TimeZone["UTC"]
|
ActiveSupport::TimeZone["UTC"]
|
||||||
time = self.updated_at
|
time = self.updated_at
|
||||||
|
|
||||||
# 使用 I18n 本地化格式化日期
|
date_string = self.weather_date&.strftime("%B %d, %Y")
|
||||||
date_string = I18n.l(self.weather_date, format: :long)
|
|
||||||
|
|
||||||
# 格式化时间
|
|
||||||
time_format = use_local_timezone ? time.in_time_zone(time_zone) : time.utc
|
|
||||||
time_string =
|
time_string =
|
||||||
if use_local_timezone
|
use_local_timezone ?
|
||||||
I18n.t("time.formats.with_zone",
|
"#{time.in_time_zone(time_zone).strftime('%H:%M')} #{timezone_info['gmtOffsetName']}" :
|
||||||
time: I18n.l(time_format, format: :time_only),
|
"#{time.utc.strftime('%H:%M')} UTC"
|
||||||
zone: timezone_info["gmtOffsetName"]
|
|
||||||
)
|
|
||||||
else
|
|
||||||
I18n.t("time.formats.with_zone",
|
|
||||||
time: I18n.l(time_format, format: :time_only),
|
|
||||||
zone: "UTC"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
case type
|
case type
|
||||||
when :date
|
when :date
|
||||||
@ -103,15 +91,9 @@ class WeatherArt < ApplicationRecord
|
|||||||
when :time
|
when :time
|
||||||
time_string
|
time_string
|
||||||
when :all
|
when :all
|
||||||
I18n.t("time.formats.date_and_time",
|
"#{date_string} #{time_string}"
|
||||||
date: date_string,
|
|
||||||
time: time_string
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
I18n.t("time.formats.date_and_time",
|
"#{date_string} #{time_string}"
|
||||||
date: date_string,
|
|
||||||
time: time_string
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@
|
|||||||
<div class="container mx-auto px-4">
|
<div class="container mx-auto px-4">
|
||||||
<div class="max-w-3xl mx-auto text-center space-y-6">
|
<div class="max-w-3xl mx-auto text-center space-y-6">
|
||||||
<h1 class="text-4xl md:text-5xl font-display font-bold">
|
<h1 class="text-4xl md:text-5xl font-display font-bold">
|
||||||
<%= t("arts.title") %>
|
Weather Arts Gallery
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-xl text-base-content/70">
|
<p class="text-xl text-base-content/70">
|
||||||
<%= t("arts.subtitle") %>
|
Discover AI-generated weather art from cities around the world
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- 如果有特色图片,显示其信息 -->
|
<!-- 如果有特色图片,显示其信息 -->
|
||||||
<% if featured_art %>
|
<% if featured_art %>
|
||||||
<div class="text-sm text-base-content/60 pt-4">
|
<div class="text-sm text-base-content/60 pt-4">
|
||||||
<%= "#{t("text.latest_from")} #{featured_art.city.full_name}" %>
|
Latest from <%= featured_art.city.name %>, <%= featured_art.city.country.name %>
|
||||||
<span class="mx-2">•</span>
|
<span class="mx-2">•</span>
|
||||||
<%= featured_art.formatted_time(:date) %>
|
<%= featured_art.formatted_time(:date) %>
|
||||||
</div>
|
</div>
|
||||||
@ -47,18 +47,18 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= params[:sort] == 'oldest' ? t("text.oldest_first") : t("text.newest_first") %>
|
<%= params[:sort] == 'oldest' ? 'Oldest First' : 'Newest First' %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52">
|
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52">
|
||||||
<li>
|
<li>
|
||||||
<%= link_to t("text.newest_first"), arts_path(sort: 'newest', region: params[:region]),
|
<%= link_to "Newest First", arts_path(sort: 'newest', region: params[:region]),
|
||||||
class: "#{'active' if params[:sort] != 'oldest'}" %>
|
class: "#{'active' if params[:sort] != 'oldest'}" %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to t("text.oldest_first"), arts_path(sort: 'oldest', region: params[:region]),
|
<%= link_to "Oldest First", arts_path(sort: 'oldest', region: params[:region]),
|
||||||
class: "#{'active' if params[:sort] == 'oldest'}" %>
|
class: "#{'active' if params[:sort] == 'oldest'}" %>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -70,20 +70,20 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= @current_region&.localized_name || t("text.all_regions") %>
|
<%= @current_region&.name || 'All Regions' %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52">
|
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52">
|
||||||
<li>
|
<li>
|
||||||
<%= link_to t("text.all_regions"), arts_path(sort: params[:sort]),
|
<%= link_to "All Regions", arts_path(sort: params[:sort]),
|
||||||
class: "#{'active' unless @current_region}" %>
|
class: "#{'active' unless @current_region}" %>
|
||||||
</li>
|
</li>
|
||||||
<div class="divider my-1"></div>
|
<div class="divider my-1"></div>
|
||||||
<% @regions.each do |region| %>
|
<% @regions.each do |region| %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to region.localized_name, arts_path(region: region.id, sort: params[:sort]),
|
<%= link_to region.name, arts_path(region: region.id, sort: params[:sort]),
|
||||||
class: "#{'active' if @current_region == region}" %>
|
class: "#{'active' if @current_region == region}" %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -93,9 +93,9 @@
|
|||||||
|
|
||||||
<!-- 结果统计 -->
|
<!-- 结果统计 -->
|
||||||
<div class="text-center text-sm text-base-content/70 mt-4">
|
<div class="text-center text-sm text-base-content/70 mt-4">
|
||||||
<%= "#{t("text.showing")} #{@weather_arts.total_count} #{t("text.weather_arts")} " %>
|
Showing <%= @weather_arts.total_count %> weather arts
|
||||||
<% if @current_region %>
|
<% if @current_region %>
|
||||||
from <%= @current_region.localized_name %>
|
from <%= @current_region.name %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -118,7 +118,7 @@
|
|||||||
<%= art.city.name %>
|
<%= art.city.name %>
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-sm text-white/80">
|
<p class="text-sm text-white/80">
|
||||||
<%= "#{art.city&.country&.emoji + " " || ""}#{art.city&.country&.localized_name}" %>
|
<%= art.city.country.name %>
|
||||||
</p>
|
</p>
|
||||||
<div class="flex items-center gap-2 text-white/90">
|
<div class="flex items-center gap-2 text-white/90">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
@ -154,7 +154,7 @@
|
|||||||
|
|
||||||
<%= link_to city_weather_art_path(art.city, art),
|
<%= link_to city_weather_art_path(art.city, art),
|
||||||
class: "btn btn-primary btn-sm w-full" do %>
|
class: "btn btn-primary btn-sm w-full" do %>
|
||||||
<%= t("button.view_detail") %>
|
View Details
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
<div class="card-actions justify-end">
|
<div class="card-actions justify-end">
|
||||||
<%= link_to city_path(city),
|
<%= link_to city_path(city),
|
||||||
class: "btn btn-primary btn-sm gap-2", data: { turbo_frame: "_top" } do %>
|
class: "btn btn-primary btn-sm gap-2", data: { turbo_frame: "_top" } do %>
|
||||||
<%= t("button.view_detail") %>
|
View Details
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -115,7 +115,7 @@
|
|||||||
<div class="card-actions justify-end">
|
<div class="card-actions justify-end">
|
||||||
<%= link_to city_path(city),
|
<%= link_to city_path(city),
|
||||||
class: "btn btn-primary btn-sm gap-2", data: { turbo_frame: "_top" } do %>
|
class: "btn btn-primary btn-sm gap-2", data: { turbo_frame: "_top" } do %>
|
||||||
<%= t("button.view_detail") %>
|
View Details
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<%= f.text_field :query,
|
<%= f.text_field :query,
|
||||||
value: params[:query] ? URI.decode_www_form_component(params[:query]) : nil,
|
value: params[:query] ? URI.decode_www_form_component(params[:query]) : nil,
|
||||||
class: "w-full pl-12 pr-12 py-3 rounded-full bg-base-200/80 backdrop-blur border border-base-300 focus:outline-none focus:ring-2 focus:ring-primary/50 transition",
|
class: "w-full pl-12 pr-12 py-3 rounded-full bg-base-200/80 backdrop-blur border border-base-300 focus:outline-none focus:ring-2 focus:ring-primary/50 transition",
|
||||||
placeholder: t("text.search_cities"),
|
placeholder: "Search cities...",
|
||||||
autocomplete: "off",
|
autocomplete: "off",
|
||||||
data: {
|
data: {
|
||||||
action: "input->search#submit",
|
action: "input->search#submit",
|
||||||
|
@ -16,18 +16,18 @@
|
|||||||
<div class="container mx-auto px-4">
|
<div class="container mx-auto px-4">
|
||||||
<div class="max-w-3xl mx-auto text-center space-y-6">
|
<div class="max-w-3xl mx-auto text-center space-y-6">
|
||||||
<h1 class="text-5xl md:text-6xl font-display font-bold leading-tight">
|
<h1 class="text-5xl md:text-6xl font-display font-bold leading-tight">
|
||||||
<%= t("cities.title") %>
|
Explore Cities
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-xl md:text-2xl text-base-content/70 font-light max-w-2xl mx-auto">
|
<p class="text-xl md:text-2xl text-base-content/70 font-light max-w-2xl mx-auto">
|
||||||
<%= t("arts.subtitle") %>
|
Discover AI-generated weather art from cities around the world
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- 特色图片信息 -->
|
<!-- 特色图片信息 -->
|
||||||
<% if featured_art %>
|
<% if featured_art %>
|
||||||
<div class="inline-block mt-6 px-4 py-2 bg-base-100/80 backdrop-blur-sm rounded-full text-sm">
|
<div class="inline-block mt-6 px-4 py-2 bg-base-100/80 backdrop-blur-sm rounded-full text-sm">
|
||||||
<%= t("text.latest_from") %>
|
Latest from
|
||||||
<span class="font-semibold"><%= featured_art.city.name %></span>,
|
<span class="font-semibold"><%= featured_art.city.name %></span>,
|
||||||
<%= featured_art.city.country.localized_name %>
|
<%= featured_art.city.country.name %>
|
||||||
<span class="mx-2">•</span>
|
<span class="mx-2">•</span>
|
||||||
<%= featured_art.formatted_time(:date) %>
|
<%= featured_art.formatted_time(:date) %>
|
||||||
</div>
|
</div>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= @current_region&.localized_name || t("text.all_regions") %>
|
<%= @current_region&.name || 'All Regions' %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -59,13 +59,13 @@
|
|||||||
<li>
|
<li>
|
||||||
<%= link_to cities_path,
|
<%= link_to cities_path,
|
||||||
class: "#{@current_region ? '' : 'active'}" do %>
|
class: "#{@current_region ? '' : 'active'}" do %>
|
||||||
<%= t("text.all_regions") %>
|
All Regions
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
<div class="divider my-1"></div>
|
<div class="divider my-1"></div>
|
||||||
<% @regions.each do |region| %>
|
<% @regions.each do |region| %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to region.localized_name,
|
<%= link_to region.name,
|
||||||
cities_path(region: region.slug),
|
cities_path(region: region.slug),
|
||||||
class: "#{@current_region == region ? 'active' : ''}" %>
|
class: "#{@current_region == region ? 'active' : ''}" %>
|
||||||
</li>
|
</li>
|
||||||
@ -79,21 +79,21 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 21v-4m0 0V5a2 2 0 012-2h6.5l1 1H21l-3 6 3 6h-8.5l-1-1H5a2 2 0 00-2 2zm9-13.5V9" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 21v-4m0 0V5a2 2 0 012-2h6.5l1 1H21l-3 6 3 6h-8.5l-1-1H5a2 2 0 00-2 2zm9-13.5V9" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= @current_country&.localized_name || t("text.all_countries") %>
|
<%= @current_country&.name || "All Countries" %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52 max-h-80 overflow-y-auto flex-nowrap">
|
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52 max-h-80 overflow-y-auto flex-nowrap">
|
||||||
<li>
|
<li>
|
||||||
<%= link_to "#{t("text.all_in")} #{@current_region.localized_name}",
|
<%= link_to "All in #{@current_region.name}",
|
||||||
cities_path(region: @current_region.slug),
|
cities_path(region: @current_region.slug),
|
||||||
class: "#{@current_country ? '' : 'active'}" %>
|
class: "#{@current_country ? '' : 'active'}" %>
|
||||||
</li>
|
</li>
|
||||||
<div class="divider my-1"></div>
|
<div class="divider my-1"></div>
|
||||||
<% @current_region.countries.order(:name).each do |country| %>
|
<% @current_region.countries.order(:name).each do |country| %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to "#{country&.emoji + " " || ""}#{country.localized_name}",
|
<%= link_to "#{country&.emoji + " " || ""}#{country.name}",
|
||||||
cities_path(region: @current_region.slug, country: country.slug),
|
cities_path(region: @current_region.slug, country: country.slug),
|
||||||
class: "#{@current_country == country ? 'active' : ''}" %>
|
class: "#{@current_country == country ? 'active' : ''}" %>
|
||||||
</li>
|
</li>
|
||||||
@ -106,9 +106,9 @@
|
|||||||
<div class="text-sm text-base-content/70 hidden">
|
<div class="text-sm text-base-content/70 hidden">
|
||||||
<%= @cities.count %> <%= 'city'.pluralize(@cities.count) %>
|
<%= @cities.count %> <%= 'city'.pluralize(@cities.count) %>
|
||||||
<% if @current_country %>
|
<% if @current_country %>
|
||||||
in <%= @current_country.localized_name %>
|
in <%= @current_country.name %>
|
||||||
<% elsif @current_region %>
|
<% elsif @current_region %>
|
||||||
in <%= @current_region.localized_name %>
|
in <%= @current_region.name %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= t("button.back_to_cities") %>
|
Back to Cities
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-actions justify-end mt-4">
|
<div class="card-actions justify-end mt-4">
|
||||||
<%= link_to t("button.view_detail"), city_weather_art_path(art.city, art),
|
<%= link_to "View Details", city_weather_art_path(art.city, art),
|
||||||
class: "btn btn-primary btn-outline" %>
|
class: "btn btn-primary btn-outline" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<section class="h-screen-90 relative overflow-hidden">
|
<section class="h-screen-90 relative overflow-hidden">
|
||||||
<% if @latest_arts.first&.image&.attached? %>
|
<% if @latest_arts.first&.image&.attached? %>
|
||||||
<div class="absolute inset-0">
|
<div class="absolute inset-0">
|
||||||
<%= image_tag @latest_arts&.first&.webp_image&.processed, class: "w-full h-full object-cover" %>
|
<%= image_tag @latest_arts.first.webp_image.processed, class: "w-full h-full object-cover" %>
|
||||||
<div class="absolute inset-0 bg-gradient-to-r from-base-100/90 to-base-100/50"></div>
|
<div class="absolute inset-0 bg-gradient-to-r from-base-100/90 to-base-100/50"></div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -11,12 +11,13 @@
|
|||||||
<div class="container mx-auto px-4 h-full flex items-center relative">
|
<div class="container mx-auto px-4 h-full flex items-center relative">
|
||||||
<div class="max-w-2xl space-y-6">
|
<div class="max-w-2xl space-y-6">
|
||||||
<h1 class="text-5xl md:text-6xl font-display font-bold leading-tight">
|
<h1 class="text-5xl md:text-6xl font-display font-bold leading-tight">
|
||||||
<%= t("home.headline_html") %>
|
Where Weather Meets<br>Artificial Intelligence
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-xl text-base-content/70 font-sans">
|
<p class="text-xl text-base-content/70 font-sans">
|
||||||
<%= t("home.subtitle") %>
|
Experience weather through the lens of AI-generated art,
|
||||||
|
bringing a new perspective to daily meteorological phenomena.
|
||||||
</p>
|
</p>
|
||||||
<%= link_to t("button.explore_cities"), cities_path,
|
<%= link_to "Explore Cities", cities_path,
|
||||||
class: "btn btn-primary btn-lg mt-8 font-sans" %>
|
class: "btn btn-primary btn-lg mt-8 font-sans" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -24,9 +25,9 @@
|
|||||||
|
|
||||||
<!-- 最新天气艺术 -->
|
<!-- 最新天气艺术 -->
|
||||||
<section class="container mx-auto px-4 py-16 space-y-12">
|
<section class="container mx-auto px-4 py-16 space-y-12">
|
||||||
<h2 class="text-3xl font-display font-bold text-center"><%= t("title.latest_weather_art") %></h2>
|
<h2 class="text-3xl font-display font-bold text-center">Latest Weather Art</h2>
|
||||||
<%= render 'home/arts', arts: @latest_arts %>
|
<%= render 'home/arts', arts: @latest_arts %>
|
||||||
<h2 class="text-3xl font-display font-bold text-center"><%= t("title.popular_weather_art") %></h2>
|
<h2 class="text-3xl font-display font-bold text-center">Popular Weather Art</h2>
|
||||||
<%= render 'home/arts', arts: @popular_arts %>
|
<%= render 'home/arts', arts: @popular_arts %>
|
||||||
<!-- <h2 class="text-3xl font-display font-bold text-center">Random Weather Art</h2>-->
|
<!-- <h2 class="text-3xl font-display font-bold text-center">Random Weather Art</h2>-->
|
||||||
<%#= render 'home/arts', arts: @random_arts %>
|
<%#= render 'home/arts', arts: @random_arts %>
|
||||||
@ -34,7 +35,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-center mt-12 mb-12">
|
<div class="text-center mt-12 mb-12">
|
||||||
<%= link_to arts_path, class: "btn btn-primary btn-lg gap-2" do %>
|
<%= link_to arts_path, class: "btn btn-primary btn-lg gap-2" do %>
|
||||||
<%= t("button.view_all_weather_arts") %>
|
View All Weather Arts
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -1,18 +1,6 @@
|
|||||||
<!-- 页脚 -->
|
<!-- 页脚 -->
|
||||||
<footer class="footer footer-center p-8 bg-base-200 text-base-content">
|
<footer class="footer footer-center p-8 bg-base-200 text-base-content">
|
||||||
<div class="container mx-auto flex flex-col gap-4">
|
<div class="container mx-auto flex flex-col gap-2">
|
||||||
<!-- 第一行:功能按钮 -->
|
|
||||||
<div class="flex items-center justify-center space-x-4">
|
|
||||||
<%= link_to rss_feed_path(format: :rss), class: "btn btn-ghost btn-sm", title: "RSS Feed" do %>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z" />
|
|
||||||
</svg>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= render 'shared/language_switcher' %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 第二行:统计信息 -->
|
|
||||||
<div id="busuanzi_container" class="text-xs opacity-70">
|
<div id="busuanzi_container" class="text-xs opacity-70">
|
||||||
<div class="space-x-2">
|
<div class="space-x-2">
|
||||||
<span>Page: </span>
|
<span>Page: </span>
|
||||||
@ -22,14 +10,13 @@
|
|||||||
<span>PV <span id="busuanzi_site_pv"></span></span>
|
<span>PV <span id="busuanzi_site_pv"></span></span>
|
||||||
<span>UV <span id="busuanzi_site_uv"></span></span>
|
<span>UV <span id="busuanzi_site_uv"></span></span>
|
||||||
<span data-controller="page-load-time">
|
<span data-controller="page-load-time">
|
||||||
Load Time: <span data-page-load-time-target="timer">x</span> ms
|
Page Load Time: <span data-page-load-time-target="timer">x</span> ms
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 第三行:版权信息 -->
|
<p class="font-display opacity-80">
|
||||||
<p class="font-display opacity-80 text-sm">
|
Copyright © 2024 - All rights reserved by AI Weather Art
|
||||||
Copyright © <%= Time.current.year %> - All rights reserved by AI Weather Art
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
@ -3,14 +3,14 @@
|
|||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<%= link_to root_path, class: "text-xl md:text-2xl font-display font-bold hover:text-primary transition-colors" do %>
|
<%= link_to root_path, class: "text-xl md:text-2xl font-display font-bold hover:text-primary transition-colors" do %>
|
||||||
<%= t('brand.name') %>
|
Today AI Weather
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Desktop Menu -->
|
<!-- Desktop Menu -->
|
||||||
<div class="hidden md:flex flex-none gap-2 items-center">
|
<div class="hidden md:flex flex-none gap-2 items-center">
|
||||||
<%= link_to t("title.cities"), cities_path, class: "btn btn-ghost btn-sm font-sans" %>
|
<%= link_to "Cities", cities_path, class: "btn btn-ghost btn-sm font-sans" %>
|
||||||
<%= link_to t("title.arts"), arts_path, class: "btn btn-ghost btn-sm font-sans" %>
|
<%= link_to "Arts", arts_path, class: "btn btn-ghost btn-sm font-sans" %>
|
||||||
|
|
||||||
<% if user_signed_in? %>
|
<% if user_signed_in? %>
|
||||||
<div class="dropdown dropdown-end">
|
<div class="dropdown dropdown-end">
|
||||||
@ -27,14 +27,12 @@
|
|||||||
</label>
|
</label>
|
||||||
<%= render 'layouts/user_menu' %>
|
<%= render 'layouts/user_menu' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render 'shared/language_switcher' %>
|
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= link_to new_user_session_path, class: "btn btn-primary btn-sm" do %>
|
<%= link_to new_user_session_path, class: "btn btn-primary btn-sm" do %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><%= t("title.sign_in") %></span>
|
<span>Sign in</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@ -48,8 +46,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
<ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
|
<ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
|
||||||
<li><%= link_to t("title.cities"), cities_path %></li>
|
<li><%= link_to "Cities", cities_path %></li>
|
||||||
<li><%= link_to t("title.arts"), arts_path %></li>
|
<li><%= link_to "Arts", arts_path %></li>
|
||||||
<div class="divider my-1"></div>
|
<div class="divider my-1"></div>
|
||||||
<% if user_signed_in? %>
|
<% if user_signed_in? %>
|
||||||
<li>
|
<li>
|
||||||
@ -58,7 +56,7 @@
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= t("title.settings") %>
|
Settings
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -69,7 +67,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><% t("title.sign_out") %></span>
|
<span>Sign out</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
@ -79,7 +77,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= t("title.sign_in") %>
|
Sign in
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" />
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><%= t("title.settings") %></span>
|
<span>Settings</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V19.5a2.25 2.25 0 002.25 2.25h.75m0-3H21m-3.75 3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V19.5a2.25 2.25 0 002.25 2.25h.75m0-3H21m-3.75 3h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008zm0-6h.008v.008h-.008v-.008z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><%= t("title.admin_dashboard") %></span>
|
<span>Admin Dashboard</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75" />
|
||||||
</svg>
|
</svg>
|
||||||
<span><%= t("title.sign_out") %></span>
|
<span>Sign out</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="<%= I18n.locale %>">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title><%= content_for(:title) || "Today Ai Weather" %></title>
|
<title><%= content_for(:title) || "Today Ai Weather" %></title>
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
@ -11,14 +11,11 @@
|
|||||||
og: {
|
og: {
|
||||||
site_name: 'TodayAIWeather',
|
site_name: 'TodayAIWeather',
|
||||||
type: 'website',
|
type: 'website',
|
||||||
keywords: "ai, ai web, ai art, ai weather, weather art, AI visualization, today ai weather",
|
|
||||||
url: request.original_url
|
url: request.original_url
|
||||||
},
|
},
|
||||||
alternate: {
|
alternate: {
|
||||||
"en" => url_for(locale: 'en'),
|
|
||||||
"zh-CN" => url_for(locale: 'zh-CN'),
|
"zh-CN" => url_for(locale: 'zh-CN'),
|
||||||
"ja" => url_for(locale: 'ja'),
|
"en" => url_for(locale: 'en')
|
||||||
"ko" => url_for(locale: 'ko')
|
|
||||||
}
|
}
|
||||||
) %>
|
) %>
|
||||||
<%= csrf_meta_tags %>
|
<%= csrf_meta_tags %>
|
||||||
@ -36,8 +33,6 @@
|
|||||||
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
||||||
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
|
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
|
||||||
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
||||||
<%= auto_discovery_link_tag :rss, rss_feed_url(format: :rss), title: 'RSS Feed' %>
|
|
||||||
|
|
||||||
<script defer data-domain="todayaiweather.com" src="https://plausible.frytea.com/js/script.js"></script>
|
<script defer data-domain="todayaiweather.com" src="https://plausible.frytea.com/js/script.js"></script>
|
||||||
|
|
||||||
<script defer src="https://busuanzi.frytea.com/js"></script>
|
<script defer src="https://busuanzi.frytea.com/js"></script>
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
# app/views/rss/feed.rss.builder
|
|
||||||
xml.instruct! :xml, version: "1.0"
|
|
||||||
xml.rss version: "2.0",
|
|
||||||
"xmlns:atom" => "http://www.w3.org/2005/Atom" do
|
|
||||||
xml.channel do
|
|
||||||
xml.title "Today AI Weather Art"
|
|
||||||
xml.description "Daily AI-generated weather art and forecasts"
|
|
||||||
xml.link root_url
|
|
||||||
xml.language "en"
|
|
||||||
xml.atom :link, href: rss_feed_url(format: :rss), rel: "self", type: "application/rss+xml"
|
|
||||||
|
|
||||||
@weather_arts.each do |art|
|
|
||||||
xml.item do
|
|
||||||
xml.title "#{art.city.full_name} Weather Art"
|
|
||||||
xml.description art.description
|
|
||||||
xml.pubDate art.created_at.to_fs(:rfc822)
|
|
||||||
xml.link city_weather_art_url(art.city, art)
|
|
||||||
xml.guid city_weather_art_url(art.city, art)
|
|
||||||
# 如果有图片,添加图片链接
|
|
||||||
xml.enclosure url: rails_blob_url(art.webp_image.processed), type: "image/jpeg" if art.image.attached?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,17 +0,0 @@
|
|||||||
<%# app/views/shared/_language_switcher.html.erb %>
|
|
||||||
<div class="dropdown dropdown-top">
|
|
||||||
<label tabindex="0" class="btn btn-ghost btn-sm">
|
|
||||||
<%= t("language.#{I18n.locale}") %>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor">
|
|
||||||
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
|
||||||
</svg>
|
|
||||||
</label>
|
|
||||||
<ul tabindex="0" class="dropdown-content menu p-2 max-h-80 overflow-y-auto flex-nowrap shadow bg-base-100 rounded-box w-32">
|
|
||||||
<% I18n.available_locales.each do |locale| %>
|
|
||||||
<%= link_to url_for(locale: locale),
|
|
||||||
class: "px-4 py-2 hover:bg-base-200 rounded-lg #{I18n.locale == locale ? 'bg-base-200' : ''}" do %>
|
|
||||||
<%= t("language.#{locale}") %>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
@ -78,12 +78,9 @@
|
|||||||
|
|
||||||
<!-- 结果统计 -->
|
<!-- 结果统计 -->
|
||||||
<div class="text-sm text-base-content/60 font-light">
|
<div class="text-sm text-base-content/60 font-light">
|
||||||
<%= t('pagination.showing_items',
|
Showing <%= collection.offset_value + 1 %> to
|
||||||
from: collection.offset_value + 1,
|
<%= collection.last_page? ? collection.total_count : collection.offset_value + collection.limit_value %>
|
||||||
to: collection.last_page? ? collection.total_count : collection.offset_value + collection.limit_value,
|
of <%= collection.total_count %> <%= collection_name || 'items' %>
|
||||||
total: collection.total_count,
|
|
||||||
items: t("pagination.items.#{collection_name}", default: t('pagination.items.default'))
|
|
||||||
) %>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
@ -1,43 +0,0 @@
|
|||||||
<%# app/views/sitemaps/index.html.erb %>
|
|
||||||
<div class="container mx-auto px-4 py-8">
|
|
||||||
<div class="max-w-4xl mx-auto">
|
|
||||||
<h1 class="text-3xl font-bold mb-6">Sitemaps Index</h1>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-lg shadow overflow-hidden">
|
|
||||||
<div class="overflow-x-auto">
|
|
||||||
<table class="table w-full">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Filename</th>
|
|
||||||
<th>Last Modified</th>
|
|
||||||
<th>Size</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<% @sitemaps.each do |sitemap| %>
|
|
||||||
<tr class="hover">
|
|
||||||
<td><%= sitemap[:key] %></td>
|
|
||||||
<td><%= sitemap[:last_modified].strftime("%Y-%m-%d %H:%M:%S") %></td>
|
|
||||||
<td><%= number_to_human_size(sitemap[:size]) %></td>
|
|
||||||
<td>
|
|
||||||
<%= link_to "View", sitemap[:url],
|
|
||||||
class: "btn btn-sm btn-primary",
|
|
||||||
target: "_blank" %>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 bg-base-200 p-4 rounded-lg">
|
|
||||||
<h2 class="text-xl font-semibold mb-2">For Search Engines</h2>
|
|
||||||
<p class="mb-2">Sitemap Index URL:</p>
|
|
||||||
<code class="block bg-base-300 p-2 rounded">
|
|
||||||
<%= sitemaps_url(format: :xml) %>
|
|
||||||
</code>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<%= link_to city_weather_art_path(weather_art.city, weather_art),
|
<%= link_to city_weather_art_path(weather_art.city, weather_art),
|
||||||
class: "btn btn-primary btn-block" do %>
|
class: "btn btn-primary btn-block" do %>
|
||||||
<%= t("button.view_detail") %>
|
View Details
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
<%# Partial _weather_stats.html.erb %>
|
<%# Partial _weather_stats.html.erb %>
|
||||||
|
|
||||||
<div class="stat bg-gradient-to-br from-primary/10 to-primary/20 hover:from-primary hover:to-primary/30 p-4 rounded-lg">
|
<div class="stat bg-gradient-to-br from-primary/10 to-primary/20 hover:from-primary hover:to-primary/30 p-4 rounded-lg">
|
||||||
<div class="stat-title font-medium text-base"><%= t("card.temperature") %></div>
|
<div class="stat-title font-medium text-base">Temperature</div>
|
||||||
<div class="stat-value text-3xl"><%= weather_art.temperature %>°C</div>
|
<div class="stat-value text-3xl"><%= weather_art.temperature %>°C</div>
|
||||||
<div class="stat-desc"><%= t("card.feel_like") %> <%= weather_art.feeling_temp %>°C</div>
|
<div class="stat-desc">Feels like <%= weather_art.feeling_temp %>°C</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat bg-gradient-to-br from-secondary/10 to-secondary/20 hover:from-secondary hover:to-secondary/30 p-4 rounded-lg">
|
<div class="stat bg-gradient-to-br from-secondary/10 to-secondary/20 hover:from-secondary hover:to-secondary/30 p-4 rounded-lg">
|
||||||
<div class="stat-title font-medium text-base"><%= t("card.wind") %></div>
|
<div class="stat-title font-medium text-base">Wind</div>
|
||||||
<div class="stat-value text-3xl"><%= weather_art.wind_scale %></div>
|
<div class="stat-value text-3xl"><%= weather_art.wind_scale %></div>
|
||||||
<div class="stat-desc"><%= weather_art.wind_speed %> km/h</div>
|
<div class="stat-desc"><%= weather_art.wind_speed %> km/h</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat bg-base-300 hover:bg-base-400 p-4 rounded-lg">
|
<div class="stat bg-base-300 hover:bg-base-400 p-4 rounded-lg">
|
||||||
<div class="stat-title font-medium text-base"><%= t("card.humidity") %></div>
|
<div class="stat-title font-medium text-base">Humidity</div>
|
||||||
<div class="stat-value text-3xl"><%= weather_art.humidity %>%</div>
|
<div class="stat-value text-3xl"><%= weather_art.humidity %>%</div>
|
||||||
<div class="stat-desc"><%= t("card.relative_humidity") %></div>
|
<div class="stat-desc">Relative humidity</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat bg-base-300 hover:bg-base-400 p-4 rounded-lg">
|
<div class="stat bg-base-300 hover:bg-base-400 p-4 rounded-lg">
|
||||||
<div class="stat-title font-medium text-base"><%= t("card.visibility") %></div>
|
<div class="stat-title font-medium text-base">Visibility</div>
|
||||||
<div class="stat-value text-3xl"><%= weather_art.visibility %> km</div>
|
<div class="stat-value text-3xl"><%= weather_art.visibility %> km</div>
|
||||||
<div class="stat-desc"><%= t("card.clear_view_distance") %></div>
|
<div class="stat-desc">Clear view distance</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat bg-accent/10 hover:bg-accent p-4 rounded-lg">
|
<div class="stat bg-accent/10 hover:bg-accent p-4 rounded-lg">
|
||||||
<div class="stat-title font-medium text-base"><%= t("card.pressure") %></div>
|
<div class="stat-title font-medium text-base">Pressure</div>
|
||||||
<div class="stat-value text-3xl"><%= weather_art.pressure %> hPa</div>
|
<div class="stat-value text-3xl"><%= weather_art.pressure %> hPa</div>
|
||||||
<div class="stat-desc"><%= t("card.atmospheric_pressure") %></div>
|
<div class="stat-desc">Atmospheric pressure</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat bg-base-200 hover:bg-base-100 p-4 rounded-lg">
|
<div class="stat bg-base-200 hover:bg-base-100 p-4 rounded-lg">
|
||||||
<div class="stat-title font-medium text-base"><%= t("card.cloud_cover") %></div>
|
<div class="stat-title font-medium text-base">Cloud Cover</div>
|
||||||
<div class="stat-value text-3xl"><%= weather_art.cloud %>%</div>
|
<div class="stat-value text-3xl"><%= weather_art.cloud %>%</div>
|
||||||
<div class="stat-desc"><%= t("card.sky_coverage") %></div>
|
<div class="stat-desc">Sky coverage</div>
|
||||||
</div>
|
</div>
|
@ -4,46 +4,29 @@
|
|||||||
</script>
|
</script>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="min-h-screen bg-base-100">
|
<div class="relative min-h-screen bg-white"> <!-- 使用更明快的背景颜色 -->
|
||||||
<div class="container mx-auto px-4 md:px-6 pt-8 pb-16">
|
<div class="container mx-auto px-4 pt-12 pb-16">
|
||||||
<!-- 返回按钮 -->
|
<div class="max-w-6xl mx-auto space-y-6">
|
||||||
|
<!-- 返回导航 -->
|
||||||
|
<div class="flex items-center">
|
||||||
<%= link_to city_path(@weather_art.city),
|
<%= link_to city_path(@weather_art.city),
|
||||||
class: "btn btn-ghost btn-md gap-2 bg-base-200 hover:bg-base-300 transition-all duration-300 mb-4" do %>
|
class: "btn btn-ghost btn-md gap-2 bg-base-200 hover:bg-base-300 transition-all duration-300" do %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
<%= "#{t("button.back_to")} #{@weather_art.city.name}" %>
|
Back to <%= @weather_art.city.name %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- 标题区域 -->
|
|
||||||
<div class="max-w-6xl mx-auto mb-8">
|
|
||||||
<h1 class="font-display text-4xl md:text-5xl font-bold text-gradient mb-4">
|
|
||||||
<%= @weather_art.city.full_name %> Weather Art
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-4 mb-6">
|
|
||||||
<div class="badge badge-lg badge-primary">
|
|
||||||
<%= "#{@weather_art&.city&.country&.emoji + " " || ""}#{@city&.country&.localized_name}" %>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-lg badge-secondary">
|
|
||||||
<%= @weather_art&.city&.state&.name %>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-lg badge-ghost">
|
|
||||||
<%= @weather_art.formatted_time(:date) %>
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-lg badge-ghost">
|
|
||||||
<%= @weather_art.formatted_time(:time, true) %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 主要内容区域 -->
|
<!-- 主要内容 -->
|
||||||
<div class="max-w-7xl mx-auto">
|
<div class="card bg-base-100 backdrop-blur-md shadow-lg border border-primary/20 overflow-hidden"> <!-- 调整透明度和阴影 -->
|
||||||
<!-- 艺术图像区域 - 移动端全宽显示 -->
|
<div class="grid lg:grid-cols-2 gap-6 items-center">
|
||||||
|
|
||||||
|
<!-- 图片区域 -->
|
||||||
<% if @weather_art.image.attached? %>
|
<% if @weather_art.image.attached? %>
|
||||||
<div class="md:rounded-xl overflow-hidden mb-8 -mx-4 md:mx-0"> <!-- 负margin实现移动端全宽 -->
|
<figure class="relative lg:h-[30rem] h-auto overflow-hidden rounded-lg"> <!-- 添加圆角 -->
|
||||||
<div class="gallery" data-controller="photo-swipe-lightbox">
|
<div class="gallery" data-controller="photo-swipe-lightbox">
|
||||||
<div data-photo-swipe-lightbox-target="gallery">
|
<div data-photo-swipe-lightbox-target="gallery" class="h-full">
|
||||||
<% watermarked = @weather_art.webp_image.processed %>
|
<% watermarked = @weather_art.webp_image.processed %>
|
||||||
<%= link_to rails_blob_path(watermarked),
|
<%= link_to rails_blob_path(watermarked),
|
||||||
data: {
|
data: {
|
||||||
@ -52,63 +35,74 @@
|
|||||||
pswp_width: 1792,
|
pswp_width: 1792,
|
||||||
pswp_height: 1024
|
pswp_height: 1024
|
||||||
} do %>
|
} do %>
|
||||||
<%= image_tag @weather_art.preview_image(:big).processed,
|
<%= image_tag @weather_art.preview_image(:big).processed, class: "object-cover w-full h-full transition-transform transform hover:scale-105 ease-in-out" %>
|
||||||
class: "w-full h-auto object-cover transition-transform hover:scale-105 duration-300 ease-in-out" %>
|
<%#= image_tag @weather_art.watermarked_variant.processed , class: "object-cover w-full h-full transition-transform transform hover:scale-105 ease-in-out" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</figure>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- 天气信息卡片 -->
|
<!-- 信息区域 -->
|
||||||
<div class="grid md:grid-cols-2 gap-6 mb-8">
|
<div class="card-body p-8 lg:py-10 lg:px-12">
|
||||||
<div class="card bg-base-100 shadow-lg">
|
<div class="prose max-w-none">
|
||||||
<div class="card-body">
|
<h1 class="font-display text-4xl md:text-5xl font-bold text-gradient mb-6">
|
||||||
<h2 class="text-2xl font-semibold mb-4 flex items-center gap-2">
|
<%= @weather_art.city.full_name %> Weather Art
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap gap-4 mb-6">
|
||||||
|
<div class="badge badge-lg badge-primary">
|
||||||
|
<%= @weather_art.formatted_time(:date) %>
|
||||||
|
</div>
|
||||||
|
<div class="badge badge-lg badge-secondary">
|
||||||
|
<%= @weather_art.formatted_time(:time, true) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mb-4">
|
||||||
<%= weather_description_icon(@weather_art.description) %>
|
<%= weather_description_icon(@weather_art.description) %>
|
||||||
<%= @weather_art.description %>
|
<%= @weather_art.description %>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<%= render 'weather_stats', weather_art: @weather_art %>
|
<%= render 'weather_stats', weather_art: @weather_art %> <!-- 使用局部渲染 -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- AI Prompt 卡片 -->
|
<div class="card bg-base-100 backdrop-blur-md shadow-lg border border-primary/20 overflow-hidden"> <!-- 调整透明度和阴影 -->
|
||||||
<div class="card bg-primary/10 shadow-lg">
|
<%= render 'shared/map', city: @weather_art.city %>
|
||||||
<div class="card-body">
|
</div>
|
||||||
|
|
||||||
|
<div class="card bg-base-100 backdrop-blur-md shadow-lg overflow-hidden">
|
||||||
|
<%= render 'shared/auto_ad' %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- AI Prompt -->
|
||||||
|
<div class="bg-primary/10 backdrop-blur-md p-6 rounded-lg border border-primary/20">
|
||||||
<div class="flex items-center gap-3 mb-4">
|
<div class="flex items-center gap-3 mb-4">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||||
</svg>
|
</svg>
|
||||||
<h3 class="font-display font-bold text-lg"><%= t("title.ai_prompt") %></h3>
|
<h3 class="font-display font-bold text-lg">AI Prompt</h3>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-base-content/80 leading-relaxed">
|
<p class="text-base-content/80 leading-relaxed">
|
||||||
<%= @weather_art.prompt %>
|
<%= @weather_art.prompt %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 地图区域 -->
|
|
||||||
<div class="card bg-base-100 shadow-lg mb-8">
|
|
||||||
<%= render 'shared/map', city: @weather_art.city %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 广告区域 -->
|
|
||||||
<div class="card bg-base-100 shadow-lg mb-8">
|
|
||||||
<%= render 'shared/auto_ad' %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 社交分享 -->
|
|
||||||
<%
|
<%
|
||||||
|
# 构建更吸引人的分享标题
|
||||||
share_title = [
|
share_title = [
|
||||||
"🎨 Amazing AI Weather Art: #{@weather_art.city.full_name}",
|
"🎨 Amazing AI Weather Art: #{@weather_art.city.full_name}",
|
||||||
"#{@weather_art.description} at #{@weather_art.temperature}°C",
|
"#{@weather_art.description} at #{@weather_art.temperature}°C",
|
||||||
"#{@weather_art.formatted_time(:all, true)}"
|
"#{@weather_art.formatted_time(:all, true)}"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
|
|
||||||
|
# 构建更有描述性的分享描述
|
||||||
share_description = [
|
share_description = [
|
||||||
"Discover this stunning AI-generated weather art!",
|
"Discover this stunning AI-generated weather art!",
|
||||||
"#{@weather_art.description} in #{@weather_art.city.full_name}.",
|
"#{@weather_art.description} in #{@weather_art.city.full_name}.",
|
||||||
@ -122,6 +116,8 @@
|
|||||||
tags: "AIWeather,Art,AIart,Weather,#{@weather_art.city&.name},#{@weather_art&.city&.country&.name}",
|
tags: "AIWeather,Art,AIart,Weather,#{@weather_art.city&.name},#{@weather_art&.city&.country&.name}",
|
||||||
image: url_for(@weather_art.webp_image.processed)
|
image: url_for(@weather_art.webp_image.processed)
|
||||||
%>
|
%>
|
||||||
</div>
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -5,28 +5,9 @@ class BatchGenerateWeatherArtsWorker
|
|||||||
MAX_DURATION = 5.minutes
|
MAX_DURATION = 5.minutes
|
||||||
SLEEP_DURATION = 10.seconds
|
SLEEP_DURATION = 10.seconds
|
||||||
DAILY_GENERATION_LIMIT = 60 # 每日生成图片上限
|
DAILY_GENERATION_LIMIT = 60 # 每日生成图片上限
|
||||||
PER_RUN_GENERATION_LIMIT = 2 # 每次运行生成图片上限
|
PER_RUN_GENERATION_LIMIT = 3 # 每次运行生成图片上限
|
||||||
|
|
||||||
def perform(*args)
|
def perform(*args)
|
||||||
lock_key = "batch_generate_weather_lock"
|
|
||||||
lock_ttl = 300 # 锁的生存时间,单位为秒
|
|
||||||
|
|
||||||
redis = Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1"))
|
|
||||||
|
|
||||||
if redis.set(lock_key, Time.current.to_s, nx: true, ex: lock_ttl)
|
|
||||||
begin
|
|
||||||
batch_tasks
|
|
||||||
ensure
|
|
||||||
redis.del(lock_key)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Rails.logger.info "Sitemap refresh is already in progress"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def batch_tasks
|
|
||||||
start_time = Time.current
|
start_time = Time.current
|
||||||
remaining_slots = calculate_remaining_slots
|
remaining_slots = calculate_remaining_slots
|
||||||
return if remaining_slots <= 0
|
return if remaining_slots <= 0
|
||||||
@ -57,6 +38,8 @@ class BatchGenerateWeatherArtsWorker
|
|||||||
print_summary(processed_cities, skipped_cities)
|
print_summary(processed_cities, skipped_cities)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def get_recent_cities
|
def get_recent_cities
|
||||||
cutoff_time = Time.current - GENERATION_INTERVAL
|
cutoff_time = Time.current - GENERATION_INTERVAL
|
||||||
City.joins("LEFT JOIN (
|
City.joins("LEFT JOIN (
|
||||||
|
@ -10,14 +10,7 @@ class RefreshSitemapWorker
|
|||||||
|
|
||||||
if redis.set(lock_key, Time.current.to_s, nx: true, ex: lock_ttl)
|
if redis.set(lock_key, Time.current.to_s, nx: true, ex: lock_ttl)
|
||||||
begin
|
begin
|
||||||
setup_sitemap_config
|
generate_sitemap
|
||||||
# 生成默认的不带语言前缀的 sitemap
|
|
||||||
generate_sitemap(nil)
|
|
||||||
|
|
||||||
# 为每个可用语言生成带前缀的 sitemap
|
|
||||||
I18n.available_locales.each do |locale|
|
|
||||||
generate_sitemap(locale)
|
|
||||||
end
|
|
||||||
ensure
|
ensure
|
||||||
redis.del(lock_key)
|
redis.del(lock_key)
|
||||||
end
|
end
|
||||||
@ -28,102 +21,58 @@ class RefreshSitemapWorker
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def setup_sitemap_config
|
def generate_sitemap
|
||||||
@host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000"
|
host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000"
|
||||||
Rails.application.routes.default_url_options[:host] = @host
|
Rails.application.routes.default_url_options[:host] = host
|
||||||
SitemapGenerator::Sitemap.default_host = ENV.fetch("RAILS_SITEMAP_DEFAULT_HOST", @host)
|
SitemapGenerator::Sitemap.default_host = ENV.fetch("RAILS_SITEMAP_DEFAULT_HOST", host)
|
||||||
|
|
||||||
if Rails.env.production?
|
if Rails.env.production?
|
||||||
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
||||||
ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:minio, :bucket)),
|
ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws, :bucket)),
|
||||||
aws_access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :access_key_id)),
|
aws_access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :access_key_id)),
|
||||||
aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :secret_access_key)),
|
aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :secret_access_key)),
|
||||||
aws_region: ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:minio, :region)),
|
aws_region: ENV.fetch("AWS_REGION", "wnam"),
|
||||||
force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio, :force_path_style)),
|
endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws, :endpoint)),
|
||||||
endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:minio, :endpoint)),
|
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
||||||
ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:minio_dev, :bucket)),
|
ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)),
|
||||||
aws_access_key_id: ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :access_key_id)),
|
aws_access_key_id: ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)),
|
||||||
aws_secret_access_key: ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :secret_access_key)),
|
aws_secret_access_key: ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)),
|
||||||
aws_region: ENV.fetch("AWS_DEV_REGION", Rails.application.credentials.dig(:minio_dev, :region)),
|
aws_region: ENV.fetch("AWS_DEV_REGION", "wnam"),
|
||||||
force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio_dev, :force_path_style)),
|
endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)),
|
||||||
endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:minio_dev, :endpoint)),
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/"
|
SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/"
|
||||||
end
|
|
||||||
|
|
||||||
def generate_sitemap(locale = nil)
|
SitemapGenerator::Sitemap.create do
|
||||||
# 设置当前语言环境
|
add root_path, changefreq: "daily", priority: 1.0
|
||||||
I18n.locale = locale || I18n.default_locale
|
add cities_path, changefreq: "daily", priority: 0.9
|
||||||
Rails.application.routes.default_url_options[:locale] = locale
|
add arts_path, changefreq: "daily", priority: 0.9
|
||||||
|
|
||||||
# 设置 sitemap 路径
|
|
||||||
# path_prefix = locale ? "sitemaps/#{locale}/" : "sitemaps/"
|
|
||||||
# SitemapGenerator::Sitemap.sitemaps_path = path_prefix
|
|
||||||
|
|
||||||
filename = locale==nil ? "sitemap" : "sitemap_#{locale}"
|
|
||||||
SitemapGenerator::Sitemap.create(filename: filename) do
|
|
||||||
available_locales = I18n.available_locales
|
|
||||||
|
|
||||||
# 首页
|
|
||||||
add root_path(locale: locale),
|
|
||||||
changefreq: "daily",
|
|
||||||
priority: 1.0,
|
|
||||||
alternate: available_locales.map { |al|
|
|
||||||
{ lang: al, href: root_url(locale: al) }
|
|
||||||
}
|
|
||||||
|
|
||||||
# 城市列表页
|
|
||||||
add cities_path(locale: locale),
|
|
||||||
changefreq: "daily",
|
|
||||||
priority: 0.9,
|
|
||||||
alternate: available_locales.map { |al|
|
|
||||||
{ lang: al, href: cities_url(locale: al) }
|
|
||||||
}
|
|
||||||
|
|
||||||
# 艺术作品列表页
|
|
||||||
add arts_path(locale: locale),
|
|
||||||
changefreq: "daily",
|
|
||||||
priority: 0.9,
|
|
||||||
alternate: available_locales.map { |al|
|
|
||||||
{ lang: al, href: arts_url(locale: al) }
|
|
||||||
}
|
|
||||||
|
|
||||||
# 城市详情页
|
|
||||||
City.find_each do |city|
|
City.find_each do |city|
|
||||||
add city_path(city, locale: locale),
|
add city_path(city),
|
||||||
changefreq: "daily",
|
changefreq: "daily",
|
||||||
priority: 0.8,
|
priority: 0.8,
|
||||||
lastmod: city.updated_at,
|
lastmod: city.updated_at
|
||||||
alternate: available_locales.map { |al|
|
|
||||||
{ lang: al, href: city_url(city, locale: al) }
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# 天气艺术作品页
|
|
||||||
WeatherArt.includes(:city).find_each do |art|
|
WeatherArt.includes(:city).find_each do |art|
|
||||||
if art.image.attached?
|
if art.image.attached?
|
||||||
add city_weather_art_path(art.city, art, locale: locale),
|
add city_weather_art_path(art.city, art),
|
||||||
changefreq: "daily",
|
changefreq: "daily",
|
||||||
priority: 0.7,
|
priority: 0.7,
|
||||||
lastmod: art.updated_at,
|
lastmod: art.updated_at,
|
||||||
images: [ {
|
images: [ {
|
||||||
loc: url_for(art.image),
|
loc: url_for(art.image),
|
||||||
title: "#{art.city.name} Weather Art - #{art.weather_date.strftime('%B %d, %Y')}"
|
title: "#{art.city.name} Weather Art - #{art.weather_date.strftime('%B %d, %Y')}"
|
||||||
} ],
|
} ]
|
||||||
alternate: available_locales.map { |al|
|
|
||||||
{ lang: al, href: city_weather_art_url(art.city, art, locale: al) }
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Rails.logger.info "Generated sitemap for #{locale || 'default'} version"
|
# SitemapGenerator::Sitemap.ping_search_engines if Rails.env.production?
|
||||||
|
Rails.logger.info "Sitemap has been generated and uploaded to S3 successfully"
|
||||||
rescue => e
|
rescue => e
|
||||||
Rails.logger.error "Error generating sitemap for #{locale || 'default'}: #{e.message}"
|
Rails.logger.error "Error refreshing sitemap: #{e.message}"
|
||||||
raise e
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1 +1 @@
|
|||||||
geGCObHW9aRt27AEzTpe7YfR9YNZtC1NVigIGs72aWNrwAkXB1DnXeDZH4OMJTPug+nxO4/5trV/XgwpTHPyqY4t1cbB22oX2aYSUijnJKz4rWaVi8K+OQfInc1pQSro9yTkJrT76a1UCYR27yxhR+l/+CxVb8yNfHMhPOLXpjhJKE6D2bppxkFJ7MTQ6FEAMxtgLLL7aDIMkt+KLhep/dfeKhW0IbZsng7MA5ExL8sd+eM3twRgTr9XIThpJ8v6lgo69fsINvaUxYdgZddqOQ+O7EeYaBGasE/RCR2DULreKwEWLA7fLgPuqrxs4EqGxdiD9LeNKZN40sJw360ZbmLtRUsMn7hEbFRcUfito7aatJ97Q/TStvTkhyWqLgt4JsqlRXHtbFayUiixwQI9WJY0iF1by6lBtoXiA8HsifY2t7muv4OaMI2386LptZ3JiIFaQOfaFJRPHmMSfejj13TaPs6J6gDDvpeLv95lhpwbMu79+zdYGeEtFK71kx2rj266YGhe5dKttcMlcNWke1WwS+GIFArjEO5sR057Z//Q/fP+voW+GL/aVgt4qySnX0Fd9kGh0ZkEtSufP8djFRYM/Yl7NjzM4ofoww3ghtzT0+eahktfpEZMqqBdLtxKf4tQSKO5xMAW2puRThunKiQeLrcuDh0PVkVeDbSwH05Wq0GFHwNft3d62Bg9310PIGHGkKU8eWnLfgn3dNy8HsihXfAgZHLzZSDZfy6htqXYsj9Vk4LeV6c359dI2lPuxb8ka0c1jjnKniPiYpcHqSUd46lPYuKEdP49ezxdOLzrkGRpiGiX4iqIV0bUrB1GLvJ2N2kcblkprvoR4daNqCuLl8noUfEczDl+puDOZg79XMWvp1zJDVyHyPnCG58951VI6GpvNg1LpF7e+EuUIBbyjBXbiyisLCujYy2Xi4RGSF+z++FVRUdXDHHATPcFoGo4kOcPiAncde7D/vM3HlaU+SmFA8vSV1BMVsKBvHyuI0SEyD3JxgCz4/Bv9cMjF4Xhtf8xcz3746jZDnUWWk/wDjUNjCm/btI3TEsQ5e2InPohL2qG/86RPhyRvGFPdDyS1ulscSNrEDZd1yuPQ3ZZaXaHpUD4K/M/nWdWvNbsrQ9J/goob+x3VwqtASdf6a4zIdGlgNhOdsYogSqms/GlKaih1jMCKUXsnY5s5phd87Tw5Gtq6I1QKOa0p2Y6grIr0uOvU/DnxlSvKbm5/tpkF7v05hOCdDRwu4//MYGQPXXCOBF3icgQvmlwBZ7kEWFLmpOFheZ4koqMyxK9GrgQnKwBLpsu0lZG4p8wNSboj5gR9MABVxTYlMVkfIPuNXhU5iWH9g2KpagDgyPcN4PHsJgBXWBBmcUvdO4DMWfH9Z7z6Q1V3TImpUabHtRN5dsL9iAepMlt4xrlqUBdWCjhBYKpX5zYukkCy83ccaKB448KupgnjbW12MFy1pLTLEKhtLV8woX3QAFDQJgFfoH8fD4lx3C25lLvfJPYSlp2xFAcNy+B3mdUF306Iff6XmOCzKlSGI39HWjYA3jpv9031T0YwY6eVKGbQyZMzO7QVeK2lSn+0BA+55INJ5hdP6XlwRlS4lidbPIxUAbMpC3yILMjImc36FvHdomuAAGC1s5naFCFtsl8LpVcdlYsX7Jwf56TV7whchV9+45aStNANyfSH6dhkikquA7i8DBPWnSbgHyomu8ihb4qVSqvtCJcw6Oh7oSz9zrQsNZkmZ+PmsGx37yY80ZZNUbdqqpIuNzTrEU5jgHbCpJqGGbEjjysleB6A3cnVLbBXWHlQubZY/NdpRMCsuThyf4YEhez6OTxd+GEwiCuJse7dSHw3N0xfkFaqad0fR+BJAXIItqIAgYMI/AMyyqrF9lIYk5YTTUSML4Ae0wIEo6tteNNxly/Ofz+DFF/GOCkBxQ88yLBGAq2QG/wkQ9upBRBAZ+dFHeazh9fi1W811EjpDEiqELEqNbxgbV+2cWBbbwVb0917+SVEWDgxer0O+iZUyYjJ9Q8rTtikjWdGuikikz8HnMY6v6kl7TC4bP3gPsyxiLk1JnmTJYGtRrJXQYH3ImlHJKVaS0gtCXZ/rXBcbqGZXpEW4b4ZeVQalMFtQW5BT+rqW7h8f+FkEeV6xKaauOsnPg3fqVfCazRMkuvKatdkn/rF/V2RjydsK3rLfAvLwfz89XRpekzI9PGJJsUKqEFO/VSoEKXedqn/tQkdGWok4VqYoplDWarCbi2sQJQztbwTUCcBT87m+a/oxHyqCrXi5hTpomCHXPrTovilF28s12Zl8ivWpFTebjtxvD/QarAjrWgx42KUuISEAAuUoVxga+ICxd0WoZlSrhcwAntWWvdQkzW41t9IUvzlQX0O9AdZEki81lRRASzEMS28ge7pFv7VkLMIplzY0Ltl/GOq1q+flX1zebEzjQjcq0PiXoIWLAj8PNIhHV/aFwH+jAwcH4pYpO8aQNjhoYBM9KZ1W5ZWSphehdrIddZ5oiZsUs9PMwFza28bAdQvCVarcrF2ofOZCNTLOdL6FntoUPovxemuQERnZ0V5xvVYnLMW8KnHjLYJqPmVMdd38gZe1Qf4JeOz+2WyW/E0SSz2dOt0zKp3klyURwr5+dlTQeGy7D1a4OPxvRIwAAr3cGNpPG2NBzGNeDSargSDrQIRBpp23gaGQpJrfnR95MFvNSx9IG9GkK+ifpwAbtsqEjF2iTYJ9BKSR8VIODLx/VoUD/1euTI--w1b7CHBZ4zFPRjgq--DpdTPDeqnUeN8aZTrINdZg==
|
VUzo0X7975miXMnnoTVXWA5260MuOUxsdsVtC079F3Tquo6Z8Re/EBiIM4hUKHX91D5CsVmPquvwj/AxW9JQxKtSUWYepyildV1B7nYAceqefvrqU+98qYvcKFbwTYXmw4kZD8lOgElcGEUNq6LgCHHXfrtEDHk0Sl6k8Pf5Pgc/SheFZwtK9FE4MGQ6y+hNaeMb7ct2E1zKKqyJKB4Lzp/Fgo7VJuIdEy8Ck23UweaJbSJ08yfS7XrmG1i2ak3fH8FCDxUrofIvyzLw27g8th071JhqiiS9fxJezH+JdaACnKao3bi5fSDL37R0nSBLOYV/Pm63Q3/Nmr560neNgErYtbIZPLETqAZTIK21yvrdaQAXlBEy6St8gdxpQNPELIVJAZ0fAaTfoFdS4/WlMt9oz9Osey9e+eWmDFhpQ/lAj+5oU0t81ioO4S+DBob6rgsAltGK/wa3GdXO2j7ACVJBv0znX3Mran8QiqGYl85+UNxLDH8fIkDyKiug8naWSxQYZIrFOHY5DG4M/IrI5u0zKiks+6kRDN7pRm1WDuW6EpEG5fDv4JRaRp41vS6ezCzXYDPIrGMDtksoJp64dDXdtD6w8NxSSXVhdBzcpZWDXzjpo/rmBM1t8WM46FsAKBrQNTi26B7q1J3rXb3zw2WmzzvVvEuKqVpKbc+d8ND8XUTBYM4d4bPrVSUtC0twMPwAnR0P3PNmV7EHCgfnOuKqDgdqpREpePPzHRpXTS1AxSehLRLO7te8SPN+NpD8Yz+drGmoV1Tx7MuymzK45ILRoBgKaBFkCVZayxhGxDRPDjtYLkQ3ZTA3MUwRhyDVQX47J3wAL5zVRmPiWobXoWEtFalW61bxvD9n9Mr1WP59oYlU4xBxb+0Yu+mvysLBMW9PIAviUknKzmkjrUu4ywqV2QrWlT2tZtM/gWDt5tvLWKDPB89SlzZ55Y6auGFFbYv7HUICo3lk2JFXNfebJF0oXEcmYq3szb80IVIWgp4pdNXOYyh9Pu7g7dZnGTPyiITmhHge/9mj7FoOxOGDsvMedefN86IPN/wCEg/fsJBzhJ0YovrwaTn5+GN9NV92TqwK3LWGkQZ4aZnOAJxIO6b4E3cebPfYjnps39pI0sx9aIN5b0XbjI6d50iLh5jz+2v0B6nDzVEyCiG6zpXXi27ZehO921G0dEQrCuWzVikquUnJbJGVf2tdwKjRDCJWhwPIkhP9YeY6uzQTjGtqDrd12VoEReFMgn1K/PjpJ0s55slbc9+BjOCCuoDTXDy6NC4n3/bsNNKPjt5x0pXkTDh90ug7IBdLweXskhrR86FBwZuf8GGZfz4ZbrVlzhIIPiG/UbkzhaVJDcJrawHj2ipcToXIoDg4Wt3+ZTGC+Kjxk5DzLJWxtIReU34xU9Fv+jndWnu4GJ4+scbwS3mUhBXdcMufeRVh1T45/PSnkwLJRVMv5c5f3CP16PkDORrmuIC+ws3Dz5lCEu1/tuaFabtY3sF6jUY6h/EIUxMllrGwzH9PI/dLu3UizRdtBR85iW03wvAxmLAABmXuRhgyca50uJ65qnFhzLRtQ3JlAIRxZT62YkawqAlUBgstuUgbMLxsCJXLhMmBCO+GuqvkF9DkPVO5dVkNj9V/dnuzqhwzbkDHGd5hwMrXMIYVii5e4q+D5eiTuSfGo/kdHIXfrGrUpUkmbkRrTsnNDUnDzDCk5CWUpuiIj7FSUY8L8Yokli04HRCCn++niPVHZM/RZIZQXAqt61YpfgPr80ut3tmW1aRsLMnkOTjL0KTW3xDv/hxjKuTZj3JqKOFISdI5zihYRwHDBTiClWEnGqkuqSS9fl56A/m17yviId15rzvBIdcLRziQnnpgUacX0lcMdv/A48SCJwAKhTzc2f9Jt8IbFW2OH3+o6QPQC3mysl9ESatJ0saZ7VFQvGSRqG+iRY7OlX2d4LssBke0KBkU4EnZOPXQ24A72m1nooWiz83DBe62d9A/XoKkX9OFh0XQypjTTu0KHqdLsEAqFqISyCz7Vxjd3pdVjaC1lJ/4hqFn3M8RJNTRefXNzgkG1ZpEOA7IGsal+rUaEDSXC8by--JNyAqrs+Fsmpu043--vwHHQzq3PsM/qcTSemHHAg==
|
@ -1,21 +1,19 @@
|
|||||||
if Rails.env.production?
|
if Rails.env.production?
|
||||||
Aws.config.update({
|
Aws.config.update({
|
||||||
region: ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:minio, :region)),
|
region: ENV.fetch("AWS_REGION", "wnam"),
|
||||||
credentials: Aws::Credentials.new(
|
credentials: Aws::Credentials.new(
|
||||||
ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :access_key_id)),
|
ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :access_key_id)),
|
||||||
ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :secret_access_key))
|
ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :secret_access_key))
|
||||||
),
|
),
|
||||||
force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio_dev, :force_path_style)),
|
endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws, :endpoint))
|
||||||
endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:minio, :endpoint))
|
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
Aws.config.update({
|
Aws.config.update({
|
||||||
region: ENV.fetch("AWS_DEV_REGION", Rails.application.credentials.dig(:minio_dev, :region)),
|
region: ENV.fetch("AWS_DEV_REGION", "wnam"),
|
||||||
credentials: Aws::Credentials.new(
|
credentials: Aws::Credentials.new(
|
||||||
ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :access_key_id)),
|
ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)),
|
||||||
ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :secret_access_key))
|
ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key))
|
||||||
),
|
),
|
||||||
force_path_style: ENV.fetch("AWS_DEV_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio_dev, :force_path_style)),
|
endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint))
|
||||||
endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:minio_dev, :endpoint))
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
# config/initializers/locale.rb
|
|
||||||
require "i18n/backend/fallbacks"
|
|
||||||
|
|
||||||
# Where the I18n library should search for translation files
|
|
||||||
I18n.load_path += Dir[Rails.root.join("config", "locales", "*.{rb,yml}")]
|
|
||||||
|
|
||||||
# Permitted locales available for the application
|
|
||||||
I18n.available_locales = [ :en, :"zh-CN", :ja, :ko, :"pt-BR", :hr, :fa, :de, :es, :fr, :it, :tr, :ru, :uk, :pl, :bn, :hi, :ur, :ar ]
|
|
||||||
|
|
||||||
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
|
||||||
# I18n::Backend::Simple.include I18n::Backend::Fallbacks
|
|
||||||
# I18n.fallbacks[:en]
|
|
||||||
I18n.fallbacks = I18n::Locale::Fallbacks.new(
|
|
||||||
en: [ :en ],
|
|
||||||
'zh-CN': [ :zh, :zh_cn, :en ]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set default locale to something other than :en
|
|
||||||
I18n.default_locale = :en
|
|
@ -1,67 +0,0 @@
|
|||||||
ar:
|
|
||||||
hello: "مرحباً بالعالم"
|
|
||||||
brand:
|
|
||||||
name: "الطقس اليوم بالذكاء الاصطناعي"
|
|
||||||
title:
|
|
||||||
cities: "المدن"
|
|
||||||
arts: "الفنون"
|
|
||||||
sign_in: "تسجيل الدخول"
|
|
||||||
sign_out: "تسجيل الخروج"
|
|
||||||
settings: "الإعدادات"
|
|
||||||
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:
|
|
||||||
title: "معرض فنون الطقس"
|
|
||||||
subtitle: "اكتشف فن الطقس المُنشأ بالذكاء الاصطناعي من مدن حول العالم"
|
|
||||||
home:
|
|
||||||
headline_html: حيث يلتقي الطقس<br>بالذكاء الاصطناعي
|
|
||||||
subtitle:
|
|
||||||
اختبر الطقس من خلال عدسة الفن المُنشأ بالذكاء الاصطناعي،
|
|
||||||
مما يجلب منظوراً جديداً للظواهر الجوية اليومية.
|
|
||||||
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: "عرض %{from} إلى %{to} من %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "سجلات الطقس"
|
|
||||||
default: "العناصر"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%B %d, %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
bn:
|
|
||||||
hello: "ওহে বিশ্ব"
|
|
||||||
brand:
|
|
||||||
name: "টুডে এআই ওয়েদার"
|
|
||||||
title:
|
|
||||||
cities: "শহরগুলি"
|
|
||||||
arts: "শিল্প"
|
|
||||||
sign_in: "সাইন ইন"
|
|
||||||
sign_out: "সাইন আউট"
|
|
||||||
settings: "সেটিংস"
|
|
||||||
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:
|
|
||||||
title: "আবহাওয়া শিল্প গ্যালারি"
|
|
||||||
subtitle: "বিশ্বজুড়ে শহরগুলি থেকে এআই-জেনারেটেড আবহাওয়া শিল্প আবিষ্কার করুন"
|
|
||||||
home:
|
|
||||||
headline_html: যেখানে আবহাওয়া মিলিত হয়<br>কৃত্রিম বুদ্ধিমত্তার সাথে
|
|
||||||
subtitle:
|
|
||||||
এআই-জেনারেটেড শিল্পের মাধ্যমে আবহাওয়া অনুভব করুন,
|
|
||||||
দৈনিক আবহাওয়া ঘটনার একটি নতুন দৃষ্টিভঙ্গি আনয়ন করে।
|
|
||||||
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}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%B %d, %Y"
|
|
55
config/locales/countries.en.yml
Normal file
55
config/locales/countries.en.yml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
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'
|
55
config/locales/countries.zh-CN.yml
Normal file
55
config/locales/countries.zh-CN.yml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
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: '澳大利亚'
|
@ -1,67 +0,0 @@
|
|||||||
de:
|
|
||||||
hello: "Hallo Welt"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Städte"
|
|
||||||
arts: "Kunst"
|
|
||||||
sign_in: "Anmelden"
|
|
||||||
sign_out: "Abmelden"
|
|
||||||
settings: "Einstellungen"
|
|
||||||
admin_dashboard: "Admin-Dashboard"
|
|
||||||
latest_weather_art: "Neueste Wetterkunst"
|
|
||||||
popular_weather_art: "Beliebte Wetterkunst"
|
|
||||||
ai_prompt: "KI-Prompt"
|
|
||||||
text:
|
|
||||||
latest_from: "Neuestes von"
|
|
||||||
search_cities: "Städte suchen..."
|
|
||||||
all_regions: "Alle Regionen"
|
|
||||||
all_countries: "Alle Länder"
|
|
||||||
all_in: "Alles in"
|
|
||||||
showing: "Zeigt"
|
|
||||||
weather_arts: "Wetterkunst"
|
|
||||||
newest_first: "Neueste zuerst"
|
|
||||||
oldest_first: "Älteste zuerst"
|
|
||||||
cities:
|
|
||||||
title: "Städte erkunden"
|
|
||||||
arts:
|
|
||||||
title: "Wetterkunst-Galerie"
|
|
||||||
subtitle: "Entdecken Sie KI-generierte Wetterkunst aus Städten auf der ganzen Welt"
|
|
||||||
home:
|
|
||||||
headline_html: Wo Wetter auf<br>Künstliche Intelligenz trifft
|
|
||||||
subtitle:
|
|
||||||
Erleben Sie Wetter durch die Linse KI-generierter Kunst,
|
|
||||||
die eine neue Perspektive auf tägliche meteorologische Phänomene bietet.
|
|
||||||
button:
|
|
||||||
explore_cities: "Städte erkunden"
|
|
||||||
view_detail: "Details anzeigen"
|
|
||||||
view_all_weather_arts: "Alle Wetterkunst anzeigen"
|
|
||||||
back_to_cities: "Zurück zu Städten"
|
|
||||||
back_to: "Zurück zu"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatur"
|
|
||||||
wind: "Wind"
|
|
||||||
humidity: "Luftfeuchtigkeit"
|
|
||||||
visibility: "Sichtweite"
|
|
||||||
pressure: "Luftdruck"
|
|
||||||
cloud_cover: "Bewölkung"
|
|
||||||
feel_like: "Gefühlt wie"
|
|
||||||
relative_humidity: "Relative Luftfeuchtigkeit"
|
|
||||||
clear_view_distance: "Klare Sichtweite"
|
|
||||||
atmospheric_pressure: "Atmosphärischer Druck"
|
|
||||||
sky_coverage: "Himmelsbedeckung"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Zeigt %{from} bis %{to} von %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "Wetteraufzeichnungen"
|
|
||||||
default: "Einträge"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%d. %b"
|
|
||||||
long: "%d. %B %Y"
|
|
@ -28,90 +28,4 @@
|
|||||||
# enabled: "ON"
|
# enabled: "ON"
|
||||||
|
|
||||||
en:
|
en:
|
||||||
language:
|
|
||||||
en: "English"
|
|
||||||
zh-CN: "简体中文"
|
|
||||||
ja: "日本語"
|
|
||||||
ko: "한국어" # 韩语
|
|
||||||
pt-BR: "Português (Brasil)" # 巴西葡萄牙语
|
|
||||||
pt: "Português" # 葡萄牙语
|
|
||||||
hr: "Hrvatski" # 克罗地亚语
|
|
||||||
fa: "فارسی" # 波斯语(法尔西语)
|
|
||||||
de: "Deutsch" # 德语
|
|
||||||
es: "Español" # 西班牙语
|
|
||||||
fr: "Français" # 法语
|
|
||||||
it: "Italiano" # 意大利语
|
|
||||||
tr: "Türkçe" # 土耳其语
|
|
||||||
ru: "Русский" # 俄语
|
|
||||||
uk: "Українська" # 乌克兰语
|
|
||||||
pl: "Polski" # 波兰语
|
|
||||||
bn: "বাংলা" # 孟加拉
|
|
||||||
hi: "हिंदी" # 印地语
|
|
||||||
ur: " اردو" # 乌尔都语
|
|
||||||
ar: "العربية" # 阿拉伯
|
|
||||||
hello: "Hello world"
|
hello: "Hello world"
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Cities"
|
|
||||||
arts: "Arts"
|
|
||||||
sign_in: "Sign in"
|
|
||||||
sign_out: "Sign out"
|
|
||||||
settings: "Settings"
|
|
||||||
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:
|
|
||||||
title: "Weather Arts Gallery"
|
|
||||||
subtitle: "Discover AI-generated weather art from cities around the world"
|
|
||||||
home:
|
|
||||||
headline_html: Where Weather Meets<br>Artificial Intelligence
|
|
||||||
subtitle:
|
|
||||||
Experience weather through the lens of AI-generated art,
|
|
||||||
bringing a new perspective to daily meteorological phenomena.
|
|
||||||
button:
|
|
||||||
explore_cities: "Explore Cities"
|
|
||||||
view_detail: "View Details"
|
|
||||||
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:
|
|
||||||
weather: "weather records"
|
|
||||||
default: "items"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%B %d, %Y"
|
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
es:
|
|
||||||
hello: "Hola mundo"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Ciudades"
|
|
||||||
arts: "Arte"
|
|
||||||
sign_in: "Iniciar sesión"
|
|
||||||
sign_out: "Cerrar sesión"
|
|
||||||
settings: "Configuración"
|
|
||||||
admin_dashboard: "Panel de administración"
|
|
||||||
latest_weather_art: "Último arte del tiempo"
|
|
||||||
popular_weather_art: "Arte del tiempo popular"
|
|
||||||
ai_prompt: "Prompt de IA"
|
|
||||||
text:
|
|
||||||
latest_from: "Lo último de"
|
|
||||||
search_cities: "Buscar ciudades..."
|
|
||||||
all_regions: "Todas las regiones"
|
|
||||||
all_countries: "Todos los países"
|
|
||||||
all_in: "Todo en"
|
|
||||||
showing: "Mostrando"
|
|
||||||
weather_arts: "Arte del tiempo"
|
|
||||||
newest_first: "Más recientes primero"
|
|
||||||
oldest_first: "Más antiguos primero"
|
|
||||||
cities:
|
|
||||||
title: "Explorar ciudades"
|
|
||||||
arts:
|
|
||||||
title: "Galería de arte del tiempo"
|
|
||||||
subtitle: "Descubre arte generado por IA del tiempo de ciudades de todo el mundo"
|
|
||||||
home:
|
|
||||||
headline_html: Donde el tiempo se encuentra<br>con la Inteligencia Artificial
|
|
||||||
subtitle:
|
|
||||||
Experimenta el tiempo a través del lente del arte generado por IA,
|
|
||||||
brindando una nueva perspectiva a los fenómenos meteorológicos diarios.
|
|
||||||
button:
|
|
||||||
explore_cities: "Explorar ciudades"
|
|
||||||
view_detail: "Ver detalles"
|
|
||||||
view_all_weather_arts: "Ver todo el arte del tiempo"
|
|
||||||
back_to_cities: "Volver a ciudades"
|
|
||||||
back_to: "Volver a"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatura"
|
|
||||||
wind: "Viento"
|
|
||||||
humidity: "Humedad"
|
|
||||||
visibility: "Visibilidad"
|
|
||||||
pressure: "Presión"
|
|
||||||
cloud_cover: "Cobertura de nubes"
|
|
||||||
feel_like: "Sensación térmica"
|
|
||||||
relative_humidity: "Humedad relativa"
|
|
||||||
clear_view_distance: "Distancia de visibilidad clara"
|
|
||||||
atmospheric_pressure: "Presión atmosférica"
|
|
||||||
sky_coverage: "Cobertura del cielo"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Mostrando %{from} a %{to} de %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "registros meteorológicos"
|
|
||||||
default: "elementos"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d de %B de %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
fa:
|
|
||||||
hello: "سلام دنیا"
|
|
||||||
brand:
|
|
||||||
name: "هوای هوش مصنوعی امروز"
|
|
||||||
title:
|
|
||||||
cities: "شهرها"
|
|
||||||
arts: "هنرها"
|
|
||||||
sign_in: "ورود"
|
|
||||||
sign_out: "خروج"
|
|
||||||
settings: "تنظیمات"
|
|
||||||
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:
|
|
||||||
title: "گالری هنرهای آب و هوا"
|
|
||||||
subtitle: "کشف هنر آب و هوای تولید شده توسط هوش مصنوعی از شهرهای سراسر جهان"
|
|
||||||
home:
|
|
||||||
headline_html: جایی که آب و هوا با<br>هوش مصنوعی ملاقات میکند
|
|
||||||
subtitle:
|
|
||||||
تجربه آب و هوا از طریق لنز هنر تولید شده توسط هوش مصنوعی،
|
|
||||||
آوردن دیدگاهی جدید به پدیدههای هواشناسی روزانه.
|
|
||||||
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: "نمایش %{from} تا %{to} از %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "رکوردهای آب و هوا"
|
|
||||||
default: "موارد"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%B %d, %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
fr:
|
|
||||||
hello: "Bonjour le monde"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Villes"
|
|
||||||
arts: "Arts"
|
|
||||||
sign_in: "Se connecter"
|
|
||||||
sign_out: "Se déconnecter"
|
|
||||||
settings: "Paramètres"
|
|
||||||
admin_dashboard: "Tableau de bord administrateur"
|
|
||||||
latest_weather_art: "Derniers arts météorologiques"
|
|
||||||
popular_weather_art: "Arts météorologiques populaires"
|
|
||||||
ai_prompt: "Prompt IA"
|
|
||||||
text:
|
|
||||||
latest_from: "Derniers de"
|
|
||||||
search_cities: "Rechercher des villes..."
|
|
||||||
all_regions: "Toutes les régions"
|
|
||||||
all_countries: "Tous les pays"
|
|
||||||
all_in: "Tout dans"
|
|
||||||
showing: "Affichage"
|
|
||||||
weather_arts: "Arts météorologiques"
|
|
||||||
newest_first: "Plus récents d'abord"
|
|
||||||
oldest_first: "Plus anciens d'abord"
|
|
||||||
cities:
|
|
||||||
title: "Explorer les villes"
|
|
||||||
arts:
|
|
||||||
title: "Galerie d'arts météorologiques"
|
|
||||||
subtitle: "Découvrez l'art météorologique généré par l'IA des villes du monde entier"
|
|
||||||
home:
|
|
||||||
headline_html: "Là où la météo rencontre<br>l'Intelligence Artificielle"
|
|
||||||
subtitle:
|
|
||||||
Découvrez la météo à travers le prisme de l'art généré par l'IA,
|
|
||||||
apportant une nouvelle perspective aux phénomènes météorologiques quotidiens.
|
|
||||||
button:
|
|
||||||
explore_cities: "Explorer les villes"
|
|
||||||
view_detail: "Voir les détails"
|
|
||||||
view_all_weather_arts: "Voir tous les arts météorologiques"
|
|
||||||
back_to_cities: "Retour aux villes"
|
|
||||||
back_to: "Retour à"
|
|
||||||
card:
|
|
||||||
temperature: "Température"
|
|
||||||
wind: "Vent"
|
|
||||||
humidity: "Humidité"
|
|
||||||
visibility: "Visibilité"
|
|
||||||
pressure: "Pression"
|
|
||||||
cloud_cover: "Couverture nuageuse"
|
|
||||||
feel_like: "Ressenti"
|
|
||||||
relative_humidity: "Humidité relative"
|
|
||||||
clear_view_distance: "Distance de visibilité claire"
|
|
||||||
atmospheric_pressure: "Pression atmosphérique"
|
|
||||||
sky_coverage: "Couverture du ciel"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Affichage de %{from} à %{to} sur %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "relevés météorologiques"
|
|
||||||
default: "éléments"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d %B %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
hi:
|
|
||||||
hello: "नमस्ते दुनिया"
|
|
||||||
brand:
|
|
||||||
name: "टुडे एआई वेदर"
|
|
||||||
title:
|
|
||||||
cities: "शहर"
|
|
||||||
arts: "कला"
|
|
||||||
sign_in: "साइन इन"
|
|
||||||
sign_out: "साइन आउट"
|
|
||||||
settings: "सेटिंग्स"
|
|
||||||
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:
|
|
||||||
title: "मौसम कला गैलरी"
|
|
||||||
subtitle: "दुनिया भर के शहरों से एआई-जनित मौसम कला की खोज करें"
|
|
||||||
home:
|
|
||||||
headline_html: जहां मौसम मिलता है<br>कृत्रिम बुद्धिमत्ता
|
|
||||||
subtitle:
|
|
||||||
एआई-जनित कला के माध्यम से मौसम का अनुभव करें,
|
|
||||||
दैनिक मौसम संबंधी घटनाओं को एक नया दृष्टिकोण प्रदान करें।
|
|
||||||
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}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%B %d, %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
hr:
|
|
||||||
hello: "Pozdrav svijete"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Gradovi"
|
|
||||||
arts: "Umjetnost"
|
|
||||||
sign_in: "Prijava"
|
|
||||||
sign_out: "Odjava"
|
|
||||||
settings: "Postavke"
|
|
||||||
admin_dashboard: "Administratorska ploča"
|
|
||||||
latest_weather_art: "Najnovija vremenska umjetnost"
|
|
||||||
popular_weather_art: "Popularna vremenska umjetnost"
|
|
||||||
ai_prompt: "AI upit"
|
|
||||||
text:
|
|
||||||
latest_from: "Najnovije od"
|
|
||||||
search_cities: "Pretraži gradove..."
|
|
||||||
all_regions: "Sve regije"
|
|
||||||
all_countries: "Sve države"
|
|
||||||
all_in: "Sve u"
|
|
||||||
showing: "Prikazuje se"
|
|
||||||
weather_arts: "Vremenska umjetnost"
|
|
||||||
newest_first: "Najnovije prvo"
|
|
||||||
oldest_first: "Najstarije prvo"
|
|
||||||
cities:
|
|
||||||
title: "Istražite gradove"
|
|
||||||
arts:
|
|
||||||
title: "Galerija vremenske umjetnosti"
|
|
||||||
subtitle: "Otkrijte umjetnost vremena generiranu AI-em iz gradova širom svijeta"
|
|
||||||
home:
|
|
||||||
headline_html: Gdje se vrijeme susreće<br>s umjetnom inteligencijom
|
|
||||||
subtitle:
|
|
||||||
Doživite vrijeme kroz objektiv umjetnosti generirane AI-em,
|
|
||||||
donoseći novu perspektivu svakodnevnim meteorološkim pojavama.
|
|
||||||
button:
|
|
||||||
explore_cities: "Istražite gradove"
|
|
||||||
view_detail: "Pogledaj detalje"
|
|
||||||
view_all_weather_arts: "Pogledaj svu vremensku umjetnost"
|
|
||||||
back_to_cities: "Natrag na gradove"
|
|
||||||
back_to: "Natrag na"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatura"
|
|
||||||
wind: "Vjetar"
|
|
||||||
humidity: "Vlažnost"
|
|
||||||
visibility: "Vidljivost"
|
|
||||||
pressure: "Tlak"
|
|
||||||
cloud_cover: "Naoblaka"
|
|
||||||
feel_like: "Osjeća se kao"
|
|
||||||
relative_humidity: "Relativna vlažnost"
|
|
||||||
clear_view_distance: "Udaljenost čistog pogleda"
|
|
||||||
atmospheric_pressure: "Atmosferski tlak"
|
|
||||||
sky_coverage: "Pokrivenost neba"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Prikazuje se %{from} do %{to} od %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "vremenskih zapisa"
|
|
||||||
default: "stavki"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d. %B %Y."
|
|
@ -1,67 +0,0 @@
|
|||||||
it:
|
|
||||||
hello: "Ciao mondo"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Città"
|
|
||||||
arts: "Arte"
|
|
||||||
sign_in: "Accedi"
|
|
||||||
sign_out: "Esci"
|
|
||||||
settings: "Impostazioni"
|
|
||||||
admin_dashboard: "Dashboard Amministratore"
|
|
||||||
latest_weather_art: "Ultima Arte Meteorologica"
|
|
||||||
popular_weather_art: "Arte Meteorologica Popolare"
|
|
||||||
ai_prompt: "Prompt IA"
|
|
||||||
text:
|
|
||||||
latest_from: "Ultimi da"
|
|
||||||
search_cities: "Cerca città..."
|
|
||||||
all_regions: "Tutte le Regioni"
|
|
||||||
all_countries: "Tutti i Paesi"
|
|
||||||
all_in: "Tutto in"
|
|
||||||
showing: "Mostrando"
|
|
||||||
weather_arts: "Arte Meteorologica"
|
|
||||||
newest_first: "Prima i più Recenti"
|
|
||||||
oldest_first: "Prima i più Vecchi"
|
|
||||||
cities:
|
|
||||||
title: "Esplora Città"
|
|
||||||
arts:
|
|
||||||
title: "Galleria Arte Meteorologica"
|
|
||||||
subtitle: "Scopri l'arte meteorologica generata dall'IA dalle città di tutto il mondo"
|
|
||||||
home:
|
|
||||||
headline_html: Dove il Meteo Incontra<br>l'Intelligenza Artificiale
|
|
||||||
subtitle:
|
|
||||||
Vivi il meteo attraverso la lente dell'arte generata dall'IA,
|
|
||||||
portando una nuova prospettiva ai fenomeni meteorologici quotidiani.
|
|
||||||
button:
|
|
||||||
explore_cities: "Esplora Città"
|
|
||||||
view_detail: "Visualizza Dettagli"
|
|
||||||
view_all_weather_arts: "Visualizza Tutta l'Arte Meteorologica"
|
|
||||||
back_to_cities: "Torna alle Città"
|
|
||||||
back_to: "Torna a"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatura"
|
|
||||||
wind: "Vento"
|
|
||||||
humidity: "Umidità"
|
|
||||||
visibility: "Visibilità"
|
|
||||||
pressure: "Pressione"
|
|
||||||
cloud_cover: "Copertura Nuvolosa"
|
|
||||||
feel_like: "Percepita"
|
|
||||||
relative_humidity: "Umidità relativa"
|
|
||||||
clear_view_distance: "Distanza di visibilità"
|
|
||||||
atmospheric_pressure: "Pressione atmosferica"
|
|
||||||
sky_coverage: "Copertura del cielo"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Mostrando da %{from} a %{to} di %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "registrazioni meteo"
|
|
||||||
default: "elementi"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d %B %Y"
|
|
@ -1,66 +0,0 @@
|
|||||||
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: 天気が出会う場所<br>人工知能
|
|
||||||
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}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
short: "%Y-%m-%d"
|
|
||||||
long: "%Y 年 %m 月 %d 日"
|
|
@ -1,66 +0,0 @@
|
|||||||
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: 날씨가 만나는 곳<br>인공지능
|
|
||||||
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}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
short: "%Y-%m-%d"
|
|
||||||
long: "%Y 년 %m 월 %d 일"
|
|
@ -1,67 +0,0 @@
|
|||||||
pl:
|
|
||||||
hello: "Witaj świecie"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Miasta"
|
|
||||||
arts: "Sztuka"
|
|
||||||
sign_in: "Zaloguj się"
|
|
||||||
sign_out: "Wyloguj się"
|
|
||||||
settings: "Ustawienia"
|
|
||||||
admin_dashboard: "Panel administratora"
|
|
||||||
latest_weather_art: "Najnowsza sztuka pogodowa"
|
|
||||||
popular_weather_art: "Popularna sztuka pogodowa"
|
|
||||||
ai_prompt: "Prompt AI"
|
|
||||||
text:
|
|
||||||
latest_from: "Najnowsze z"
|
|
||||||
search_cities: "Szukaj miast..."
|
|
||||||
all_regions: "Wszystkie regiony"
|
|
||||||
all_countries: "Wszystkie kraje"
|
|
||||||
all_in: "Wszystko w"
|
|
||||||
showing: "Wyświetlanie"
|
|
||||||
weather_arts: "Sztuka pogodowa"
|
|
||||||
newest_first: "Od najnowszych"
|
|
||||||
oldest_first: "Od najstarszych"
|
|
||||||
cities:
|
|
||||||
title: "Odkryj miasta"
|
|
||||||
arts:
|
|
||||||
title: "Galeria sztuki pogodowej"
|
|
||||||
subtitle: "Odkryj sztukę pogodową generowaną przez AI z miast na całym świecie"
|
|
||||||
home:
|
|
||||||
headline_html: Gdzie pogoda spotyka się<br>ze sztuczną inteligencją
|
|
||||||
subtitle:
|
|
||||||
Doświadcz pogody przez pryzmat sztuki generowanej przez AI,
|
|
||||||
wprowadzając nową perspektywę do codziennych zjawisk meteorologicznych.
|
|
||||||
button:
|
|
||||||
explore_cities: "Odkryj miasta"
|
|
||||||
view_detail: "Zobacz szczegóły"
|
|
||||||
view_all_weather_arts: "Zobacz całą sztukę pogodową"
|
|
||||||
back_to_cities: "Powrót do miast"
|
|
||||||
back_to: "Powrót do"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatura"
|
|
||||||
wind: "Wiatr"
|
|
||||||
humidity: "Wilgotność"
|
|
||||||
visibility: "Widoczność"
|
|
||||||
pressure: "Ciśnienie"
|
|
||||||
cloud_cover: "Zachmurzenie"
|
|
||||||
feel_like: "Odczuwalna"
|
|
||||||
relative_humidity: "Wilgotność względna"
|
|
||||||
clear_view_distance: "Zasięg widoczności"
|
|
||||||
atmospheric_pressure: "Ciśnienie atmosferyczne"
|
|
||||||
sky_coverage: "Pokrycie nieba"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Wyświetlanie %{from} do %{to} z %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "zapisów pogody"
|
|
||||||
default: "elementów"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d %B %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
pt-BR:
|
|
||||||
hello: "Olá mundo"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Cidades"
|
|
||||||
arts: "Artes"
|
|
||||||
sign_in: "Entrar"
|
|
||||||
sign_out: "Sair"
|
|
||||||
settings: "Configurações"
|
|
||||||
admin_dashboard: "Painel de Administração"
|
|
||||||
latest_weather_art: "Arte Meteorológica Mais Recente"
|
|
||||||
popular_weather_art: "Arte Meteorológica Popular"
|
|
||||||
ai_prompt: "Prompt de IA"
|
|
||||||
text:
|
|
||||||
latest_from: "Mais recente de"
|
|
||||||
search_cities: "Pesquisar cidades..."
|
|
||||||
all_regions: "Todas as Regiões"
|
|
||||||
all_countries: "Todos os Países"
|
|
||||||
all_in: "Tudo em"
|
|
||||||
showing: "Mostrando"
|
|
||||||
weather_arts: "Artes Meteorológicas"
|
|
||||||
newest_first: "Mais Recentes Primeiro"
|
|
||||||
oldest_first: "Mais Antigos Primeiro"
|
|
||||||
cities:
|
|
||||||
title: "Explorar Cidades"
|
|
||||||
arts:
|
|
||||||
title: "Galeria de Artes Meteorológicas"
|
|
||||||
subtitle: "Descubra arte meteorológica gerada por IA de cidades ao redor do mundo"
|
|
||||||
home:
|
|
||||||
headline_html: Onde o Clima Encontra<br>a Inteligência Artificial
|
|
||||||
subtitle:
|
|
||||||
Experimente o clima através das lentes da arte gerada por IA,
|
|
||||||
trazendo uma nova perspectiva para os fenômenos meteorológicos diários.
|
|
||||||
button:
|
|
||||||
explore_cities: "Explorar Cidades"
|
|
||||||
view_detail: "Ver Detalhes"
|
|
||||||
view_all_weather_arts: "Ver Todas as Artes Meteorológicas"
|
|
||||||
back_to_cities: "Voltar para Cidades"
|
|
||||||
back_to: "Voltar para"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatura"
|
|
||||||
wind: "Vento"
|
|
||||||
humidity: "Umidade"
|
|
||||||
visibility: "Visibilidade"
|
|
||||||
pressure: "Pressão"
|
|
||||||
cloud_cover: "Cobertura de Nuvens"
|
|
||||||
feel_like: "Sensação térmica"
|
|
||||||
relative_humidity: "Umidade relativa"
|
|
||||||
clear_view_distance: "Distância de visão clara"
|
|
||||||
atmospheric_pressure: "Pressão atmosférica"
|
|
||||||
sky_coverage: "Cobertura do céu"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Mostrando %{from} até %{to} de %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "registros meteorológicos"
|
|
||||||
default: "itens"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%d/%m/%Y"
|
|
||||||
short: "%d %b"
|
|
||||||
long: "%d de %B de %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
pt:
|
|
||||||
hello: "Olá mundo"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Cidades"
|
|
||||||
arts: "Artes"
|
|
||||||
sign_in: "Entrar"
|
|
||||||
sign_out: "Sair"
|
|
||||||
settings: "Configurações"
|
|
||||||
admin_dashboard: "Painel de Administração"
|
|
||||||
latest_weather_art: "Arte Meteorológica Mais Recente"
|
|
||||||
popular_weather_art: "Arte Meteorológica Popular"
|
|
||||||
ai_prompt: "Prompt de IA"
|
|
||||||
text:
|
|
||||||
latest_from: "Mais recente de"
|
|
||||||
search_cities: "Pesquisar cidades..."
|
|
||||||
all_regions: "Todas as Regiões"
|
|
||||||
all_countries: "Todos os Países"
|
|
||||||
all_in: "Tudo em"
|
|
||||||
showing: "Mostrando"
|
|
||||||
weather_arts: "Artes Meteorológicas"
|
|
||||||
newest_first: "Mais Recentes Primeiro"
|
|
||||||
oldest_first: "Mais Antigos Primeiro"
|
|
||||||
cities:
|
|
||||||
title: "Explorar Cidades"
|
|
||||||
arts:
|
|
||||||
title: "Galeria de Artes Meteorológicas"
|
|
||||||
subtitle: "Descubra arte meteorológica gerada por IA de cidades ao redor do mundo"
|
|
||||||
home:
|
|
||||||
headline_html: Onde o Clima Encontra<br>a Inteligência Artificial
|
|
||||||
subtitle:
|
|
||||||
Experimente o clima através das lentes da arte gerada por IA,
|
|
||||||
trazendo uma nova perspectiva para os fenômenos meteorológicos diários.
|
|
||||||
button:
|
|
||||||
explore_cities: "Explorar Cidades"
|
|
||||||
view_detail: "Ver Detalhes"
|
|
||||||
view_all_weather_arts: "Ver Todas as Artes Meteorológicas"
|
|
||||||
back_to_cities: "Voltar para Cidades"
|
|
||||||
back_to: "Voltar para"
|
|
||||||
card:
|
|
||||||
temperature: "Temperatura"
|
|
||||||
wind: "Vento"
|
|
||||||
humidity: "Umidade"
|
|
||||||
visibility: "Visibilidade"
|
|
||||||
pressure: "Pressão"
|
|
||||||
cloud_cover: "Cobertura de Nuvens"
|
|
||||||
feel_like: "Sensação térmica"
|
|
||||||
relative_humidity: "Umidade relativa"
|
|
||||||
clear_view_distance: "Distância de visão clara"
|
|
||||||
atmospheric_pressure: "Pressão atmosférica"
|
|
||||||
sky_coverage: "Cobertura do céu"
|
|
||||||
pagination:
|
|
||||||
showing_items: "Mostrando %{from} a %{to} de %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "registros meteorológicos"
|
|
||||||
default: "itens"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%d de %b"
|
|
||||||
long: "%d de %B de %Y"
|
|
15
config/locales/regions.en.yml
Normal file
15
config/locales/regions.en.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
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'
|
15
config/locales/regions.zh-CN.yml
Normal file
15
config/locales/regions.zh-CN.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
zh-CN:
|
||||||
|
regions:
|
||||||
|
AS: '亚洲'
|
||||||
|
SA: '南亚'
|
||||||
|
SEA: '东南亚'
|
||||||
|
EA: '东亚'
|
||||||
|
ME: '中东'
|
||||||
|
AF: '非洲'
|
||||||
|
NA: '北非'
|
||||||
|
SSA: '撒哈拉以南非洲'
|
||||||
|
EU: '欧洲'
|
||||||
|
NAM: '北美洲'
|
||||||
|
SAM: '南美洲'
|
||||||
|
CAM: '中美洲'
|
||||||
|
OC: '大洋洲'
|
@ -1,67 +0,0 @@
|
|||||||
ru:
|
|
||||||
hello: "Привет, мир"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
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: Где погода встречается<br>с искусственным интеллектом
|
|
||||||
subtitle:
|
|
||||||
Познакомьтесь с погодой через призму искусства, созданного искусственным интеллектом,
|
|
||||||
открывая новый взгляд на ежедневные метеорологические явления.
|
|
||||||
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: "Показано с %{from} по %{to} из %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "записей о погоде"
|
|
||||||
default: "элементов"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d %B %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
tr:
|
|
||||||
hello: "Merhaba dünya"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
title:
|
|
||||||
cities: "Şehirler"
|
|
||||||
arts: "Sanat"
|
|
||||||
sign_in: "Giriş yap"
|
|
||||||
sign_out: "Çıkış yap"
|
|
||||||
settings: "Ayarlar"
|
|
||||||
admin_dashboard: "Yönetici Paneli"
|
|
||||||
latest_weather_art: "En Son Hava Durumu Sanatı"
|
|
||||||
popular_weather_art: "Popüler Hava Durumu Sanatı"
|
|
||||||
ai_prompt: "AI Komut"
|
|
||||||
text:
|
|
||||||
latest_from: "En son"
|
|
||||||
search_cities: "Şehirleri ara..."
|
|
||||||
all_regions: "Tüm Bölgeler"
|
|
||||||
all_countries: "Tüm Ülkeler"
|
|
||||||
all_in: "Tümü"
|
|
||||||
showing: "Gösteriliyor"
|
|
||||||
weather_arts: "Hava Durumu Sanatları"
|
|
||||||
newest_first: "En Yeni Önce"
|
|
||||||
oldest_first: "En Eski Önce"
|
|
||||||
cities:
|
|
||||||
title: "Şehirleri Keşfet"
|
|
||||||
arts:
|
|
||||||
title: "Hava Durumu Sanat Galerisi"
|
|
||||||
subtitle: "Dünya genelindeki şehirlerden AI tarafından oluşturulan hava durumu sanatını keşfedin"
|
|
||||||
home:
|
|
||||||
headline_html: "Hava Durumu<br>Yapay Zeka ile Buluşuyor"
|
|
||||||
subtitle:
|
|
||||||
AI tarafından oluşturulan sanat perspektifinden hava durumunu deneyimleyin,
|
|
||||||
günlük meteorolojik olaylara yeni bir bakış açısı getirin.
|
|
||||||
button:
|
|
||||||
explore_cities: "Şehirleri Keşfet"
|
|
||||||
view_detail: "Detayları Görüntüle"
|
|
||||||
view_all_weather_arts: "Tüm Hava Durumu Sanatlarını Görüntüle"
|
|
||||||
back_to_cities: "Şehirlere Geri Dön"
|
|
||||||
back_to: "Geri Dön"
|
|
||||||
card:
|
|
||||||
temperature: "Sıcaklık"
|
|
||||||
wind: "Rüzgar"
|
|
||||||
humidity: "Nem"
|
|
||||||
visibility: "Görüş Mesafesi"
|
|
||||||
pressure: "Basınç"
|
|
||||||
cloud_cover: "Bulut Örtüsü"
|
|
||||||
feel_like: "Hissedilen"
|
|
||||||
relative_humidity: "Bağıl nem"
|
|
||||||
clear_view_distance: "Net görüş mesafesi"
|
|
||||||
atmospheric_pressure: "Atmosfer basıncı"
|
|
||||||
sky_coverage: "Gökyüzü kapsama"
|
|
||||||
pagination:
|
|
||||||
showing_items: "%{total} %{items} içinden %{from} ile %{to} arası gösteriliyor"
|
|
||||||
items:
|
|
||||||
weather: "hava durumu kayıtları"
|
|
||||||
default: "öğe"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%d %b"
|
|
||||||
long: "%d %B %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
uk:
|
|
||||||
hello: "Привіт світ"
|
|
||||||
brand:
|
|
||||||
name: "Today AI Weather"
|
|
||||||
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: "Відкрийте для себе згенероване ШІ погодне мистецтво з міст по всьому світу"
|
|
||||||
home:
|
|
||||||
headline_html: Де погода зустрічається<br>зі штучним інтелектом
|
|
||||||
subtitle:
|
|
||||||
Відчуйте погоду через призму мистецтва, створеного ШІ,
|
|
||||||
що дає новий погляд на щоденні метеорологічні явища.
|
|
||||||
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: "Показано %{from} до %{to} з %{total} %{items}"
|
|
||||||
items:
|
|
||||||
weather: "погодних записів"
|
|
||||||
default: "елементів"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%d %B %Y"
|
|
@ -1,67 +0,0 @@
|
|||||||
ur:
|
|
||||||
hello: "ہیلو دنیا"
|
|
||||||
brand:
|
|
||||||
name: "ٹوڈے اے آئی ویدر"
|
|
||||||
title:
|
|
||||||
cities: "شہر"
|
|
||||||
arts: "فن"
|
|
||||||
sign_in: "سائن ان"
|
|
||||||
sign_out: "سائن آؤٹ"
|
|
||||||
settings: "ترتیبات"
|
|
||||||
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:
|
|
||||||
title: "موسمی فن گیلری"
|
|
||||||
subtitle: "دنیا بھر کے شہروں سے اے آئی سے تیار کردہ موسمی فن دریافت کریں"
|
|
||||||
home:
|
|
||||||
headline_html: جہاں موسم<br>مصنوعی ذہانت سے ملتا ہے
|
|
||||||
subtitle:
|
|
||||||
اے آئی سے تیار کردہ فن کے ذریعے موسم کا تجربہ کریں،
|
|
||||||
روزمرہ موسمیاتی مظاہر کو ایک نیا نظریہ فراہم کرتا ہے۔
|
|
||||||
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: "%{items} کے %{total} میں سے %{from} سے %{to} تک دکھا رہا ہے"
|
|
||||||
items:
|
|
||||||
weather: "موسمی ریکارڈز"
|
|
||||||
default: "آئٹمز"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
default: "%Y-%m-%d"
|
|
||||||
short: "%b %d"
|
|
||||||
long: "%B %d, %Y"
|
|
@ -1,65 +0,0 @@
|
|||||||
zh-CN:
|
|
||||||
hello: "你好"
|
|
||||||
brand:
|
|
||||||
name: "全球艺术天气"
|
|
||||||
title:
|
|
||||||
cities: "城市探索"
|
|
||||||
arts: "艺术巡览"
|
|
||||||
sign_in: "用户登录"
|
|
||||||
sign_out: "退出登录"
|
|
||||||
settings: "系统设置"
|
|
||||||
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:
|
|
||||||
title: "天象画廊"
|
|
||||||
subtitle: "邂逅寰宇都市AI气象绘卷"
|
|
||||||
home:
|
|
||||||
headline_html: 当气象邂逅<br>人工智能之美
|
|
||||||
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: "显示第 %{from} 到第 %{to} 条,共 %{total} 条%{items}"
|
|
||||||
items:
|
|
||||||
weather: "天气记录"
|
|
||||||
default: "记录"
|
|
||||||
time:
|
|
||||||
formats:
|
|
||||||
time_only: "%H:%M"
|
|
||||||
with_zone: "%{time} %{zone}"
|
|
||||||
date_and_time: "%{date} %{time}"
|
|
||||||
date:
|
|
||||||
formats:
|
|
||||||
short: "%Y-%m-%d"
|
|
||||||
long: "%Y 年 %m 月 %d 日"
|
|
@ -1,7 +1,6 @@
|
|||||||
require "sidekiq/web"
|
require "sidekiq/web"
|
||||||
|
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
|
|
||||||
devise_for :users
|
devise_for :users
|
||||||
root "home#index"
|
root "home#index"
|
||||||
|
|
||||||
@ -25,9 +24,7 @@ Rails.application.routes.draw do
|
|||||||
get "cities/index"
|
get "cities/index"
|
||||||
get "cities/show"
|
get "cities/show"
|
||||||
get "home/index"
|
get "home/index"
|
||||||
get "sitemaps", to: "sitemaps#index"
|
|
||||||
get "sitemaps/*path", to: "sitemaps#show", format: false
|
get "sitemaps/*path", to: "sitemaps#show", format: false
|
||||||
get "feed", to: "rss#feed", format: "rss", as: :rss_feed
|
|
||||||
|
|
||||||
devise_for :admin_users, ActiveAdmin::Devise.config
|
devise_for :admin_users, ActiveAdmin::Devise.config
|
||||||
ActiveAdmin.routes(self)
|
ActiveAdmin.routes(self)
|
||||||
@ -50,4 +47,3 @@ Rails.application.routes.draw do
|
|||||||
# Defines the root path route ("/")
|
# Defines the root path route ("/")
|
||||||
# root "posts#index"
|
# root "posts#index"
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000"
|
host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000"
|
||||||
Rails.application.routes.default_url_options[:host] = host
|
Rails.application.routes.default_url_options[:host] = host
|
||||||
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
||||||
Rails.application.credentials.dig(:minio, :bucket),
|
Rails.application.credentials.dig(:aws, :bucket),
|
||||||
aws_access_key_id: Rails.application.credentials.dig(:minio, :access_key_id),
|
aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id),
|
||||||
aws_secret_access_key: Rails.application.credentials.dig(:minio, :secret_access_key),
|
aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key),
|
||||||
aws_region: Rails.application.credentials.dig(:minio, :region)
|
aws_region: Rails.application.credentials.dig(:aws, :region)
|
||||||
)
|
)
|
||||||
SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/"
|
SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/"
|
||||||
|
|
||||||
|
@ -19,21 +19,19 @@ build:
|
|||||||
# bucket: your_own_bucket-<%= Rails.env %>
|
# bucket: your_own_bucket-<%= Rails.env %>
|
||||||
amazon_dev:
|
amazon_dev:
|
||||||
service: S3
|
service: S3
|
||||||
access_key_id: <%= ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :access_key_id)) %>
|
access_key_id: <%= ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :access_key_id)) %>
|
||||||
secret_access_key: <%= ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :secret_access_key)) %>
|
secret_access_key: <%= ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws_dev, :secret_access_key)) %>
|
||||||
region: <%= ENV.fetch("AWS_DEV_REGION", Rails.application.credentials.dig(:minio_dev, :region)) %>
|
region: <%= ENV.fetch("AWS_DEV_REGION", "wnam") %>
|
||||||
bucket: <%= ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:minio_dev, :bucket)) %>
|
bucket: <%= ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:aws_dev, :bucket)) %>
|
||||||
endpoint: <%= ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:minio_dev, :endpoint)) %>
|
endpoint: <%= ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:aws_dev, :endpoint)) %>
|
||||||
force_path_style: <%= ENV.fetch("AWS_DEV_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio_dev, :force_path_style)) %>
|
|
||||||
|
|
||||||
amazon:
|
amazon:
|
||||||
service: S3
|
service: S3
|
||||||
access_key_id: <%= ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :access_key_id)) %>
|
access_key_id: <%= ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :access_key_id)) %>
|
||||||
secret_access_key: <%= ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :secret_access_key)) %>
|
secret_access_key: <%= ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:aws, :secret_access_key)) %>
|
||||||
region: <%= ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:minio, :region)) %>
|
region: <%= ENV.fetch("AWS_REGION", "wnam") %>
|
||||||
bucket: <%= ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:minio, :bucket)) %>
|
bucket: <%= ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:aws, :bucket)) %>
|
||||||
endpoint: <%= ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:minio, :endpoint)) %>
|
endpoint: <%= ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:aws, :endpoint)) %>
|
||||||
force_path_style: <%= ENV.fetch("AWS_DEV_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio, :force_path_style)) %>
|
|
||||||
|
|
||||||
# Remember not to checkin your GCS keyfile to a repository
|
# Remember not to checkin your GCS keyfile to a repository
|
||||||
# google:
|
# google:
|
||||||
|
40
db/seeds.rb
40
db/seeds.rb
@ -10,6 +10,11 @@
|
|||||||
# AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development?
|
# AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password') if Rails.env.development?
|
||||||
AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password')
|
AdminUser.create!(email: 'admin@example.com', password: 'password', password_confirmation: 'password')
|
||||||
|
|
||||||
|
# WeatherArt.delete_all
|
||||||
|
# City.delete_all
|
||||||
|
# Country.delete_all
|
||||||
|
# Region.delete_all
|
||||||
|
|
||||||
# 创建区域
|
# 创建区域
|
||||||
regions = Region.create!([
|
regions = Region.create!([
|
||||||
{
|
{
|
||||||
@ -17,14 +22,46 @@ regions = Region.create!([
|
|||||||
code: 'AS'
|
code: 'AS'
|
||||||
# },
|
# },
|
||||||
# {
|
# {
|
||||||
|
# name: 'Southeast Asia',
|
||||||
|
# code: 'SEA'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# name: 'East Asia',
|
||||||
|
# code: 'EA'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# name: 'Middle East',
|
||||||
|
# code: 'ME'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
# name: 'Africa',
|
# name: 'Africa',
|
||||||
# code: 'AF'
|
# code: 'AF'
|
||||||
# },
|
# },
|
||||||
# {
|
# {
|
||||||
|
# name: 'North Africa',
|
||||||
|
# code: 'NA'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# name: 'Sub-Saharan Africa',
|
||||||
|
# code: 'SSA'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
# name: 'Europe',
|
# name: 'Europe',
|
||||||
# code: 'EU'
|
# code: 'EU'
|
||||||
# },
|
# },
|
||||||
# {
|
# {
|
||||||
|
# name: 'North America',
|
||||||
|
# code: 'NAM'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# name: 'South America',
|
||||||
|
# code: 'SAM'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# name: 'Central America',
|
||||||
|
# code: 'CAM'
|
||||||
|
# },
|
||||||
|
# {
|
||||||
# name: 'Oceania',
|
# name: 'Oceania',
|
||||||
# code: 'OC'
|
# code: 'OC'
|
||||||
}
|
}
|
||||||
@ -96,6 +133,9 @@ Country.create!([
|
|||||||
])
|
])
|
||||||
|
|
||||||
# 创建城市
|
# 创建城市
|
||||||
|
# Dir[Rails.root.join('db/seeds/cities/*.rb')].sort.each do |file|
|
||||||
|
# require file
|
||||||
|
# end
|
||||||
china = Country.find_by code: 'CN'
|
china = Country.find_by code: 'CN'
|
||||||
City.create!([
|
City.create!([
|
||||||
{
|
{
|
||||||
|
22
db/seeds/cities/australia.rb
Normal file
22
db/seeds/cities/australia.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
australia = Country.find_by code: 'AU'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Sydney',
|
||||||
|
latitude: -33.8688,
|
||||||
|
longitude: 151.2093,
|
||||||
|
country: australia,
|
||||||
|
timezone: 'Australia/Sydney',
|
||||||
|
active: true,
|
||||||
|
priority: 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Melbourne',
|
||||||
|
latitude: -37.8136,
|
||||||
|
longitude: 144.9631,
|
||||||
|
country: australia,
|
||||||
|
timezone: 'Australia/Melbourne',
|
||||||
|
active: true,
|
||||||
|
priority: 75
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/bangladesh.rb
Normal file
13
db/seeds/cities/bangladesh.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
bangladesh = Country.find_by code: 'BD'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Dhaka',
|
||||||
|
latitude: 23.8103,
|
||||||
|
longitude: 90.4125,
|
||||||
|
country: bangladesh,
|
||||||
|
timezone: 'Asia/Dhaka',
|
||||||
|
active: true,
|
||||||
|
priority: 85
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/brazil.rb
Normal file
13
db/seeds/cities/brazil.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
brazil = Country.find_by code: 'BR'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Rio de Janeiro',
|
||||||
|
latitude: -22.9068,
|
||||||
|
longitude: -43.1729,
|
||||||
|
country: brazil,
|
||||||
|
timezone: 'America/Sao_Paulo',
|
||||||
|
active: true,
|
||||||
|
priority: 80
|
||||||
|
}
|
||||||
|
])
|
10
db/seeds/cities/canada.rb
Normal file
10
db/seeds/cities/canada.rb
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
canada = Country.find_by code: 'CA'
|
||||||
|
City.create!(
|
||||||
|
name: 'Toronto',
|
||||||
|
latitude: 43.6532,
|
||||||
|
longitude: -79.3832,
|
||||||
|
priority: 50,
|
||||||
|
country: canada,
|
||||||
|
timezone: 'America/Toronto',
|
||||||
|
active: true
|
||||||
|
)
|
346
db/seeds/cities/china.rb
Normal file
346
db/seeds/cities/china.rb
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
china = Country.find_by code: 'CN'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Shanghai',
|
||||||
|
latitude: 31.2304,
|
||||||
|
longitude: 121.4737,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Beijing',
|
||||||
|
latitude: 39.9042,
|
||||||
|
longitude: 116.4074,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Shenzhen',
|
||||||
|
latitude: 22.5431,
|
||||||
|
longitude: 114.0579,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Guangzhou',
|
||||||
|
latitude: 23.1291,
|
||||||
|
longitude: 113.2644,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Chengdu',
|
||||||
|
latitude: 30.5728,
|
||||||
|
longitude: 104.0668,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tianjin',
|
||||||
|
latitude: 39.3434,
|
||||||
|
longitude: 117.3616,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Wuhan',
|
||||||
|
latitude: 30.5928,
|
||||||
|
longitude: 114.3055,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Dongguan',
|
||||||
|
latitude: 23.0208,
|
||||||
|
longitude: 113.7518,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Chongqing',
|
||||||
|
latitude: 29.4316,
|
||||||
|
longitude: 106.9123,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Xi'an",
|
||||||
|
latitude: 34.3416,
|
||||||
|
longitude: 108.9398,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hangzhou',
|
||||||
|
latitude: 30.2741,
|
||||||
|
longitude: 120.1551,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Foshan',
|
||||||
|
latitude: 23.0219,
|
||||||
|
longitude: 113.1216,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Nanjing',
|
||||||
|
latitude: 32.0603,
|
||||||
|
longitude: 118.7969,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hong Kong',
|
||||||
|
latitude: 22.3193,
|
||||||
|
longitude: 114.1694,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Hong_Kong',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Shenyang',
|
||||||
|
latitude: 41.8057,
|
||||||
|
longitude: 123.4315,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Zhengzhou',
|
||||||
|
latitude: 34.7472,
|
||||||
|
longitude: 113.6249,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Qingdao',
|
||||||
|
latitude: 36.0671,
|
||||||
|
longitude: 120.3826,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Suzhou',
|
||||||
|
latitude: 31.2990,
|
||||||
|
longitude: 120.5853,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Changsha',
|
||||||
|
latitude: 28.2282,
|
||||||
|
longitude: 112.9388,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Jinan',
|
||||||
|
latitude: 36.6512,
|
||||||
|
longitude: 117.1201,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Kunming',
|
||||||
|
latitude: 25.0389,
|
||||||
|
longitude: 102.7183,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Harbin',
|
||||||
|
latitude: 45.8038,
|
||||||
|
longitude: 126.5340,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Shijiazhuang',
|
||||||
|
latitude: 38.0428,
|
||||||
|
longitude: 114.5149,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hefei',
|
||||||
|
latitude: 31.8206,
|
||||||
|
longitude: 117.2272,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Dalian',
|
||||||
|
latitude: 38.9140,
|
||||||
|
longitude: 121.6147,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Xiamen',
|
||||||
|
latitude: 24.4798,
|
||||||
|
longitude: 118.0819,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Nanning',
|
||||||
|
latitude: 22.8170,
|
||||||
|
longitude: 108.3665,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Changchun',
|
||||||
|
latitude: 43.8171,
|
||||||
|
longitude: 125.3235,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Taiyuan',
|
||||||
|
latitude: 37.8706,
|
||||||
|
longitude: 112.5489,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'New Taipei City',
|
||||||
|
latitude: 25.0120,
|
||||||
|
longitude: 121.4657,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Taipei',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Guiyang',
|
||||||
|
latitude: 26.6470,
|
||||||
|
longitude: 106.6302,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Wuxi',
|
||||||
|
latitude: 31.4914,
|
||||||
|
longitude: 120.3119,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Shantou',
|
||||||
|
latitude: 23.3535,
|
||||||
|
longitude: 116.6822,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ürümqi',
|
||||||
|
latitude: 43.8256,
|
||||||
|
longitude: 87.6168,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Zhongshan',
|
||||||
|
latitude: 22.5415,
|
||||||
|
longitude: 113.3926,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ningbo',
|
||||||
|
latitude: 29.8683,
|
||||||
|
longitude: 121.5440,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Fuzhou',
|
||||||
|
latitude: 26.0745,
|
||||||
|
longitude: 119.2965,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Nanchang',
|
||||||
|
latitude: 28.6820,
|
||||||
|
longitude: 115.8579,
|
||||||
|
country: china,
|
||||||
|
timezone: 'Asia/Shanghai',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/egypt.rb
Normal file
13
db/seeds/cities/egypt.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
egypt = Country.find_by code: 'EG'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Alexandria',
|
||||||
|
latitude: 31.2001,
|
||||||
|
longitude: 29.9187,
|
||||||
|
country: egypt,
|
||||||
|
timezone: 'Africa/Cairo',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/france.rb
Normal file
13
db/seeds/cities/france.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
france = Country.find_by code: 'FRA'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Paris',
|
||||||
|
latitude: 48.8566,
|
||||||
|
longitude: 2.3522,
|
||||||
|
country: france,
|
||||||
|
timezone: 'Europe/Paris',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
22
db/seeds/cities/germany.rb
Normal file
22
db/seeds/cities/germany.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
germany = Country.find_by code: 'DE'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Frankfurt',
|
||||||
|
latitude: 50.1109,
|
||||||
|
longitude: 8.6821,
|
||||||
|
country: germany,
|
||||||
|
timezone: 'Europe/Berlin',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Berlin',
|
||||||
|
latitude: 52.5200,
|
||||||
|
longitude: 13.4050,
|
||||||
|
country: germany,
|
||||||
|
timezone: 'Europe/Berlin',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
22
db/seeds/cities/india.rb
Normal file
22
db/seeds/cities/india.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
india = Country.find_by code: 'IN'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Mumbai',
|
||||||
|
latitude: 19.0760,
|
||||||
|
longitude: 72.8777,
|
||||||
|
country: india,
|
||||||
|
timezone: 'Asia/Kolkata',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bengaluru',
|
||||||
|
latitude: 12.9716,
|
||||||
|
longitude: 77.5946,
|
||||||
|
country: india,
|
||||||
|
timezone: 'Asia/Kolkata',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
22
db/seeds/cities/japan.rb
Normal file
22
db/seeds/cities/japan.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
japan = Country.find_by code: 'JP'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Tokyo',
|
||||||
|
latitude: 35.6762,
|
||||||
|
longitude: 139.6503,
|
||||||
|
country: japan,
|
||||||
|
timezone: 'Asia/Tokyo',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Yokohama',
|
||||||
|
latitude: 35.4437,
|
||||||
|
longitude: 139.6380,
|
||||||
|
country: japan,
|
||||||
|
timezone: 'Asia/Tokyo',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/mexico.rb
Normal file
13
db/seeds/cities/mexico.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
mexico = Country.find_by code: 'MX'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Mexico City',
|
||||||
|
latitude: 19.4326,
|
||||||
|
longitude: -99.1332,
|
||||||
|
country: mexico,
|
||||||
|
timezone: 'America/Mexico_City',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/nigeria.rb
Normal file
13
db/seeds/cities/nigeria.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
nigeria = Country.find_by code: 'NG'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Lagos',
|
||||||
|
latitude: 6.5244,
|
||||||
|
longitude: 3.3792,
|
||||||
|
country: nigeria,
|
||||||
|
timezone: 'Africa/Lagos',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/pakistan.rb
Normal file
13
db/seeds/cities/pakistan.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pakistan = Country.find_by code: 'PK'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Lahore',
|
||||||
|
latitude: 31.5204,
|
||||||
|
longitude: 74.3587,
|
||||||
|
country: pakistan,
|
||||||
|
timezone: 'Asia/Karachi',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
22
db/seeds/cities/russia.rb
Normal file
22
db/seeds/cities/russia.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
russia = Country.find_by code: 'RU'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Moscow',
|
||||||
|
latitude: 55.7558,
|
||||||
|
longitude: 37.6173,
|
||||||
|
country: russia,
|
||||||
|
timezone: 'Europe/Moscow',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sankt Petersburg',
|
||||||
|
latitude: 59.9311,
|
||||||
|
longitude: 30.3609,
|
||||||
|
country: russia,
|
||||||
|
timezone: 'Europe/Moscow',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/saudi_arabia.rb
Normal file
13
db/seeds/cities/saudi_arabia.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
saudi_arabia = Country.find_by code: 'CA'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Riyadh',
|
||||||
|
latitude: 24.7136,
|
||||||
|
longitude: 46.6753,
|
||||||
|
country: saudi_arabia,
|
||||||
|
timezone: 'Asia/Riyadh',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/singapore.rb
Normal file
13
db/seeds/cities/singapore.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
singapore = Country.find_by code: 'SG'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Singapore',
|
||||||
|
latitude: 1.3521,
|
||||||
|
longitude: 103.8198,
|
||||||
|
country: singapore,
|
||||||
|
timezone: 'Asia/Singapore',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/south_korea.rb
Normal file
13
db/seeds/cities/south_korea.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
south_korea = Country.find_by code: 'KR'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Seoul',
|
||||||
|
latitude: 37.5665,
|
||||||
|
longitude: 126.9780,
|
||||||
|
country: south_korea,
|
||||||
|
timezone: 'Asia/Seoul',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/thailand.rb
Normal file
13
db/seeds/cities/thailand.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
thailand = Country.find_by code: 'TH'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Bangkok',
|
||||||
|
latitude: 13.7563,
|
||||||
|
longitude: 100.5018,
|
||||||
|
country: thailand,
|
||||||
|
timezone: 'Asia/Bangkok',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
22
db/seeds/cities/turkey.rb
Normal file
22
db/seeds/cities/turkey.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
turkey = Country.find_by code: 'TR'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'İstanbul',
|
||||||
|
latitude: 41.0082,
|
||||||
|
longitude: 28.9784,
|
||||||
|
country: turkey,
|
||||||
|
timezone: 'Europe/Istanbul',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ankara',
|
||||||
|
latitude: 39.9334,
|
||||||
|
longitude: 32.8597,
|
||||||
|
country: turkey,
|
||||||
|
timezone: 'Europe/Istanbul',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
13
db/seeds/cities/uk.rb
Normal file
13
db/seeds/cities/uk.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
uk = Country.find_by code: 'GB'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'London',
|
||||||
|
latitude: 51.5074,
|
||||||
|
longitude: -0.1278,
|
||||||
|
country: uk,
|
||||||
|
timezone: 'Europe/London',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
40
db/seeds/cities/usa.rb
Normal file
40
db/seeds/cities/usa.rb
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
usa = Country.find_by code: 'US'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'San Francisco',
|
||||||
|
latitude: 37.7749,
|
||||||
|
longitude: -122.4194,
|
||||||
|
country: usa,
|
||||||
|
timezone: 'America/Los_Angeles',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Chicago',
|
||||||
|
latitude: 41.8781,
|
||||||
|
longitude: -87.6298,
|
||||||
|
country: usa,
|
||||||
|
timezone: 'America/Chicago',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'New York City',
|
||||||
|
latitude: 40.7128,
|
||||||
|
longitude: -74.0060,
|
||||||
|
country: usa,
|
||||||
|
timezone: 'America/New_York',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Los Angeles',
|
||||||
|
latitude: 34.0522,
|
||||||
|
longitude: -118.2437,
|
||||||
|
country: usa,
|
||||||
|
timezone: 'America/Los_Angeles',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
22
db/seeds/cities/vietnam.rb
Normal file
22
db/seeds/cities/vietnam.rb
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
vietnam = Country.find_by code: 'VN'
|
||||||
|
|
||||||
|
City.create!([
|
||||||
|
{
|
||||||
|
name: 'Ho Chi Minh City',
|
||||||
|
latitude: 10.8231,
|
||||||
|
longitude: 106.6297,
|
||||||
|
country: vietnam,
|
||||||
|
timezone: 'Asia/Ho_Chi_Minh',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hanoi',
|
||||||
|
latitude: 21.0285,
|
||||||
|
longitude: 105.8542,
|
||||||
|
country: vietnam,
|
||||||
|
timezone: 'Asia/Ho_Chi_Minh',
|
||||||
|
active: true,
|
||||||
|
priority: 100
|
||||||
|
}
|
||||||
|
])
|
@ -32,7 +32,7 @@ namespace :geo do
|
|||||||
region.update!(
|
region.update!(
|
||||||
name: data["name"],
|
name: data["name"],
|
||||||
code: data["name"],
|
code: data["name"],
|
||||||
translations: data["translations"].to_json.to_s,
|
translations: data["translations"],
|
||||||
flag: data["flag"] || true,
|
flag: data["flag"] || true,
|
||||||
wiki_data_id: data["wikiDataId"]
|
wiki_data_id: data["wikiDataId"]
|
||||||
)
|
)
|
||||||
@ -55,7 +55,7 @@ namespace :geo do
|
|||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
subregion.update!(
|
subregion.update!(
|
||||||
translations: data["translations"].to_json,
|
translations: data["translations"],
|
||||||
flag: data["flag"] || true,
|
flag: data["flag"] || true,
|
||||||
wiki_data_id: data["wikiDataId"]
|
wiki_data_id: data["wikiDataId"]
|
||||||
)
|
)
|
||||||
@ -106,8 +106,8 @@ namespace :geo do
|
|||||||
tld: data["tld"],
|
tld: data["tld"],
|
||||||
native: data["native"],
|
native: data["native"],
|
||||||
nationality: data["nationality"],
|
nationality: data["nationality"],
|
||||||
timezones: data["timezones"].to_json,
|
timezones: data["timezones"],
|
||||||
translations: data["translations"].to_json,
|
translations: data["translations"],
|
||||||
latitude: data["latitude"],
|
latitude: data["latitude"],
|
||||||
longitude: data["longitude"],
|
longitude: data["longitude"],
|
||||||
emoji: data["emoji"],
|
emoji: data["emoji"],
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
require "test_helper"
|
|
||||||
|
|
||||||
class RssControllerTest < ActionDispatch::IntegrationTest
|
|
||||||
# test "the truth" do
|
|
||||||
# assert true
|
|
||||||
# end
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user