Discussion:
Using constants for text domain
Justas Butkus
2013-11-27 13:38:12 UTC
Permalink
Hi all.

In a recent response to "Best way to allow slug rewrite of CPT via i18n"
by Otto I saw him warning against use of defined constant for the text
domain.

What is the reasoning behind this, are there any exceptions to this rule?

We are proxying calls to gettext functions (__, _x, ...) family via our
class, so the result is much like this:
```
class PluginPrefix_Foo {

public function __( $string ) {
return __( $string, PLUGINPREFIX_TEXT_DOMAIN );
}

}
```
--
Regards,
Justas Butkus
J.D. Grimes
2013-11-27 13:57:40 UTC
Permalink
The reason that your setup is a bad idea is because it won’t be possible to generate the POT file automatically with the available programs. Your text domain should always be a string, otherwise the POT generators won’t pick it up properly. The same also goes for the strings being gettexted, which is why, although your system will work, it won’t be easy to generate your POT files automatically. The POT generator won’t recognize your functions as gettext functions, so it won’t pick up those strings either.

-J.D.
Post by Justas Butkus
Hi all.
In a recent response to "Best way to allow slug rewrite of CPT via i18n" by Otto I saw him warning against use of defined constant for the text domain.
What is the reasoning behind this, are there any exceptions to this rule?
```
class PluginPrefix_Foo {
public function __( $string ) {
return __( $string, PLUGINPREFIX_TEXT_DOMAIN );
}
}
```
--
Regards,
Justas Butkus
_______________________________________________
wp-hackers mailing list
http://lists.automattic.com/mailman/listinfo/wp-hackers
Justas Butkus
2013-11-27 14:03:02 UTC
Permalink
Given that we generate the POT files on our own (extending existing
tools, i.e. MakePOT) - these issues seems to be related only to building
of the release package, and not running the script itself? Or am I still
missing something?

While the benefit of that seems the possibility to catch text-domain
misuse error early. I mean with function call it either fails, if you
mistype it's name, or returns the correct result, and the process is
reentrable. Whilst using static text string it may get silently ignored,
creating new text domains.
--
Thanks for the response,
Justas Butkus
Post by J.D. Grimes
The reason that your setup is a bad idea is because it won’t be possible to generate the POT file automatically with the available programs. Your text domain should always be a string, otherwise the POT generators won’t pick it up properly. The same also goes for the strings being gettexted, which is why, although your system will work, it won’t be easy to generate your POT files automatically. The POT generator won’t recognize your functions as gettext functions, so it won’t pick up those strings either.
-J.D.
J.D. Grimes
2013-11-27 15:34:30 UTC
Permalink
While the benefit of that seems the possibility to catch text-domain misuse error early. I mean with function call it either fails, if you mistype it's name, or returns the correct result, and the process is reentrable. Whilst using static text string it may get silently ignored, creating new text domains.
I also worry about those mistakes, which is why I created this: https://github.com/JDGrimes/wp-l10n-validator
Justas Butkus
2013-11-27 15:50:49 UTC
Permalink
Post by J.D. Grimes
I also worry about those mistakes, which is why I created this: https://github.com/JDGrimes/wp-l10n-validator
Seems like this might have found it's place within PHP_CodeSniffer, as
part of some (or independent) ruleset.

Thank you for sharing.
--
Regards,
Justas Butkus
Otto
2013-11-27 19:46:57 UTC
Permalink
Given that we generate the POT files on our own (extending existing tools,
i.e. MakePOT) - these issues seems to be related only to building of the
release package, and not running the script itself? Or am I still missing
something?
What you're missing here is that your wrapper system required you to build
a whole extra process to build the POT files yourself instead of using
standard tools that somebody else built.

If you want to manually handle your translations, then that's fine and you
can do it how you please. I'd prefer to not have to handle my own
translations, and to use standardized tools to let me crowdsource them. Or
even better, to offload the whole process to WordPress.org and gain
benefits like speed and smaller filesizes.

Imagine a system where the WordPress.org plugin/theme directory
automatically scans all plugins/themes and builds POT files for you. Then
it uploads them into a GlotPress instance, allowing translators all over
the world to work together to build various language packs for them.
Strings used in one plugin/theme can be quickly translated in a different
one, through suggestions generated by textual similarities. A big database
of all strings used in all plugin/theme code, with translations provided
and approved by the user communities themselves. Automated PO/MO file
generation. Automated updates to users, separate from the plugin/theme. No
more bumping versions just to get updated language packs out there.

For such a grandiose system to actually work, those __() function calls
need to be machine-readable. No PHP variables. No PHP constants. Just plain
strings. C'mon, work with us here.

-Otto
Ryan McCue
2013-11-27 14:07:16 UTC
Permalink
Post by Justas Butkus
What is the reasoning behind this, are there any exceptions to this rule?
The reason it's a bad idea is because the static analysis tools used to
generate the POT files won't recognise it automatically.

