将Elm应用程序国际化的好方法是什么?
我需要将ELM HTML应用程序中的UI字符串国际化为3种不同的语言 我正在考虑这样做: 1) 我将从Javascript中获取currentLanguage,并将其传递到ProgramWithFlags中。我将把语言保留在模型中 2) 我将在代码中设置一些类型将Elm应用程序国际化的好方法是什么?,elm,Elm,我需要将ELM HTML应用程序中的UI字符串国际化为3种不同的语言 我正在考虑这样做: 1) 我将从Javascript中获取currentLanguage,并将其传递到ProgramWithFlags中。我将把语言保留在模型中 2) 我将在代码中设置一些类型 type alias Languages = English | French | Spanish -- One of these for each string I want to internationalize type alia
type alias Languages = English | French | Spanish
-- One of these for each string I want to internationalize
type alias InternationalizedStrings = StringHello | StringFoo | StringBar
3) 我将创建一个函数,用于返回每个已翻译的短语,以便在视图中使用
getPhrase: InternationalizationString Languages -> string
getPhrase stringId lang =
case lang of
English ->
case stringId of
StringHello -> "Hello"
StringFoo -> "Foo"
StringBar -> "Bar"
French ->
case stringId of
StringHello -> "Bonjour"
StringFoo -> "Oui"
StringBar -> "Non"
...
有更好的方法吗?我有很多字符串。如果您不提供字符串的翻译,希望编译器出现错误,那么您的解决方案是正确的 如果您想允许尚未翻译的字符串,或者觉得为每个可翻译字符串指定一个类型很乏味,那么您可能需要切换到基于
Dict
的解决方案。要修补它,只需将其放入:
导入Dict公开(Dict)
导入Html(文本)
类型语言
=英语
|法语的
|西班牙文
类型别名键=
一串
主要=
文本键->字符串
翻译语言键=
让
口述=
朗案
英语->
口述从句表
[(“你好”,“英语”)
]
法语->
口述从句表
[(“你好”,“敬礼”)
]
西班牙语->
口述从句表
[(“你好”,“你好”)
,(“仅存在于西班牙语中的关键字”,“42”)
]
在里面
Dict.get key Dict |>Maybe.withDefault(“找不到“++key”的翻译)
不久前,我在国际化方面遇到了一个难题,并提出了以下设置:
- 在全局
模型中定义语言
- 具有一个非常简单的功能,可用于
模块和功能视图
- 函数的签名为
localString:Language->String->String
基本上是在全局字典中进行查找,以找到从您提供的单词到您提供的语言的翻译localString
- 如果找不到您提供的单词,或者找不到您提供的语言的翻译,它将始终返回默认为原始单词的
字符串
- 将全局字典(和helper)函数不保存在模型中,而是保存在一个单独的文件中(它是相当静态的数据,在运行时不会更改)
类型是联合类型,以确保我们只有“批准的”语言李>语言
- 实际字典使用到字符串的转换。
类型不允许强类型作为键Dict
- 您需要在您的
模型中添加
(可以通过JS端口获得)语言
- 您仍然可以在视图中使用简短可读的代码进行翻译,如
p[]文本语言键 语言托基语= 案例语言 英语->“英语” 西班牙语->“西班牙语” 法语->“法语” keyToLanguage:LanguageKey->Language 键语言键= 案例关键 “英语”->英语 “西班牙语”->西班牙语 “法语”->法语 _->默认语言 中文:LocalWord->(语言,LocalWord) 英语单词= (英语,word) 西班牙语:LocalWord->(语言,LocalWord) 西班牙语单词= (西班牙语,word) 法语:LocalWord->(语言,LocalWord) 法语单词= (法语,word) --内部材料 键入别名Word=String 键入别名LocalWord=String 类型alias LanguageKey=String 键入别名字典=Dict Word Dict 键入别名WordDict=Dict language关键字LocalWord init:字典 初始化= Dict.fromList[] newLocalWord:Word->(语言,LocalWord)->可能是WordDict->可能是WordDict newLocalWord(localLanguage,localWord)wordDict= 单词词典 |>Maybe.withDefault(Dict.fromList[]) |>Dict.insert(languageToKey defaultLanguage)单词 |>Dict.insert(language tokey localLanguage)localWord |>只是 addTranslation:Word->(语言,本地单词)->字典->字典 添加翻译词新翻译词典= 词典 |>Dict.updateword(newLocalWord新翻译) localString:Language->Word->LocalWord 本地字符串语言字= 让 词条= Dict.get单词globalDictionary 本地语言= 语言托基语 在里面 案例词条 只需wordDict-> 获取本地语言wordDict |>也许。用默认的词 没有-> 单词 添加:单词->列表(语言,本地单词)->词典->词典 添加单词翻译列表字典= List.foldl(添加翻译词)字典翻译列表 --在下面建立字典 全球词典 全球词典= 初始化 |>加上“你好”[西班牙语“你好”,法语“你好”] |>添加“Man”[西班牙语“Hombre”,法语“Homme”] |>添加“Child”[法语“Enfant”] --对于Elm lang,请仅尝试 本地模型= {语言=西班牙语} 主要= 分区[] [p[]
[text我几个月前写了一篇文章。如果你有能力,试着更喜欢使用ADT而不是
s,因为Dict
s在类型级别上不能给你同样的保证(这就是为什么Dict
返回Dict.get
).ADT还可以检查您正在处理的数据类型类型,您可以对其进行模式匹配,并使用您喜欢的任何可能是a
方法(例如toString
)。也就是说,如果不将解析器从MyPhrase foo bar->“我的短语包含”++toString foo++“&”++bar++“
写入.elm
或.json
中,现有系统/翻译服务可能会使使用此方法变得困难。您可以做的是.po
import Dict exposing (Dict) import Html exposing (text) type Language = English | French | Spanish type alias Key = String main = text <| translate French "Hello" translate : Language -> Key -> String translate lang key = let dict = case lang of English -> Dict.fromList [ ( "Hello", "in english" ) ] French -> Dict.fromList [ ( "Hello", "salut" ) ] Spanish -> Dict.fromList [ ( "Hello", "hola" ) , ( "someKeyThatOnlyExistsInSpanish", "42" ) ] in Dict.get key dict |> Maybe.withDefault ("can not find translation for " ++ key)
import Html exposing (div, p, text) import Dict exposing (Dict) -- Manage your languages below type Language = English | Spanish | French defaultLanguage : Language defaultLanguage = English languageToKey : Language -> LanguageKey languageToKey language = case language of English -> "English" Spanish -> "Spanish" French -> "French" keyToLanguage : LanguageKey -> Language keyToLanguage key = case key of "English" -> English "Spanish"-> Spanish "French" -> French _ -> defaultLanguage english : LocalWord -> (Language, LocalWord) english word = (English, word) spanish : LocalWord -> (Language, LocalWord) spanish word = (Spanish, word) french : LocalWord -> (Language, LocalWord) french word = (French, word) -- Internal stuff type alias Word = String type alias LocalWord = String type alias LanguageKey = String type alias Dictionary = Dict Word WordDict type alias WordDict = Dict LanguageKey LocalWord init : Dictionary init = Dict.fromList [] newLocalWord : Word -> (Language, LocalWord) -> Maybe WordDict -> Maybe WordDict newLocalWord word (localLanguage, localWord) wordDict = wordDict |> Maybe.withDefault (Dict.fromList []) |> Dict.insert (languageToKey defaultLanguage) word |> Dict.insert (languageToKey localLanguage) localWord |> Just addTranslation : Word -> (Language, LocalWord) -> Dictionary -> Dictionary addTranslation word newTranslation dictionary = dictionary |> Dict.update word (newLocalWord word newTranslation) localString : Language -> Word -> LocalWord localString language word = let wordEntry = Dict.get word globalDictionary localLanguage = languageToKey language in case wordEntry of Just wordDict -> Dict.get localLanguage wordDict |> Maybe.withDefault word Nothing -> word add : Word -> List (Language, LocalWord) -> Dictionary -> Dictionary add word translationList dictionary = List.foldl (addTranslation word) dictionary translationList -- BUILD DICTIONARY BELOW globalDictionary : Dictionary globalDictionary = init |> add "Hello" [ spanish "Hola", french "Bonjour" ] |> add "Man" [ spanish "Hombre", french "Homme" ] |> add "Child" [ french "Enfant" ] -- For Elm-lang Try only localModel = { language = Spanish } main = div [] [ p [] [ text <| "Hello in Spanish: " ++ localString localModel.language "Hello" ] , p [] [ text <| "In dictionary, but not in Spanish: " ++ localString localModel.language "Child" ] , p [] [ text <| "Is not in dictionary: " ++ localString localModel.language "Car" ] ]