2021-10-02 17:41:25 +02:00
|
|
|
# "bn_BD" => load_locale("bn_BD"), # Bengali (Bangladesh) [Incomplete]
|
|
|
|
# "eu" => load_locale("eu"), # Basque [Incomplete]
|
|
|
|
# "sk" => load_locale("sk"), # Slovak [Incomplete]
|
2021-11-08 22:58:20 +01:00
|
|
|
LOCALES_LIST = {
|
2021-12-22 00:52:08 +01:00
|
|
|
"ar" => "العربية", # Arabic
|
|
|
|
"cs" => "Čeština", # Czech
|
|
|
|
"da" => "Dansk", # Danish
|
|
|
|
"de" => "Deutsch", # German
|
|
|
|
"el" => "Ελληνικά", # Greek
|
|
|
|
"en-US" => "English", # English
|
|
|
|
"eo" => "Esperanto", # Esperanto
|
|
|
|
"es" => "Español", # Spanish
|
|
|
|
"fa" => "فارسی", # Persian
|
|
|
|
"fi" => "Suomi", # Finnish
|
|
|
|
"fr" => "Français", # French
|
|
|
|
"he" => "עברית", # Hebrew
|
|
|
|
"hr" => "Hrvatski", # Croatian
|
|
|
|
"hu-HU" => "Magyar Nyelv", # Hungarian
|
|
|
|
"id" => "Bahasa Indonesia", # Indonesian
|
|
|
|
"is" => "Íslenska", # Icelandic
|
|
|
|
"it" => "Italiano", # Italian
|
|
|
|
"ja" => "日本語", # Japanese
|
|
|
|
"ko" => "한국어", # Korean
|
|
|
|
"lt" => "Lietuvių", # Lithuanian
|
|
|
|
"nb-NO" => "Norsk bokmål", # Norwegian Bokmål
|
|
|
|
"nl" => "Nederlands", # Dutch
|
|
|
|
"pl" => "Polski", # Polish
|
|
|
|
"pt" => "Português", # Portuguese
|
|
|
|
"pt-BR" => "Português Brasileiro", # Portuguese (Brazil)
|
|
|
|
"pt-PT" => "Português de Portugal", # Portuguese (Portugal)
|
|
|
|
"ro" => "Română", # Romanian
|
|
|
|
"ru" => "русский", # Russian
|
|
|
|
"sr" => "srpski (latinica)", # Serbian (Latin)
|
|
|
|
"sr_Cyrl" => "српски (ћирилица)", # Serbian (Cyrillic)
|
|
|
|
"sv-SE" => "Svenska", # Swedish
|
|
|
|
"tr" => "Türkçe", # Turkish
|
|
|
|
"uk" => "Українська", # Ukrainian
|
|
|
|
"vi" => "Tiếng Việt", # Vietnamese
|
|
|
|
"zh-CN" => "汉语", # Chinese (Simplified)
|
|
|
|
"zh-TW" => "漢語", # Chinese (Traditional)
|
2021-03-22 21:49:06 +00:00
|
|
|
}
|
|
|
|
|
2021-11-08 22:58:20 +01:00
|
|
|
LOCALES = load_all_locales()
|
|
|
|
|
2021-10-21 22:30:49 +03:00
|
|
|
CONTENT_REGIONS = {
|
|
|
|
"AE", "AR", "AT", "AU", "AZ", "BA", "BD", "BE", "BG", "BH", "BO", "BR", "BY",
|
|
|
|
"CA", "CH", "CL", "CO", "CR", "CY", "CZ", "DE", "DK", "DO", "DZ", "EC", "EE",
|
|
|
|
"EG", "ES", "FI", "FR", "GB", "GE", "GH", "GR", "GT", "HK", "HN", "HR", "HU",
|
|
|
|
"ID", "IE", "IL", "IN", "IQ", "IS", "IT", "JM", "JO", "JP", "KE", "KR", "KW",
|
|
|
|
"KZ", "LB", "LI", "LK", "LT", "LU", "LV", "LY", "MA", "ME", "MK", "MT", "MX",
|
|
|
|
"MY", "NG", "NI", "NL", "NO", "NP", "NZ", "OM", "PA", "PE", "PG", "PH", "PK",
|
|
|
|
"PL", "PR", "PT", "PY", "QA", "RO", "RS", "RU", "SA", "SE", "SG", "SI", "SK",
|
|
|
|
"SN", "SV", "TH", "TN", "TR", "TW", "TZ", "UA", "UG", "US", "UY", "VE", "VN",
|
2021-10-21 23:38:49 +03:00
|
|
|
"YE", "ZA", "ZW",
|
2021-10-21 22:30:49 +03:00
|
|
|
}
|
|
|
|
|
2021-11-08 22:58:20 +01:00
|
|
|
def load_all_locales
|
|
|
|
locales = {} of String => Hash(String, JSON::Any)
|
|
|
|
|
|
|
|
LOCALES_LIST.each_key do |name|
|
|
|
|
locales[name] = JSON.parse(File.read("locales/#{name}.json")).as_h
|
|
|
|
end
|
|
|
|
|
|
|
|
return locales
|
2018-12-20 15:32:09 -06:00
|
|
|
end
|
|
|
|
|
2021-11-08 23:52:55 +01:00
|
|
|
def translate(locale : String?, key : String, text : String | Nil = nil) : String
|
2021-11-25 19:46:34 +01:00
|
|
|
# Log a warning if "key" doesn't exist in en-US locale and return
|
|
|
|
# that key as the text, so this is more or less transparent to the user.
|
2021-11-21 01:46:35 +01:00
|
|
|
if !LOCALES["en-US"].has_key?(key)
|
|
|
|
LOGGER.warn("i18n: Missing translation key \"#{key}\"")
|
2021-11-25 19:46:34 +01:00
|
|
|
return key
|
2021-11-21 01:46:35 +01:00
|
|
|
end
|
2018-12-20 15:32:09 -06:00
|
|
|
|
2021-11-08 23:52:55 +01:00
|
|
|
# Default to english, whenever the locale doesn't exist,
|
|
|
|
# or the key requested has not been translated
|
|
|
|
if locale && LOCALES.has_key?(locale) && LOCALES[locale].has_key?(key)
|
|
|
|
raw_data = LOCALES[locale][key]
|
|
|
|
else
|
|
|
|
raw_data = LOCALES["en-US"][key]
|
|
|
|
end
|
|
|
|
|
|
|
|
case raw_data
|
|
|
|
when .as_h?
|
|
|
|
# Init
|
|
|
|
translation = ""
|
|
|
|
match_length = 0
|
2019-04-28 14:50:17 -05:00
|
|
|
|
2021-11-08 23:52:55 +01:00
|
|
|
raw_data.as_h.each do |key, value|
|
|
|
|
if md = text.try &.match(/#{key}/)
|
|
|
|
if md[0].size >= match_length
|
|
|
|
translation = value.as_s
|
|
|
|
match_length = md[0].size
|
2019-04-28 14:50:17 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-11-08 23:52:55 +01:00
|
|
|
when .as_s?
|
|
|
|
translation = raw_data.as_s
|
|
|
|
else
|
|
|
|
raise "Invalid translation \"#{raw_data}\""
|
2018-12-20 15:32:09 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
if text
|
|
|
|
translation = translation.gsub("`x`", text)
|
|
|
|
end
|
|
|
|
|
|
|
|
return translation
|
|
|
|
end
|
2019-04-28 14:56:06 -05:00
|
|
|
|
2021-12-21 23:10:03 +01:00
|
|
|
def translate_count(locale : String, key : String, count : Int) : String
|
|
|
|
# Fallback on english if locale doesn't exist
|
|
|
|
locale = "en-US" if !LOCALES.has_key?(locale)
|
|
|
|
|
|
|
|
# Retrieve suffix
|
|
|
|
suffix = I18next::Plurals::RESOLVER.get_suffix(locale, count)
|
|
|
|
plural_key = key + suffix
|
|
|
|
|
|
|
|
if LOCALES[locale].has_key?(plural_key)
|
|
|
|
translation = LOCALES[locale][plural_key].as_s
|
|
|
|
else
|
|
|
|
# Try #1: Fallback to singular in the same locale
|
|
|
|
singular_suffix = I18next::Plurals::RESOLVER.get_suffix(locale, 1)
|
|
|
|
|
|
|
|
if LOCALES[locale].has_key?(key + singular_suffix)
|
|
|
|
translation = LOCALES[locale][key + singular_suffix].as_s
|
|
|
|
else
|
|
|
|
# Try #2: Fallback to english (or return key we're already in english)
|
|
|
|
if locale == "en-US"
|
|
|
|
LOGGER.warn("i18n: Missing translation key \"#{key}\"")
|
|
|
|
return key
|
|
|
|
end
|
|
|
|
|
|
|
|
translation = translate_count("en-US", key, count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return translation.gsub("{{count}}", count.to_s)
|
|
|
|
end
|
|
|
|
|
2021-11-08 23:52:55 +01:00
|
|
|
def translate_bool(locale : String?, translation : Bool)
|
2019-04-28 14:56:06 -05:00
|
|
|
case translation
|
|
|
|
when true
|
|
|
|
return translate(locale, "Yes")
|
|
|
|
when false
|
|
|
|
return translate(locale, "No")
|
|
|
|
end
|
|
|
|
end
|