beef331 / website

Code for the official Nim programming language website
https://nim-lang.org
19 stars 1 forks source link

ni18n #69

Closed heinthanth closed 1 year ago

heinthanth commented 1 year ago

Name: ni18n

Author: Hein Thant

ni18n is Super simple, Super Fast Nim macro for internationalization and localization. No runtime lookup for translation since all translations are compiled down to Nim functions ( except we still have a runtime case statement for locale to call correct generated locale specific function )

import 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)

# compiler error here since each function is generated with the same signature from lambda
echo ihaveCat_withCount(Chinese, "some str") 

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!