i18n Ideas

Message Syntax (Example)

simple-message = Some translated stuff

internal-reference = Internal Reference
interpolation = Of { internal-reference } and { $external }


plurals =
    { $unreadEmails ->
        [one] You have one unread email.
       *[other] You have { $unreadEmails } unread emails.
    }

# `currency` is usually specified by the caller.
currencies = 
    { NUMBER($price, style: "currency", currency: "EUR") }

dates = 
    { DATETIME($date, day: "2-digit", month: "2-digit", year: "numeric") }
times =
    { DATETIME($time, hour: "2-digit", minute: "2-digit") }

Overlays (Nice to have)

some-message = Read our 
   <some-elem title="Privacy Policy">privacy policy</some-elem>.

+

<Localized id="some-message">
  <a key="some-elem" href="https://www.mozilla.org/privacy" />
</Localized>

=

Read our 
<a href="https://www.mozilla.org/privacy"
  title="Privacy Policy">privacy policy</a>.

Proposed React API

import React from 'react'
import { Localized, Consumer } from 'localization'

interface MyComponentProps {
  href: string
  username: string
}

const MyComponent: React.SFC<MyComponentProps> = ({ href, username }) => (
  <div>
    <Localized id="some-text" props={{ username }}>
      <a href={href} />
    </Localized>
  </div>
)

const MyInput: React.SFC<{}> = () => (
  <Consumer>
    {translate => (
      <input
        type="text" 
        placeholder={translate('some-placeholder', { required: true })} />
    )}
  </Consumer>
)

Codegen

// some-translation =
//    Translation with { $string } 
//    and { NUMBER($number) } 
//    and { DATETIME($date) }

// turns into js code:
const Translations = {
  ["some-translation"]({ string, number, date }) {
    const _number = …format(number)
    const _date = …format(date)
    return `Translation with ${string} and ${_number} and ${_date}`
  }
}

// typescript definitons:
interface Props { string: string, number: number, date: Date }
interface Translate {
  (id: 'some-translation', props: Props): string
  (id: 'returns-react'): React.ReactNode
}

declare var translate: Translate
// … and similar for React Components

this is where the fun starts :-)

Project Plan

* Reuse existing MessageFormat or Fluent parser

  -> figure out how much of the parser we can reuse

* Generate code from translation strings:

  -> simple strings, strings with simple interpolations

  -> more complex things like plurals, numbers, dates

* Generate typescript definitions with correct types

* Make overlays work with react

// simple-msg = Some simple Message.
// -internal = Internal
// interpolated = with { -internal } and { $external } Interpolation

function simpleMsg() {
  return "Some simple Message.";
}
function _internal() {
  return "Internal";
}
function interpolated({ external }) {
  return "with " + _internal() + " and " + String(external) + " Interpolation";
}

export default {
  "simple-msg": simpleMsg,
  "interpolated": interpolated,
};

Progress

Made with Slides.com