5 ms·
I've never worked on a localized project but Fluent's explanation for why they use identifiers makes a lot of sense to me. I didnt see anything in your blog pos
by iudqnolq 3y ago
I've never worked on a localized project but Fluent's explanation for why they use identifiers makes a lot of sense to me. I didnt see anything in your blog post addressing their issues with English source identifiers.
https://github.com/projectfluent/fluent/wiki/Fluent-vs-gettext#social-contract https://github.com/projectfluent/fluent/wiki/Fluent-vs-gette...
> The most important difference between gettext and Fluent is the choice of a message identifier. Gettext approaches the problem by taking the source string (often English). While the choice seem simple, it has long standing consequences in form of two limitations that this choice imposes.
First of all, it means that any change to the source string invalidate all translations of the string. This severely increases the burden on the developers to never alter messages in the source language as it results in all translations having to be updated.
> Secondly, it makes it harder to introduce multiple messages with the same source string which should be translated differently ...
> Fluent establishes a social contract between the developer and localizers. The developer introduces a unique identifier and provides a set of variables such as number of unread emails or the name of the user, and localizers are using Fluent syntax features to construct the best possible translation for that identifier.
- tmpfs 3y agoExactly, thanks for highlighting this, it always really irked me about the gettext design that they were tightly coupled to the source translations.
- comex 3y agoI’ve never worked on localization either, but I do spend a lot of time reading other people’s source code, and I always find it mildly annoying when a project uses identifiers because it means I have to grep twice: once for the message (to find the identifier) and once for the identifier (to find the code that uses it). In projects that embed messages directly, I only have to grep once. I’ve wondered about the possibility of having the best of both worlds: have the source code contain the full English message (and no other identifier), but use a tool that automatically assigns identifiers to source code locations that contain messages. Different locations would get different identifiers even if they use the same string. The tool would have to be history-aware, in order to keep the identifier the same if the code is moved or if the message is edited. It would have to use heuristics to differentiate between “message was edited” and “message was deleted, and an unrelated message was added in roughly the same place”. But in practice this would usually be easy to do. …Or you could simplify things drastically by having the source code contain both the English message and a unique identifier (perhaps just a number rather than anything descriptive). That’s less fun though.
- antipotoad 3y agoThe latter is roughly what we do on the project I work on: English string directly in the source, plus a human-readable identifier that helps translators understand the context of the string they’re translating. One script to extract all strings, and another to load all translations. Works fine really.
- avgcorrection 3y agoA double grep sounds easy to automate. FWIW I do the same thing in our code.
- beagle3 3y agoWeb2py solves the 2nd problem, by stripping everything after the last hash sign (#) if using the original string, but still using the entire string to look up translations. It’s a joy to use. Technically, it also solves the first problem - because there is also a “no translation” translation, and you can make the changes there instead of in the source code - no worse than Fluent in terms of work - but a lot more confusing down the line, so I wouldn’t refer to it as a solution.
- avgcorrection 3y ago> Web2py solves the 2nd problem, by stripping everything after the last hash sign (#) if using the original string, Sounds good. Since it is the last one then it will also handle something like this: Fetch grocery item #{number} # groceries
- beagle3 3y agoYes. If the string contains a #, you must append another # at the end to “escape” it.