Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

02 - Up & Running

02-up-and-running.livemd

02 - Up & Running

Mix.install([
  :gettext,
  :ex_cldr,
  :ex_cldr_numbers,
  :ex_cldr_dates_times,
  :ex_cldr_trans,
  :jason
])

# find the current directory, where the livebook is running
{current_dir, _} = System.cmd("pwd", [])

# create new directories for translation files
System.cmd("mkdir", ["-p", "priv/gettext/hi_IN/LC_MESSAGES"])
System.cmd("mkdir", ["-p", "priv/gettext/pt_BR/LC_MESSAGES"])

# create a new ".po" translation file
sample_po_translation_file_hi = """
msgid "%{count} reviews"
msgstr "%{count} समीक्षाएँ"

msgid "Color"
msgstr "रंग"

msgid "Size"
msgstr "आकार"

msgid "Size guide"
msgstr "साइज़ संदर्शिका"
"""

sample_po_translation_file_pt = """
msgid "%{count} reviews"
msgstr "%{count} avaliações"

msgid "Color"
msgstr "Cor"

msgid "Size"
msgstr "Tamanho"

msgid "Size guide"
msgstr "Guia de tamanho"
"""

{:ok, file} = File.open("priv/gettext/hi_IN/LC_MESSAGES/default.po", [:write, :utf8])
IO.write(file, sample_po_translation_file_hi)

{:ok, file} = File.open("priv/gettext/pt_BR/LC_MESSAGES/default.po", [:write, :utf8])
IO.write(file, sample_po_translation_file_pt)

# define a gettext backend module
defmodule DemoApp.Gettext do
  use Gettext, otp_app: :foo
end

# define a CLDR backend module
defmodule DemoApp.Backend do
  use Cldr,
    locales: ["en", "de", "pt", "hi"],
    default_locale: "en",
    providers: [Cldr.Number, Cldr.DateTime, Cldr.Trans],
    json_library: Jason
end

# Set an app-wide default backend
Application.put_env(:ex_cldr, :default_backend, DemoApp.Backend)
Generating DemoApp.Backend for 5 locales named [:de, :en, :hi, :pt, :und] with a default locale named :en
:ok

Translating static strings with gettext

# the 'locale' of the current Elixir process can be set explicitly

Gettext.put_locale("pt_BR")
Gettext.get_locale()
"pt_BR"
# import your app's gettext 'backend' module to have the markup functions available
import DemoApp.Gettext
DemoApp.Gettext
# static strings that are marked-up using gettext, can be translated at runtime

gettext("Color")
|> IO.inspect()

gettext("Size")
|> IO.inspect()

gettext("Size guide")
|> IO.inspect()

:ok
"Cor"
"Tamanho"
"Guia de tamanho"
:ok
# if a translation is not available, the original string in the 'default' language is returned

gettext("This has not been translated yet.")
"This has not been translated yet."
# variables can be interpolated dynamically

num_reviews = 117
gettext("%{count} reviews", count: num_reviews)
"117 avaliações"
# we can wrap code our code to set a different locale explicitly

Gettext.put_locale("pt_BR")

Gettext.with_locale("hi_IN", fn ->
  gettext("%{count} reviews", count: num_reviews)
  |> IO.inspect(label: :hi_IN)
end)

gettext("%{count} reviews", count: num_reviews)
|> IO.inspect(label: :pt_BR)

:ok
hi_IN: "117 समीक्षाएँ"
pt_BR: "117 avaliações"
:ok

Handling variables with ex_cldr

Cldr.Number.to_string!(59.95, locale: "hi-IN", currency: "USD")
|> IO.inspect()

Cldr.Number.to_string!(59.95, locale: "pt-BR", currency: "USD")
|> IO.inspect()

Cldr.Number.to_string!(59.95, locale: "de-DE", currency: "USD")
|> IO.inspect()

:ok
"$59.95"
"US$ 59,95"
"59,95 $"
:ok
Cldr.Date.to_string!(~D[1985-12-21], format: :short, locale: "en-US")
|> IO.inspect()

Cldr.Date.to_string!(~D[1985-12-21], format: :short, locale: "hi-IN")
|> IO.inspect()

Cldr.Date.to_string!(~D[1985-12-21], format: :short, locale: "de-DE")
|> IO.inspect()

:ok
"12/21/85"
"21/12/85"
"21.12.85"
:ok
now = DateTime.now!("Etc/UTC")
earlier = DateTime.add(now, -300)

Cldr.DateTime.Relative.to_string!(earlier, relative_to: now, locale: "en-US")
|> IO.inspect()

Cldr.DateTime.Relative.to_string!(earlier, relative_to: now, locale: "de-DE")
|> IO.inspect()

Cldr.DateTime.Relative.to_string!(earlier, relative_to: now, locale: "pt_BR")
|> IO.inspect()

:ok
"5 minutes ago"
"vor 5 Minuten"
"há 5 minutos"
:ok

Translating database records with ex_cldr_trans

defmodule DemoApp.Product do
  use Ecto.Schema
  use DemoApp.Backend.Trans, translates: [:title, :description]

  schema "products" do
    field(:title, :string)
    field(:description, :string)
    # use the 'translations' macro to set up a map-field with a set of nested 
    # structs to handle translation values for each configured locale and each 
    # translatable field
    translations(:translations)
  end
end
{:module, DemoApp.Product, <<70, 79, 82, 49, 0, 0, 20, ...>>,
 [__schema__: 1, __schema__: 1, __schema__: 1, __schema__: 1, __schema__: 2, __schema__: 2, ...]}
DemoApp.Product.Translations.__schema__(:fields)
[:de, :hi, :pt]
product = %DemoApp.Product{
  title: "Basic Tee 6-Pack",
  description: "The Basic Tee 6-Pack allows you to fully express your vibrant personality ...",
  translations: %DemoApp.Product.Translations{
    pt: %DemoApp.Product.Translations.Fields{
      title: "camiseta básica",
      description:
        "O Basic Tee 6-Pack permite que você expresse totalmente sua personalidade vibrante ..."
    }
    # de: ...,
    # hi: ...
  }
}

IO.inspect(product.title)
IO.inspect(product.description)

product_pt = Cldr.Trans.Translator.translate(product, :pt)

IO.inspect(product_pt.title)
IO.inspect(product_pt.description)

:ok
"Basic Tee 6-Pack"
"The Basic Tee 6-Pack allows you to fully express your vibrant personality ..."
"camiseta básica"
"O Basic Tee 6-Pack permite que você expresse totalmente sua personalidade vibrante ..."
:ok