ni18n is Super Fast Nim Macros For Internationalization and Localization.
It generates functions for each translation name at compile time. So, there's no runtime translation lookup like HashMap.
Example:
import src/ni18n type Locale = enum English Chinese i18nInit Locale, true: hello: English = "Hello, $name!" Chinese = "你好, $name!" ihaveCat: English = "I've cats" Chinese = "我有猫" withCount: English = proc(count: int): string = case count of 0: "I don't have a cat" of 1: "I have one cat" else: "I have " & $count & " cats" Chinese = proc(count: int): string = proc translateCount(count: int): string = case count of 2: "二" of 3: "三" of 4: "四" of 5: "五" else: $count return case count of 0: "我没有猫" of 1: "我有一只猫" else: "我有" & translateCount(count) & "只猫" # prints "你好, 黄小姐!". This function behave the same as `strutils.format` echo hello(Chinese, "name", "黄小姐") # prints 我有猫 echo ihaveCat(Chinese) # prints 我有五只猫 echo ihaveCat_withCount(Chinese, 5) # or like this ( because Nim compiler is smart! ) echo ihaveCatWithCount(Chinese, 5)
Notes For `ni18n` DSL
DSL has top-level translation definitions and sub-translation definitions. Each translation definition can have multiple sub-translation definitions.
root = seq[topLevelTranslation] ; topLevelTranslation = nameIdent ":" seq[translationPair] ; translationPair = localeIdent "=" translation | nameIdent ":" seq[translationPair] ; translation = nnkStrLit | nnkLambda ;
- Translation must exists for all possible locales.
- nnkLambda must have the same signature for all locales.
Behind the Scene
Imagine u write this code:
type Locale = enum English Chinese i18nInit Locale, true: hello: English = "Hello, $name!" Chinese = "你好, $name!"
Magic macro will convert that code into this:
type Locale = enum English Chinese proc hello_English(args: varargs[string, `$`]): string = format("Hello, $name!", args) proc hello_Chinese(args: varargs[string, `$`]): string = format("你好, $name!", args) proc hello*(locale: Locale, args: varargs[string, `$`]): string = case locale of English: hello_English(args) of Chinese: hello_Chinese(args)
So, we have just locale runtime check, but since that's enum, we're still going fast!
See also
- strutils.`%` proc to learn more about string interpolation.
Macros
macro i18nInit(enumT: typedesc; shouldExportLookup: static bool; translationPairs: untyped): untyped
-
compile translations DSL into locale specific procedures and lookup procedures
- enumT is the enum that contains all available locales
- shouldExportLookup is a boolean that indicates whether to export lookup functions
- translationPairs is a list of translation pairs
In most cases, shouldExportLookup should be set to true because u want to write translations in a separate file and import generated lookup functions from other modules.
Source Edit