diff --git a/public/editor.css b/public/editor.css index 115fd2f..7a49f21 100644 --- a/public/editor.css +++ b/public/editor.css @@ -14,7 +14,7 @@ } .example-editor .ace_editor { - line-height: 1.2rem !important; + line-height: 1.2rem; } .example-editor .ace_editor .ace_cursor { @@ -49,7 +49,7 @@ } .example-editor .ace_editor .ace_string { - color: var(--code-string-color); + color: var(--code-string-color); } .example-editor .ace_editor .ace_number { @@ -81,7 +81,7 @@ box-shadow: 0 0 3px 0px white; } -.example-editor .ace_editor.ace_nobold .ace_line > span { +.example-editor .ace_editor.ace_nobold .ace_line>span { font-weight: normal !important; } @@ -105,4 +105,4 @@ .example-editor .ace_editor .ace_error { background: #ffa5a5 !important; -} +} \ No newline at end of file diff --git a/public/fluent.css b/public/fluent.css index 0b4da9e..a547b98 100644 --- a/public/fluent.css +++ b/public/fluent.css @@ -40,41 +40,34 @@ body { font-weight: 300; background-color: var(--main-bg-color); color: var(--main-bg-text-color); - min-width: 370px; line-height: 1.3rem; display: grid; - grid-template-columns: - [full-start] minmax(0, 1fr) - [main-start] minmax(0, var(--site-width)) - [main-end] minmax(0, 1fr) - [full-end]; + grid-template-columns: + [full-start] minmax(1rem, 1fr) [main-start] minmax(0, var(--site-width)) [main-end] minmax(1rem, 1fr) [full-end]; } -body > div { - display: inherit; - grid-column: full; - grid-template-columns: inherit; -} - -body > div > * { +body>:is(nav, header, main, section, footer) { grid-column: main; - padding-left: 1rem; - padding-right: 1rem; } +:is(header, main, section) h1 { + font-weight: 300; + font-size: 2rem; + line-height: 1.1; +} -/* Navigation Header */ +/* Navigation Header */ #topbar { display: flex; justify-content: space-between; } -#topbar > .logo { - line-height: var(--height-top-bar); +#topbar>.logo { + line-height: var(--height-top-bar); } -#topbar > .logo > a { +#topbar>.logo>a { display: inline-block; color: var(--logo-color); text-decoration: none; @@ -83,24 +76,27 @@ body > div > * { height: var(--height-top-bar); } -#topbar > ul { +#topbar>ul { list-style: none; + display: flex; + flex-wrap: wrap; + gap: 0.1rem 0.7rem; + justify-content: center; } -#topbar > ul > li { +#topbar>ul>li { display: inline-block; - line-height: var(--height-top-bar); - margin-left: 0.7rem; + line-height: var(--height-top-bar); } -#topbar > ul > li > a { +#topbar>ul>li>a { display: inline-block; color: var(--main-accent-lighter-color); text-decoration: none; height: var(--height-top-bar); } -#topbar > ul > li > a:hover { +#topbar>ul>li>a:hover { color: var(--main-bg-text-active-color); } @@ -113,21 +109,20 @@ body > div > * { padding-bottom: 3rem; } -#intro > h1 { +#intro>h1 { font-size: 4rem; - font-weight: 300; margin: 3.5rem 0; } -#intro > h2 { +#intro>h2 { font-size: 2rem; - line-height: 2.2rem; + line-height: 1.2; font-weight: 300; margin: 3rem auto; max-width: 80%; } -#intro > a.cta { +#intro>a.cta { color: var(--main-accent-darker-color); text-decoration: none; font-size: 1.3rem; @@ -136,7 +131,7 @@ body > div > * { border: 1px solid var(--main-accent-darker-color); } -#intro > a.cta:hover { +#intro>a.cta:hover { background-color: var(--main-accent-darker-color); color: white; } @@ -145,31 +140,29 @@ body > div > * { #above-the-fold { display: flex; - padding-top: 2rem !important; - padding-bottom: 5rem !important; + padding-top: 2rem; + padding-bottom: 5rem; } -#above-the-fold > ul { +#above-the-fold>ul { flex: 1; } -#above-the-fold > ul > li { +#above-the-fold>ul>li { margin-top: 1rem; margin-bottom: 2rem; padding-right: 2rem; } -#above-the-fold > ul > li > h1 { - font-weight: 300; +#above-the-fold>ul>li>h1 { margin-bottom: 1rem; - font-size: 2rem; } -#above-the-fold > ul > li > p > a { +#above-the-fold>ul>li>p>a { color: var(--main-accent-color); } -#above-the-fold > ul > li > p > a:hover { +#above-the-fold>ul>li>p>a:hover { color: var(--main-accent-darker-color); } @@ -187,23 +180,21 @@ body > div > * { line-height: 1.5rem; } -#explainer > h1 { - font-size: 2rem; - font-weight: 300; +#explainer>h1 { margin: 0.5rem 0; } -#explainer > p { +#explainer>p { padding: 0.5rem 0; } -#explainer > p > a { +#explainer>p>a { color: var(--main-accent-text-color); text-decoration: none; font-weight: 400; } -#explainer > p > a:hover { +#explainer>p>a:hover { text-decoration: underline; } @@ -224,8 +215,6 @@ body > div > * { } #examples h1 { - font-size: 2rem; - font-weight: 300; margin: 4rem 0 2rem 0; } @@ -237,16 +226,16 @@ body > div > * { #examples .example-vertical { flex: 4; - border-top: 1px solid var(--main-accent-color); + /* border-top: 1px solid var(--main-accent-color); */ } .example-vertical .variables { border-top: 1px solid #ddd; - border-bottom: 1px solid var(--main-accent-color); + /* border-bottom: 1px solid var(--main-accent-color); */ display: grid; grid-template-columns: 2fr 5fr; grid-template-rows: auto; - grid-row-gap: 0.5rem; + gap: 0.5rem .3rem; } .example-vertical .results { @@ -288,27 +277,27 @@ dl.variables { padding: 1rem; } -dl.variables > dt { +dl.variables>dt { color: var(--code-variable-color); } -dl.variables > dd { +dl.variables>dd { display: flex; } -dl.variables > dd > input { +dl.variables>dd>input { width: 80%; } -dl.variables > dd > input[type=range] { +dl.variables>dd>input[type=range] { height: 1.3rem; } -dl.variables > dd > label { +dl.variables>dd>label { padding: 0 0.5rem; } -dl.variables > dd.radio { +dl.variables>dd.radio { display: grid; grid-template-columns: 1fr 9fr; grid-template-rows: auto; @@ -322,11 +311,11 @@ dl.variables > dd.radio { align-items: start; } -.output > dt { +.output>dt { color: var(--code-id-color); } -.output > dd { +.output>dd { color: var(--code-string-color); } @@ -339,7 +328,7 @@ dl.variables > dd.radio { } .annotation__name { - color: var(--code-error-color); + color: var(--code-error-color); } .annotation__body { @@ -348,14 +337,14 @@ dl.variables > dd.radio { .annotation__slice, .annotation__label { - white-space: pre-wrap; - color: #999; - margin: 0; + white-space: pre-wrap; + color: #999; + margin: 0; } .annotation__name, .annotation__label { - color: #d14; + color: #d14; } @@ -369,21 +358,27 @@ dl.variables > dd.radio { main { display: block; } - - #examples { - display: none; - } } @media (max-width: 30rem) { #topbar { justify-content: end; + padding-top: 1rem; } - #topbar > .logo { + + #topbar>.logo { display: none; } - #topbar > ul > li { + #topbar>ul>li { margin-left: 0.2rem; } -} + + #above-the-fold { + flex-direction: column; + } + + #examples { + display: none; + } +} \ No newline at end of file diff --git a/public/index.html b/public/index.html index 84541d4..937b12d 100644 --- a/public/index.html +++ b/public/index.html @@ -1,340 +1,326 @@ - - - Project Fluent - - - - - - - - - - - - - - -
- + + + + Project Fluent + + + + + + + + + + + + + + + + +
+

+ Fluent +

+

A localization system
for natural-sounding translations.

+ Learn more +
+
+
-
-
- - -
-
-
-
-

Why did we create Fluent?

- Software localization has been dominated by an outdated paradigm: - translations that map one-to-one to the English copy. The - grammar of the source language imposes limits on the expressiveness - of the translation. + Natural-sounding translations with genders and grammatical + cases only when necessary. Expressiveness is not limited by the + grammar of the source language.

+ +
  • +

    + Progressive Enhancement +

    - We created Fluent to change this paradigm. Translators should be - able to use the entire expressive power of their language without - asking developers for permission. In Fluent, translations are - asymmetric. A simple string in English can map to a complex - multi-variant translation in another language. + Translations are isolated; locale-specific logic doesn't leak + to other locales. Authors can iteratively improve translations + without impact on other languages.

    +
  • +
  • +

    + Fully-Featured +

    - Fluent makes it possible to cater to the grammar and style of many - languages, independently of the source language. It happens in - isolation; the fact that one language benefits from more advanced - logic doesn’t require any other localization to apply it. Each - localization is in control of how complex the translation - becomes. + Date, time, and number formatting. Plural categories. + Bidirectionality support. Custom formatters. Easy-to-read + syntax. Runtime translation and re-translation. Robust error + handling.

    -
  • -
    -
    -
    -

    Interactive Walkthrough

    -
    -
    -
    -

    The English Translation

    - -

    - - In Fluent, most messages are simple text strings identified by - an identifier. In the first message in the example, - tabs-close-button is the identifier and - Close is the value. - -

    -

    - - Sometimes, translations require a little bit of logic to sound - right in the target language. In the - tabs-close-tooltip message, the correct variant of - the translation depends on the value of the - $tabCount variable. The names of the variants, - [one] and [other], are standard names - of the plural categories defined by the Unicode in CLDR. - - -

    -

    - - On the other hand, when no logic is required, translations in - Fluent stay simple. The tabs-close-warning message - appears in Firefox when the user tries to close a window with - more than one tab. The message is only displayed when the tab - count is 2 or more, and so in English, the word tab - will always appear as the plural tabs. - -

    -

    - - -sync-brand-name is a special kind of message in - Fluent, called a term. Term identifiers always start - with a dash. Terms can be referenced by other messages, but - cannot be displayed directly in the app. Referencing terms is a - powerful tool for ensuring consistency. Once defined, a - translation can be reused in other translations. - -

    -

    - - The -sync-brand-name term can be referenced from - other messages, and it will always resolve to the same value. - Terms help enforce style guidelines; they can also be swapped - in and out to modify the branding in unofficial builds and on - beta release channels. - -

    -
    -
    - -
    -
    -
    -

    The Italian Translation

    -

    - - In Italian, the messages from the tabs-close - family have a similar structure to their English counterparts. - Even if the languages are different, the grammar requirements - for these particular messages are similar. Fluent doesn't - impose any additional complexity when it's not necessary. - -

    -

    - - The capitalization rules, however, are different in Italian - than in English. Thanks to the asymmetric nature of Fluent, the - Italian translation is free to define two facets of the brand - name. The default one, [uppercase], is suitable - for standalone appearances (sync-dialog-title) - and for beginning of sentences - (sync-headline-title). - -

    -

    - - At the same time, the [lowercase] variant can be - explicitly requested by passing the first: - "lowercase" parameter when the brand name is used inside - a larger sentence in the sync-signedout-title - message. - -

    -
    -
    - -
    -
    -
    -

    The Polish Translation

    - -

    - - The Polish translation illustrates how Fluent caters to yet - more complex grammars. - -

    -

    - - The imperative Close command in - tabs-close-button, Zamknij, still remains - a simple string, same as in English and in Italian. The other - messages in the tabs-close group, however, require - a bit more attention to sound well in Polish. It's related to - the fact that Polish, a Slavic language, has more plural - categories than English (a Germanic language) or Italian (a - Romance language). For example, the Polish translation for - tab takes a different form for counts of 2, 3, and 4 - than it does for 5, 6, or 7. Hence, the - tabs-close-warning message requires additional - variants in Polish: [few] and [many]. - -

    -

    - - Similar to how Italian needed to vary the forms of - -sync-brand-name with regards to the - capitalization, the Polish translation defines three variants - of the brand name corresponding to three grammatical cases: - nominative, genitive, and - accusative. - -

    -

    - - Using terms inside sentences requires care in Polish, which is - an inflected language. The Polish translation can reference the - specific term variant corresponding to the genitive - declension to construct a grammatically correct sentence in the - sync-signedout-title message. - -

    -
    -
    -
    -
    -
    - -
    - - +

    + + In Fluent, most messages are simple text strings identified by + an identifier. In the first message in the example, + tabs-close-button is the identifier and + Close is the value. + +

    +

    + + Sometimes, translations require a little bit of logic to sound + right in the target language. In the + tabs-close-tooltip message, the correct variant of + the translation depends on the value of the + $tabCount variable. The names of the variants, + [one] and [other], are standard names + of the plural categories defined by the Unicode in CLDR. + + +

    +

    + + On the other hand, when no logic is required, translations in + Fluent stay simple. The tabs-close-warning message + appears in Firefox when the user tries to close a window with + more than one tab. The message is only displayed when the tab + count is 2 or more, and so in English, the word tab + will always appear as the plural tabs. + +

    +

    + + -sync-brand-name is a special kind of message in + Fluent, called a term. Term identifiers always start + with a dash. Terms can be referenced by other messages, but + cannot be displayed directly in the app. Referencing terms is a + powerful tool for ensuring consistency. Once defined, a + translation can be reused in other translations. + +

    +

    + + The -sync-brand-name term can be referenced from + other messages, and it will always resolve to the same value. + Terms help enforce style guidelines; they can also be swapped + in and out to modify the branding in unofficial builds and on + beta release channels. + +

    + + + +
    +
    +
    +

    The Italian Translation

    +

    + + In Italian, the messages from the tabs-close + family have a similar structure to their English counterparts. + Even if the languages are different, the grammar requirements + for these particular messages are similar. Fluent doesn't + impose any additional complexity when it's not necessary. + +

    +

    + + The capitalization rules, however, are different in Italian + than in English. Thanks to the asymmetric nature of Fluent, the + Italian translation is free to define two facets of the brand + name. The default one, [uppercase], is suitable + for standalone appearances (sync-dialog-title) + and for beginning of sentences + (sync-headline-title). + +

    +

    + + At the same time, the [lowercase] variant can be + explicitly requested by passing the first: + "lowercase" parameter when the brand name is used inside + a larger sentence in the sync-signedout-title + message. + +

    +
    +
    + +
    +
    +
    +

    The Polish Translation

    + +

    + + The Polish translation illustrates how Fluent caters to yet + more complex grammars. + +

    +

    + + The imperative Close command in + tabs-close-button, Zamknij, still remains + a simple string, same as in English and in Italian. The other + messages in the tabs-close group, however, require + a bit more attention to sound well in Polish. It's related to + the fact that Polish, a Slavic language, has more plural + categories than English (a Germanic language) or Italian (a + Romance language). For example, the Polish translation for + tab takes a different form for counts of 2, 3, and 4 + than it does for 5, 6, or 7. Hence, the + tabs-close-warning message requires additional + variants in Polish: [few] and [many]. + +

    +

    + + Similar to how Italian needed to vary the forms of + -sync-brand-name with regards to the + capitalization, the Polish translation defines three variants + of the brand name corresponding to three grammatical cases: + nominative, genitive, and + accusative. + +

    +

    + + Using terms inside sentences requires care in Polish, which is + an inflected language. The Polish translation can reference the + specific term variant corresponding to the genitive + declension to construct a grammatically correct sentence in the + sync-signedout-title message. + +

    +
    +
    + + + + + \ No newline at end of file diff --git a/src/index.js b/src/index.js index c3615cf..fc30750 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ // vim: ts=4 et sts=4 sw=4 -import React, {Fragment} from 'react'; +import React, { Fragment } from 'react'; import ReactDOM from 'react-dom'; import ftl from "@fluent/dedent"; @@ -42,8 +42,8 @@ function Example0() { } ReactDOM.render( - , - document.getElementById('demo-app') + , + document.getElementById('demo-app') ); const example1 = { @@ -59,7 +59,8 @@ const example1 = { tabs-close-warning = You are about to close {$tabCount -> [one] {$tabCount} tab - *[other] {$tabCount} tabs}. + *[other] {$tabCount} tabs + }. Are you sure you want to continue? ## Syncing