【问题标题】:Rename *.po to *.mo in Makefile在 Makefile 中将 *.po 重命名为 *.mo
【发布时间】:2015-07-21 17:25:12
【问题描述】:

我需要将 ./lang/ 文件夹中的所有 *.po 翻译文件转换为 *.mo 文件。 在 Makefile 的“i18n”目标中,我写了:

i18n:
@for file in $(wildcard ./lang/*.po); do\
    msgfmt $$file -o $(subst po,mo,$$file); \
done

但是,此代码不起作用;此外,所有的 *.po 文件都被损坏了。

文件夹中有 3 个文件,我得到每个文件:

./lang/uk_UK.po:1:2: syntax error
./lang/uk_UK.po:2: line terminator inside the line
./lang/uk_UK.po:3: Unknown key word «G»
./lang/uk_UK.po:4: Unknown key word «P»
./lang/uk_UK.po:5: Unknown key word «A»
./lang/uk_UK.po:6: Unknown key word «Z»
./lang/uk_UK.po:9: line terminator inside the line
./lang/uk_UK.po:10: Unknown key word «Report»
./lang/uk_UK.po:11: Unknown key word «POT»
./lang/uk_UK.po:12: Unknown key word «PO»
./lang/uk_UK.po:13: Unknown key word «Last»
./lang/uk_UK.po:14: Unknown key word «Language»
./lang/uk_UK.po:15: Unknown key word «Language»
./lang/uk_UK.po:16: Unknown key word «MIME»
./lang/uk_UK.po:17: Unknown key word «Content»
./lang/uk_UK.po:18: Unknown key word «Content»
./lang/uk_UK.po:19: Unknown key word «Entangle»
./lang/uk_UK.po:20: Unknown key word «AES»

因此,该命令似乎在 msgfmt 获取文件之前对其进行了修改。

我花了很多时间尝试不同的解决方案。我遇到了三种类型的问题:

1) 语法错误 - 不正确的循环

2) 替换错误

3) 翻译文件损坏

我的代码有什么问题?

【问题讨论】:

  • 定义“不起作用”。构建日志中有错误吗?
  • 没有错误,没有响应 - 只是翻译文件损坏。
  • 哦,其实有错误!在问题中查看它们。
  • 问题似乎出在以下代码部分:$(subst po,mo,$$file)
  • $(subst) 是一个 make 函数。您正在尝试在 shell 上下文中的 shell 变量上使用它。这行不通。

标签: shell makefile translation rename


【解决方案1】:

您的问题是您将 make 函数(和 make 上下文)与 shell 功能/变量(和 shell 上下文)混合在一起。

i18n:
    @for file in $(wildcard ./lang/*.po); do\
        msgfmt $$file -o $(subst po,mo,$$file); \
    done

$(wildcard)$(subst) 函数在 make 解析时(或适当的变量扩展时)扩展。 shell for 循环在 shell 执行时运行。

因此,虽然您的 $(wildcard) 在 shell 脚本运行之前正确执行(并为您的 for 循环提供一些操作)并因此可以正常工作(某种程度上)$(subst) 调用 在 shell 脚本运行之前执行,因此对字面值 $$file 进行操作,而不是 shell 变量 $file 的扩展。

在这种情况下,事实证明,您可能不想要 既不 $(wildcard) $(subst),而是想要这样的东西:

.PHONY: i18n
i18n:
    @for file in ./lang/*.po; do\
        msgfmt $$file -o "$${file/%po/mo}"; \
    done

.PHONY: i18n 行是必要的,以确保任何东西都创建了 i18n 文件时 make 目标正常工作。

如果 "$${file/%po/mo}" 扩展失败,那么使用 "$${foo%po}mo" 应该可以代替。 // 扩展(用于模式替换)可能是 bash 主义,但 % 扩展(用于后缀删除)是 POSIX。

尽管你实际上可能想要使用更像这样的东西:

.PHONY: i18n
i18n: $(PO_FILES:po=mo)

%.mo: %.po
    msgfmt $< -o $@

让 make 做“这个.mo 文件是否需要更新”检查/等等。并更有效地使用 make 为您所做的事情。

【讨论】:

  • 不幸的是,这些方法都不起作用。第一个产生“错误替换”错误,另一个产生 - “混合隐式和静态样本。停止。”
  • Bleh,第二个错字了。对于那个很抱歉。定影。虽然我认为第一个应该可以工作......除非/bin/sh 不支持您的系统上可能的扩展。为此添加一个替代品。
  • 嗯...也许我做错了什么,但这段代码不起作用:.PHONY: i18n i18n: @for file in ./lang/*.po; do\ msgfmt $$file -o "$${file/%po}mo"; \ done 再次替换错误。如果我删除一个美元符号,它会将翻译保存到一个名为“mo”的文件中。第二个变体有效。
  • 第一个版本的替代扩展中没有/。只是%。无论如何,第二种变体更好。
猜你喜欢
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多