Skip to content

kevinresol/turnwing

Repository files navigation

turnwing

Hackable localization library for Haxe

What?

Type safety

Translations are done with interfaces. You will never mis-spell the translation key anymore.

In many existing localization libraries, the translation function looks like this:

loc.translate('hello', {name: 'World'});
loc.translate('orange', {number: 1});

There is one and only one translation function and its type is String->Dynamic->String. That means it takes a String key, a Dynamic parameter object and returns a substituted string. Several things can go wrong here: wrong translation key, wrong param name or wrong param data type.

With turnwing, we have typed translators. Each of them is a user-defined function and typed specifically.

loc.hello('World'); // String->String
loc.orange(1); // Int->String

Peace of mind

There is only one place where errors could happen, that is when the localization data is loaded.

This is because data are validated when they are loaded. The data provider does all the heavy lifting to make sure the loaded data includes all the needed translation keys and values. As a result, there is no chance for actual translation calls to fail.

Hackable

Users can plug in different implementations at various part of the library.

For example, JsonProvider uses JSON as the underlying localization format. One can easily write a XmlProvider (perhaps with tink_xml).

Also, an ErazorTemplate may replace the default HaxeTemplate implementation.

Usage

import turnwing.*;
import turnwing.provider.*;
import turnwing.template.*;

interface MyLocale {
	function hello(name:String):String;
	function orange(number:Int):String;
	var sub(get, never):SubLocale;
}

interface SubLocale {
	function yo():String;
}

class Main {
	static function main() {
		var source = new ResourceStringSource(lang -> '$lang.json');
		var template = new HaxeTemplate();
		var loc = new Manager<MyLocale>(new JsonProvider<MyLocale>(source, template));
		loc.get('en').handle(function(o) switch o {
			case Success(localizer):
				// data prepared, we can now translate something
				$type(localizer); // MyLocale
				trace(localizer.hello('World')); // "Hello, World!"
				trace(localizer.orange(4)); // "There are 4 orange(s)!"
			case Failure(e):
				// something went wrong when fetching the localization data
				trace(e);
		});
	}
}

// and your json data looks like this:
{
	"hello": "Hello, ::name::!",
	"orange": "There are ::number:: orange(s)!",
	"sub": {
		"yo": "Yo!"
	}
}

Providers

JsonProvider

JsonProvider is a provider for JSON sources. Its data validation is powered by tink_json, which generates the validation code with macro at compile time according to the type information of the user-defined locale interface.

Requires a templating engine to interpolate the parameters. The interface is defined in Template.hx. HaxeTemplate is an implementation based on haxe.Template from the Haxe standard library.

Usage:

var source = new ResourceStringSource(lang -> '$lang.json');
var template = new HaxeTemplate();
var provider = new JsonProvider<MyLocale>(source, template);

To use it, install tink_json and include it as dependency in your project

FluentProvider (JS Only)

FluentProvider is a provider for Fluent.

Messages in the FTL file should be named the same as the Locale interface functions. Nested interfaces should be delimited by a dash (-). Please refer to the files in the tests/data/ftl folder as an example.

At the moment, the validation logic is incomplete and only performs a very rough check. So, runtime error may occur in a locale function call. This will be improved in the future.

Usage:

var source = new ResourceStringSource(lang -> '$lang.ftl');
var provider = new FluentProvider<MyLocale>(source);

To use it, you have to install the npm package @fluent/bundle

About

Type safe & hackable localization library for Haxe

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published