-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
New find_xgettext method to i18n module #13900
base: master
Are you sure you want to change the base?
Conversation
9ebc09e
to
4f5283b
Compare
docs/markdown/i18n-module.md
Outdated
@@ -74,3 +74,72 @@ for normal keywords. In addition it accepts these keywords: | |||
* `mo_targets` *required*: mo file generation targets as returned by `i18n.gettext()`. | |||
|
|||
*Added 0.62.0* | |||
|
|||
|
|||
### i18n.pot_extractor() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer a more specific name like find_xgettext
for this function and XgettextProgram
for the object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I'm open changing the names, I'm not sure about find_xgettext
, because I think it would suggest that the returned object is compatible with was is returned by find_program
. Or should it be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think this is a neat idea. I modified it to make the returned object a subclass of ExternalProgram.
b35d6b7
to
9347ef2
Compare
@@ -115,6 +134,161 @@ | |||
} | |||
|
|||
|
|||
class XgettextProgram(ExternalProgram): |
Check failure
Code scanning / CodeQL
Missing call to `__init__` during object initialization Error
method ExternalProgram.__init__
__init__ method
This method return a XgettextProgram object used to extract translatable string from source files into a .pot translation template. It differs from a plain CustomTarget in three ways: - It accepts build targets as sources, and automatically resolves source files from those build targets; - It detects command lines that are too long, and writes, at config time, the list of source files into a text file to be consumed by the xgettext command; - It detects dependencies between pot extraction targets, based on the dependencies between source targets.
@typed_kwargs( | ||
'i18n.find_xgettext', | ||
_ARGS, | ||
KwargInfo('required', bool, default=True), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use the shared option that also handles UserFeatureOptions? Or add the disabler argument. There may be something I'm missing here.
for dep in depends: | ||
source_list += '\n' + path.join(dep.subdir, dep.get_filename()) | ||
|
||
estimated_cmdline_length = len(source_list) + len(arguments) + sum(len(arg) for arg in arguments) + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this code is correct, but it looks really odd because of the way your count the spaces in arguments, I think:
# count the space between each argument as well
estimated_cmdline_length = len(source_list) + sum(len(arg) + 1 for arg in arguments) + 1
would be more clear
|
||
estimated_cmdline_length = len(source_list) + len(arguments) + sum(len(arg) for arg in arguments) + 1 | ||
if estimated_cmdline_length < 8000: | ||
# Maximum command line length on Windows is 8191 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a helper function to calculate an rsp threshold in the ninja backend, which includes an environment variable to tune whether we use an rsp file or not. I wonder if it would be appropriate to use that function here (maybe moved to utils.universal
)? (or possibly it would make more sense to have a way for custom_targets to specify that they can use an RSP file, but that seems like a large out of scope project.
class XgettextProgram(ExternalProgram): | ||
|
||
def __init__(self, xgettext: ExternalProgram, args: T.List[str]): | ||
self.__dict__.update(xgettext.__dict__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this, but I understand why you did this.
- merge `bool`: | ||
if `true`, will merge the resulting pot file with extracted pot files | ||
related to dependencies of the given source targets. For instance, | ||
if you build an executable, then you may want to merge the executable | ||
translations with the translations from the dependent libraries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it should be called "recursive" instead of "merge".
- alias `list[build_tgt]`: | ||
a list of build targets using the same resulting pot file. For | ||
instance, if you build both a static and a shared library from the | ||
same sources, you may specify the static library target as an alias, | ||
to use the generated pot file when that static library is used as a | ||
dependency of another target. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand what this is doing. But it seems backwards somehow.
## i18n module find_xgettext | ||
|
||
There is a new `find_xgettext` function in `i18n` module that acts as a | ||
wrapper around `xgettext`. It allows to extract strings to translate from | ||
source files. | ||
|
||
This function is convenient, because: | ||
- It can find the sources files from a build target; | ||
- It will use an intermediate file when the number of source files is too | ||
big to be handled directly from the command line; | ||
- It is able to get strings to translate from the dependencies of the given | ||
targets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately the goal here is just to avoid the i18n.gettext() assumption that POTFILES is the source of truth for xgettext, right?
It feels like this function adds complexity which doesn't directly serve that. In particular, it seems odd to have a function which finds the program, and then have that yield an object with a single method. We could instead directly provide an i18n.xgettext()
function with the same API contract which internally looks up xgettext, no?
Since the underlying goal as I understand it is essentially "i18n.gettext() is not suitable for my use case because it depends on POTFILES but I would like to calculate the list from meson.build", it feels a bit like a more appropriate solution here could be to teach |
I understood that he also wants to generate multiple .pot files, so that would not be a single POTFILES. |
This method return a PotExtractor object used to extract translatable
string from source files into a .pot translation template.
It differs from a plain CustomTarget in three ways:
files from those build targets;
time, the list of source files into a text file to be consumed by the
xgettext command;
dependencies between source targets.
This does the specific thing I need for my project, that I was trying to implement in a more generic way in #12272 and #11822.