пишемо i18n - локалізацію-мультимовність - на erlang

маленька замітка про інтерналізацію - локалізацію -
мультимовність на вебсайті написаному на erlang :)

простенький велосипед, щоб не чіпати монстрів типу gettext -

загалом алгоритм наступний:

  1. беремо значення мови з куки/заголовку/бази даних etc (цей код ми не розглядаємо зараз)
  2. в залежності від мови - викликатимемо відповідний модуль з перекладами
  3. функція, яка визначає plural forms

це все :)
поїхали -

для зручності використання у великому проекті я використовую два ключі замість одного

файл tr_en.erl

-module(tr_en).

-export([
  tr/2
]).


%%tr(Key1, Key2) -> Value

tr(main, hello) -> <<"Hello">>;

tr(some, apples) -> [<<"apple">>, <<"apples">>, <<"apples">>];

tr(_, _) -> <<"K-V not found">>.


файл tr_uk.erl

-module(tr_uk).

-export([
  tr/2
]).


%%tr(Key1, Key2) -> Value

tr(main, hello) -> <<"Привіт"/utf8>>;

tr(some, apples) -> [<<"яблуко"/utf8>>, <<"яблука"/utf8>>, <<"яблук"/utf8>>];

tr(Key1, Key2) -> tr_en:tr(Key1, Key2). %% default en

файл tr.erl

-module(tr).

-export([
  tr/3,
  tr/4,
  plural/4
]).


%%lang_to_module(Lang)
lang_to_module(uk) -> tr_uk;
lang_to_module(_) -> tr_en.


%% plural forms
plural(Count, T1, T2, T3) ->
  N1 = Count rem 100,
  case ( (N1 > 4) andalso (N1 < 20) ) of
    true -> T3;
    _ ->
      case ( Count rem 10 ) of
        0 -> T3;
        1 -> T1;
        2 -> T2;
        3 -> T2;
        4 -> T2;
        _ -> T3
      end
  end.

%> tr:plural(1, "яблуко", "яблука", "яблук").
%"яблуко"
%> tr:plural(2, "яблуко", "яблука", "яблук").
%"яблука"
%> tr:plural(5, "яблуко", "яблука", "яблук").
%"яблук"


%%tr(Lang, Key1, Key2) -> Value
%%tr(Lang, Key1, Key2, Number) -> Value


tr(Lang, Key1, Key2) ->
  Mod = lang_to_module(Lang),
  Mod:tr(Key1, Key2).


tr(Lang, Key1, Key2, Num) ->
  Mod = lang_to_module(Lang),
  [T1, T2, T3] = Mod:tr(Key1, Key2),
  plural(Num, T1, T2, T3).

використання:

> tr:tr(uk, main, hello).

> tr:tr(uk, some, apples, 2).

це все :)