stasm | 4 months ago | on: OpenMW 0.50.0 Released – open-source Morrowind reimplementation
stasm's comments
stasm | 2 years ago | on: The Wikimedia Foundation joins Mastodon and the Fediverse
It seems like a wasted opportunity to set up a new domain (in this case: wikimedia.social) rather than use an existing one with a subdomain, e.g. social.wikimedia.org or social.wikimediafoundation.org. With a new domain I still have to do the work to verify whether the domain is indeed owned by the Wikimedia Foundation.
stasm | 3 years ago | on: JavaScript and TypeScript features of the last 3 years
One of the reasons was to allow private and public fields of the same name, so that subclasses are free to add own public fields without accidentally discovering private fields of superclasses. There were many more considerations that went into the design: https://github.com/tc39/proposal-class-fields/blob/main/PRIV....
There was a heated debate about this and the choice of the # sigil back in 2015 at the time private fields were being designed: https://github.com/tc39/proposal-private-fields/issues/14.
stasm | 3 years ago | on: Get in zoomer, we're saving React
How does macOS achieve its reactivity? Is it two-way bindings? Events/messages? Immediate mode re-renders?
stasm | 3 years ago | on: A 14kb page can load much faster than a 15kb page
stasm | 3 years ago | on: Ask HN: Does anybody still use bookmarking services?
If it's something I may want to come back to, or something that I'd be sad if it disappeared from the web, I save it to a synced folder using the SingleFile extension which inlines all content into a single HTML file.
stasm | 4 years ago | on: First look: adding type annotations to JavaScript
let user = new User();
let user: User = new User();stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
That's an interesting suggestion! Right now, the identifier between the brackets is required, but we could relax this in the future. In 1.0, we erred on the side of more conservative and explicit design, to improve the readability and discoverability of the syntax for translators.
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
n % 10 = 1 and
n % 100 != 11 or
v = 2 and
f % 10 = 1 and
f % 100 != 11 or
v != 2 and
f % 10 = 1
…where n is the absolute value of the number, f is the visible fractional digits with trailing zeros, and v is _the number_ of visible fraction digits with trailing zeros. Some rules can get even more complex than that; see [0] and [1].It's safer and more robust to rely on the plural categories defined by the Unicode: (zero | one | two | few | many | other), and by the APIs provided by the platform (ICU, Intl.PluralRules, etc.).
[0] http://www.unicode.org/cldr/charts/latest/supplemental/langu...
[1] http://unicode.org/reports/tr35/tr35-numbers.html#Operands
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
```properties
# A comment
hello = Hello, world!
```
This is in fact by design. Properties files are quite nice for simple things. Fluent builds on top of them, and provides modern features like multiline text blocks (as long as it's indented, it's considered text continuation) and the micro-syntax for expressions: {$var}, {$var -> ...} etc.So far, I haven't had much time to invest in building proper highlighting modes for popular editors. There are ACE and Vim modes mentioned in other comments here, and also a slightly outdated https://atom.io/packages/language-ftl20n written by a contributor. I'd love to see more such contributions, and I'll be more than happy to help by reviewing code!
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
Authoring tools can help here, too. Pontoon, Mozilla's translation management system, pre-populates plural variants based on the number of plural categories defined in Unicode's CLDR.
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
> And it would result in combinatorial explosion of translation message versions if source code had to add special case for each quirk in each language.
This is the exact problem we designed Fluent to solve. If you get a chance to try it out, feel free to reach out to me if you questions. I'll be more than happy to help and to hear feedback.
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
We're also working on creating richer and more streamlined authoring experience in Pontoon, Mozilla's translation management system. You can read about the current state of Fluent support in Pontoon in my colleague's post at https://blog.mozilla.org/l10n/2019/04/11/implementing-fluent....
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
https://projectfluent.org/play/?id=2d7ab4b7ed1c4d9656475614f...
It's a complex piece of UI and consequently, the resulting Fluent message is also quite complex. But possible to build :)
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
The Fluent Syntax is a simple declarative DSL. By design, it doesn't allow translators to build complex conditionals or use arithmetic. There is, however, an escape hatch. The problem you described can be solved in Fluent with a little bit of one-time help from the developer of the source code, through a feature of Fluent called custom functions.
Translations in Fluent can use functions to format values or decide between variants. There exist built-in functions like NUMBER and DATETIME. They are rarely used because the Fluent runtime calls them on numeric and temporal values implicitly, but they can be helpful when localizers wish to use custom formatting options.
weekday-today = Today is {DATETIME($today, weekday: "long")}.
See https://projectfluent.org/play/?id=a3540d4f02c104a634adbfc0e... for a live example of DATETIME.There can also be custom functions, defined during the initialization of the runtime. In Firefox, we use one such function called PLATFORM: https://searchfox.org/mozilla-central/rev/d33d470140ce3f9426.... It can be used as follows:
open-preferences = {PLATFORM() ->
[windows] Open Options
*[other] Open Preferences
}
The logic of custom functions is entirely up to developers and the localization needs of the UI. In https://github.com/projectfluent/fluent/issues/228#issuecomm..., for instance, I suggested using a custom function to handle negative and positive floor numbers.A custom function can also cater to the use-case you described. A simple and possibly naive implementation in JavaScript could look like the following one:
function NUMBER_HEAD(num) {
while (num > 999) {
num /= 1e3;
}
let first = num.toString()[0];
return num < 10 ? first
: num < 100 ? first + "x"
: first + "xx";
}
I wrote this with Polish in mind, but it could be useful to other languages in which numerals are named after the first thousand-triple, in a left to right order. Depending on the exact product requirements, the function could be called NUMBER_HEAD_POLISH, or perhaps NUMBER_HEAD_TRIPLE_FIRST_DIGIT :)Once defined, the function can be used as follows:
# The Polish copy can take advantage of the custom function.
page-of = {NUMBER_HEAD($pageTotal) ->
[1xx] Strona {$pageCurrent} ze {$pageTotal}
*[other] Strona {$pageCurrent} z {$pageTotal}
}
This method still requires some work from developers, but it only needs to happen once and in a single palce in code: where the Fluent runtime is initialized. Because they are code, custom functions can be reviewed and tested just as any other code in the code base, to help ensure that they do what they claim to :)Importantly, the use of the custom function is completely opt-in.
# The English copy doesn't need any special handling.
page-of = Page {$pageCurrent} of {$pageTotal}
All localization callsites remain unchanged, and all existing translations remain functional.stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations
We've taken a layered approach to designing Fluent: what we're announcing today is the 1.0 of the syntax and file format specification. The implementations are still maturing towards 1.0 quality, but let me quickly describe what our current thinking is.
For JavaScript, we're working on low-level library which implements a parser of Fluent files, and offers an agnostic API for formatting translations. On top of it we hope to see an ecosystem of glue-code libraries, or bindings, each satisfying the needs of a different use-case or framework.
I've been working on one such binding library called fluent-react. It's still in its 0.x days, but it's already used in a number of Mozilla projects (e.g. in Firefox DevTools). In fluent-react translations can contain limited markup. During rendering, the markup is sanitized and then matched against props defined by the developer in the source code, in a way that overlays the translation onto the source's structure. Hence, this feature is called Overlays. See https://github.com/projectfluent/fluent.js/wiki/React-Overla....
Here's how you could re-implement your example using fluent-react. Note that the <a>'s href is only defined in the prop to the Localized component.
<Localized
id="confirm"
$clickCount={7}
a={<a href="..."></a>}
>
{"Please <a>click here {$clickCount ->
[one] 1 time
*[other] {$clickCount} times
}</a> to confirm."}
</Localized>
I'd love to get more feedback on ideas in fluent-react. Please feel free to reach out if you have more questions!stasm | 7 years ago | on: Fluent 1.0: a localization system for natural-sounding translations