-
Notifications
You must be signed in to change notification settings - Fork 715
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integration with GNU gettext #165
Comments
So what about {trans url=$url|urlencode what=$what|htmlencode where=$where|htmlencode}I pushed <a href="%url">%what on %where</a>!{/trans} It could be implemented as standard block plugin and the index names of the $params array in the plugin would correspond to %name in the content which could be easily replaced, |
That's true, but:
Is less readable, less maintanable, a little bug magnet (typo on param name vs placeholder name), and longer than:
Plus, with my proposed syntax, migration of non-translatable to translatable sentences is easy, just add Also, using my proposed syntax allow the Finally, rewriting using a preprocessor seems necessary to allow syntax like:
It's clearly more readable, in the case placeholders are used, than giving the plural form as a parameter. I started to work on a demo preprocessor as a smarty plugin (yay) using regex ( :( ) and it works well, I just need some time to meditate on the pro and cons of using it, that's also why I need feedback. |
Great work! I'm searching for a gettext implementation to use myself, and have been looking at these projects: But I really like your proposed syntax. So readable and easy to use!
|
Maybe with this and a callback function when a var is used...example: function smarty_block_translate($params, $content, Smarty_Internal_Template $template, &$repeat)
{
if($repeat) {
$smarty = new Smarty();
$smarty->callback_when_var_is_used(function($var) use( $params) {
return __($params[$var]);
});
$content = $smarty->fetch('string:'.$content);
$repeat = 0;
}
return $content;
} |
@manuelcanga So you're translating variables one by one ? |
I'm just leaving what we do currently, as it addresses i18n from within smarty. We created a function called For example:
Then, the 't' function uses our internal i18n logic to translate that string to the indexed string in a text file based on user language selection. We needed a plain text solution for the translation strings because end-users need to be able to edit them when necessary. As for singular/plural scenarios,
|
I hadn't thought of contexts, but the developer is more than welcome to prefix their i18n string with something meaningful for the context; such as STRING_MENU_PRINTER_OPEN and STRING_MENU_FILE_OPEN. For the example of
In the event that you want one variable repeated, you simply use the index however many times necessary. Such as:
Now, I'm not inferring that my method is the best way to achieve this, in fact I'd love feedback on how it could be improved! It's just how I implemented it thus far. |
And your example can properly encode (given urlencode as u and htmlencode as h, but that's just an example):
Which is nice, how do you disambiguate parameters and quantity ? Also smarty let you pass positional parameters ? How ? About enhancements, I'm clearly not a big fan of having "translations keys" like "STRING_I_PUSHED_LINK_S_S_ON_S", they don't give enough context on what is "S" to the translators, so they force you to produce a first translation (double work). I prefer the GNU gettext approch of having a "C" language which is the "developper one", which can be translated to english and any other language. This way, your untranslated interface is still nice, and you provide a lot of information to translators (an already "correct" sentence). Finally, why not considering using |
I modified Smarty core by changing the line
with
I found it strange that some internal functions could handle positional arugments, but that isn't exposed to 3rd party developers. By going with this approach, any developer can write a function to accept index-based arguments. Albeit this does introduce some ambiguity in some cases, but I felt the chance of ambiguous was outweighed by simple functions, (such as date and other functions that only accept one parameter), being able to have cleaner calls in the template. In my system, the translation string calls the positioned argument by the key Personally, I've found that removing the translation strings away from the template has helped speed up development. eg: I don't have to worry about what text is contained in message N, all I care is that it's STRING_FOR_SOMETHING and move on; the translation can be done later by someone else if necessary. This also helps segregate different portions of codes; eg: the tpl is responsible for the layout and how data is displayed ONLY, the translation strings reside in a different location entirely, just like CSS/JS. This is a little extreme of an example, but it seems logical for me. It's also how Android development functions; the interface XML contains literal strings which are then referenced by the lang files elsewhere. The framework benefits because it has a list of what literal strings are available in the system and translators can benefit because everything they need is in one file, as opposed to digging through the templates to see what's there. I'm also doing a trick of writing the en_US version of the string in the supplemental translation files as a comment just above the literal string. This way if someone bilingual is doing translation, they have the English version of the word/phrase available right there while they're scrolling through the file. One important downside I've found thus far is ini files are single-line only, so if you need to pass in a paragraph for translation, that entire paragraph is on one line :( At some point we may switch to JSON or YAML files to alleviate this, which will be a simple fix in the translation subsystem to check for LANG.yml in addition to LANG.ini, so I'm not overly concerned about that migration. |
@cdp1337 |
@uwetews because there's a test case that checks this exact bug/feature that I fixed. It's expecting an exception to be thrown in that event and using my script it goes through cleanly. Would you like me to update that test case and re-request another pull request? |
@cdp1337 I though a bit of your syntax, and came by to my abandonned git branch where I worked on it on January ^^ First, I prefer the Also, using positional markers is highly important, because a lot of languages use different order in their sentences. But using named markers may be easier for translators to work with, giving them a bit of context about what is what. Using your syntax, and allowing positional arguments, we can do:
Leaving the named arguments to gettext parameters, which is nice and readable:
Yet I prefer my syntax, having the downside of needing a prefilter, which is:
Ultimately the prefilter only change the This last version really mixes text in the template, the complete oposite of hiding the string in a tag like:
I read your argument about "tags speed up development" but I'm not sure I'm getting it. For me, the On the other hand with your syntax, the developer have to declare the TAG in another file, which is more work, and make porting of non-internationalized code very time-consuming. With both syntax, we can imagine a 'xgettext' tool parsing smarty code to automatically generate I currently have an implementation of the prefilter if someone want to test it that I can share, my prefilter changes I still need to write the "xgettext" to have it really usefull, we don't want to generate pot files manually. |
Oddly enough I've never been a huge fan of printf/sprintf... don't know why. Probably why I opted for What I meant by speeding up development is when initially writing the template file I don't have the translation string available so I usually had to come up with it on-the-fly. This usually meant I'd spend a few minutes going back and forth on a few variations instead of continuing on with the template. As for the tag in another file, the framework handles all that automatically. |
About not having the translation while writing the There's, in fact, a very slim difference between allcaps-tags and "C strings", they are tags too, almost not aimed to be shown to users. But they're cool because:
|
See #1005 (comment) |
I think Smarty would beneficiate from a well designed gettext plugin. But to do this, I think we should discuss about what "well designed" mean for a gettext plugin.
Specs:
I'll present the ideas using the following, typical example:
First things first I think we can't use a
|trans
modifier, as modifier parameters can't be modified, and, at least capitalizing a parameter to be given to gettext may be usefull.So we may use either a function:
Or a block:
The example using the function may give:
And with a block:
That's more or less the same but some things to note here:
Just for the record, a version with positional parameters and a context:
To enhance readability one may though of:
That's clearly more readable, sadly it won't work with current implementation of block plugins as content is processed (strings are replaced) before being given to the block.
This may be doable using a preprocessor plugin rewriting the "inplace syntax" to a "parametrized syntax".
Obviously this last syntax need a specialized xgettext that'll replace
{....}
in strings by%1s
,%2s
, etc...: there's NO way we get {$url|urlencode} in po files (Also think that the translation may be used by other languages, so %1s is cool (supported by C, Java, whatever...)I'm waiting for feedback on those ideas, while trying to implement the preprocessor.
The text was updated successfully, but these errors were encountered: