在Makefile

时间:2015-05-11 09:16:02

标签: shell makefile translation rename

我需要将 ./ 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)翻译文件损坏

我的代码出了什么问题?

1 个答案:

答案 0 :(得分:1)

您的问题是您正在使用shell功能/变量(以及shell上下文)混合make函数(和make context)。

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

{make}分析时间(或适当的变量扩展时间)扩展$(wildcard)$(subst)函数。 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行是必要的,以确保make目标在任何内容创建i18n文件时都能正常工作。

如果"$${file/%po/mo}"扩展失败,则应使用"$${foo%po}mo"//扩展(用于模式替换)可能是bash-ism,但%扩展(用于删除后缀)是POSIX。

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

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

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

要让make执行“此.mo文件是否需要更新”检查/等。并且更有效地使用make为你做的事。