It's OK if you're writing your own generation scripts, but some people
will parse the code themselves (using POEdit/etc), so you may want to
mention it in your documentation.
--
Ryan McCue
<http://ryanmccue.info/>
Justas Butkus
2013-11-27 14:30:24 UTC
Permalink
Thank you for explaining.

As I said - we are doing this to allow easier modification, if any would
be needed (despite anything - it's still easier to change one function,
than all usage places) and catch errors (those who haven't ever made a
mistake may throw their bits and bytes at me).
--
Regards,
Justas Butkus
Post by Ryan McCue
The reason it's a bad idea is because the static analysis tools used to
generate the POT files won't recognise it automatically.
It's OK if you're writing your own generation scripts, but some people
will parse the code themselves (using POEdit/etc), so you may want to
mention it in your documentation.
Otto
2013-11-27 19:28:38 UTC
Permalink
Post by Justas Butkus
We are proxying calls to gettext functions (__, _x, ...) family via our
```
class PluginPrefix_Foo {
public function __( $string ) {
return __( $string, PLUGINPREFIX_TEXT_DOMAIN );
}
}
```
... and that fails on two entirely different levels. ;)

Rather than explain in great detail, I'll refer you to three of my posts:

1.
http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/

2. http://ottopress.com/2012/more-internationalization-fun/

3. http://ottopress.com/2013/language-packs-101-prepwork/

The first one will explain why using $string and PLUGINPREFIX_TEXT_DOMAIN
are incorrect.

The second one will make you aware of a few more functions you might not
know about.

The third will tell you how to refactor a bit so that you can properly
support the upcoming Language Pack system in WordPress.

If you have questions, ask. :)

-Otto
Justas Butkus
2013-11-28 08:16:28 UTC
Permalink
Post by Otto
... and that fails on two entirely different levels. ;)
1.
http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/
2. http://ottopress.com/2012/more-internationalization-fun/
3. http://ottopress.com/2013/language-packs-101-prepwork/
The first one will explain why using $string and PLUGINPREFIX_TEXT_DOMAIN
are incorrect.
The second one will make you aware of a few more functions you might not
know about.
The third will tell you how to refactor a bit so that you can properly
support the upcoming Language Pack system in WordPress.
If you have questions, ask. :)
Hello.

Thank you, Otto, for taking time. I will only respond to this message,
as I see your other message repeats, in some portions, what you have
posted previously on your blog.

I believe it's quite obvious that the last entry from your blog makes
the greatest impression.
We have been employing some internal solution based on GlotPress,
despite we are not providing translations of our own, except for the
one, that users contribute, and that takes time to review, adjust, etc.
for inclusion in some release.

Even if language packs are not yet available and built on WordPress - we
are very likely to change our build process.
Though as plugin-specific class was introduced for several reasons, it's
likely to stay in development environment, but as long as we employ
tools, which operate on AST level, it might be rather trivial to replace
the calls to our methods to their counterpart methods from WordPress
stack, modifying and/or amending arguments as needed.

While two first articles are interesting, but I believe anyone working
in a multinational team is likely to learn fast and early, that grammar
is not alike across languages. Actually on your second article I am
missing information about plural forms, which allow virtually infinite
translation table entries for `_n` family calls, bottom line being that
WordPress handles it the way it should.

Another thing which keeps me interested for quite long - how well
translators, who have nil programming experience, handle variable
swapping - given initial entry is '%d', how likely a translator is to
change it to '%3$d'. That either tells me, that we have to always put
full specifier ('I will have %1$d tacos and %2$d buritos'), or turn to
using non-positional system, like 'I will have {number_tacos} tacos and
{number_buritos} buritos', which would be later replaced with
appropriate values, but that might also cause the confusion, when
translator might decide to change '{number_tacos}' to '{@!#!@_!@#@!}'.
But this is clearly not the point of this discussion.

One last thing remains on my mind, which is likely to generate some
heat, which I would like to avoid, but I can't ignore the issue. The
performance case. Assume we know, that we are going to call `date_i18n`
some thousand times during a page load. With just three distinct forms
which all are static and used within a single loop that has no external
dependency, thus voiding possibility of translation string modification
in between. Just for the sake of discussion - assume, that we have a way
to ensure, that no dynamic elements are to be introduced in the final
string. In that sense it seems kind of logical, to use intermediate
representation, which generates the resulting string, which might then
be passed to some simplified date (timestamp) formatter. As I said -
just for the sake of discussion it would be good if we could assume we
have really analysed the data, intermediate forms, resulting forms as
well as resolved date adjustment issues. Also I would prefer to not get
into the discussion about incremental loading and the likes here. What's
your view on this issue? As using some cache might shave a full second,
resulting in generously acceptable, instead of terribly slow. This is
accidentally last - it's important to us, and we have employed several
different solutions.

Once again - thank you for your kind responses. And for pointing at the
planned introduction of language packs - which seems like a really
awesome addition to WordPress.
--
Regards,
Justas Butkus
Loading...