Giter Site home page Giter Site logo

nim-intl's Introduction

The intl Nim package make it easy to do internationalization (i18n) and localization (l10n) in Nim programs.

tests

This is alpha-quality. Please file issues for any bugs you encounter.

Features

  • Compact message format
  • Automatic message extraction during compilation
  • Message format indicates what's been translated
  • Really fast message lookup
  • Flexibility beyond pluralizing
  • Multiple message repositories (e.g. your program has one list of messages, and a library you import has its own)
  • Extracted messages can automatically update message files during compilation (if you want)
  • Select a single locale at compile time and avoid all runtime message lookups.
  • Warn about duplicate message keys for non-matching values
  • Don't require labels for proc messages. See nim-lang/Nim#15004

Quickstart

Intall intl:

nimble install https://github.com/iffy/nim-intl.git

Run the following to generate some boilerplate in the ./trans directory:

intl init

Follow the instructions emitted by intl init to incorporate the newly generated catalog into your code. For instance, add locales for English and Chinese:

intl add en
intl add zh

Create a Nim file (or add some of the following to an existing one):

# main.nim
import ./trans/all
if paramCount() > 0:
  setLocale(paramStr(1))
echo tr"Hello, World!"
intlPostlude(currentSourcePath(), "trans")

Compile, which will automatically extract messages for translation in locale-specific files within ./trans/:

nim c main.nim

Edit trans/zh.nim to perform translation.

# trans/zh.nim - Before translating
import ./base
messages "zh":
  todo 71994, "s_rhellowor71994", r"Hello, World!"
# trans/zh.nim - After translating
import ./base
messages "zh":
  done 71994, "s_rhellowor71994", r"你好,世界!"

Recompile:

nim c main.nim

Run the localized program!

$ ./main en
Hello, World!
$ ./main zh
你好,世界!

More examples

This program prints out one translateable message:

import intl
intlCatalog "myprogram"

# `tr` marks strings for translation
echo tr"Hello, World!"

# Emit extracted messages during compilation
intlPostlude()

Because of the intlPostlude() call, compilation generates the extracted messages, which you can paste back into your code:

## ==== intl postlude ====
baseMessages:
  msg "s_rhellowor71994", r"Hello, World!"
## ==== end intl postlude ====

Let's put the baseMessages: block in as well as the start of a locale for Spanish using messages "localename"::

import intl
intlCatalog "myprogram"

baseMessages:
  msg "s_rhellowor71994", r"Hello, World!"

messages "es":
  discard

echo tr"Hello, World!"
intlPostlude()

Compile this file, and it will provide a fleshed-out set of Spanish messages, ready to be translated:

## ==== intl postlude ====
baseMessages:
  msg "s_rhellowor71994", r"Hello, World!"

messages "es":
  todo 71994, "s_rhellowor71994", r"Hello, World!"
## ==== end intl postlude ====

Changing locale

Use setLocale() to change the locale. The following will print ¡Hola!:

import intl
intlCatalog "myprogram"

baseMessages:
  msg "s_rhellowor71994", r"Hello, World!"

messages "es":
  done 71994, "s_rhellowor71994", r"¡Hola!"

setLocale("es")
echo tr"Hello, World!"
intlPostlude()

Message keys

You may specify the key used to identify each message, rather than the autogenerated one by calling tr with 2 arguments like this:

echo tr("greeting", "Hello, World!")

This produces:

baseMessages:
  msg "greeting", "Hello, World!"

messages "es":
  todo 32096, "greeting", "Hello, World!"

Pluralization

intl let's you use a Nim proc to do whatever is needed for pluralizing. Translators will translate Nim functions. Consider the following:

import intl
intlCatalog "myprogram"

echo "You have " & tr("num-animals", proc(cats:int, dogs:int):string =
  result = $cats & " "
  if cats == 1:
    result.add("cat")
  else:
    result.add("cats")
  result.add " and " & $dogs & " "
  if dogs == 1:
    result.add("dog")
  else:
    result.add("dogs")
  result.add(".")
)(1, 6)

intlPostlude()

Compiling and running produces:

## ==== intl postlude ====
baseMessages:
  msg "num-animals", proc (cats: int; dogs: int): string =
    result = "You have " & $cats & " "
    if cats == 1:
      result.add("cat")
    else:
      result.add("cats")
    result.add " and " & $dogs & " "
    if dogs == 1:
      result.add("dog")
    else:
      result.add("dogs")
    result.add(".")
## ==== end intl postlude ====
You have 1 cat and 6 dogs.

Warning: Because procs can be used, remember to audit translations from other sources.

Tracking

Messages within each messages "locale": block have the following format:

  <status> <hash>, "<key>", <value>

<status> is one of the following:

  • todo - This message needs to be translated. When done translating, the translator should change this to done
  • done - This message is translated. Translators change the status to done to indicate that the translation has been complete.
  • redo - This message possibly needs to be re-translated. The compiler marks messages as redo when the underlying message has changed.
  • gone - This message is no longer present in the source code.

<hash> is an opaque hash computed from the message value. It's used to determine if a messages should be marked as redo. Users should leave this alone.

<key> is the auto-generated or user-provided unique key for this message. Users should leave this alone.

<value> is the localized value for the message. Users should change this.

Automatic catalog updating

If you want intl to automatically update message catalogs, call the postlude like this:

import intl
intlCatalog "mycatalog"
intlPostlude(currentSourcePath(), "trans")

This will cause files to be written in ./trans. After the first time running this, change your main Nim file to this:

import ./trans/all
intlPostlude(currentSourcePath(), "trans")

Add locales by creating empty Nim files named ./trans/XX.nim where XX is the locale name. Recompile and they will be populated with your messages.

Design

Speed

All message lookups are simply attribute access on the currently-selected locale's messages. This is probably fast (though I haven't measured anything). Consider this echo statement:

echo tr"Hello, World!"

In the case where the message is in baseMessages:, it expands to:

echo [selectedMessages_myprogram.s_rhellowor71994]

And if the message hasn't yet been added to baseMessages:, it reverts to the literal value:

echo ["Hello, World!"]

nim-intl's People

Contributors

iffy avatar

Stargazers

charlie.zip avatar niko avatar John Viega avatar prestosilver avatar Carlo Capocasa avatar  avatar Cristian Camilo Ruiz avatar lf_araujo avatar Sebastian avatar

Watchers

 avatar James Cloos avatar  avatar

Forkers

bob16795

nim-intl's Issues

Make some design changes

Revisiting this, my current wishlist is:

  • Make message extraction be a cli command rather than only compiling (e.g. intl extract)
  • Make a way to extract translation data from JavaScript/TypeScript (maybe -- or maybe defining a good enough format for the catalog would make it easy for a JavaScript/TypeScript tool to add things to the catalog). The gist is, I want to use this in my JavaScript project.
  • Make a way to compile translations to JavaScript in a standalone way
  • Retain old catalog items until manually removed
  • Remove the postlude thing
  • Look at what chronicles does with scope to scope translations to particular projects (so that multiple libraries that use intl can be combined without conflict between their translations).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.