ijse / freemarker.js

make freemarker available for node.js with FMPP.
http://freemarker.js.org/
MIT License
111 stars 41 forks source link

数据中有中文导致乱码的问题及解决 #27

Open and80506 opened 7 years ago

and80506 commented 7 years ago

问题描述: 以下代码执行后中文出现乱码

/Users/xx/Downloads/freemarker.js/fmpp/fmpp /Users/xx/Downloads/freemarker.js/test/template/test.ftl -C /var/folders/0d/99l1ldnj1758v9zs8ydjb90m0000gn/T/4f1b37f1-717f-4dad-a622-5506a1b9dbf0

4f1b37f1-717f-4dad-a622-5506a1b9dbf0文件中的内容

logFile: fmpp.log
sourceRoot: /Users/xx/Downloads/freemarker.js/test/template/
outputRoot: /var/folders/0d/99l1ldnj1758v9zs8ydjb90m0000gn/T
data: {
 "word": {
  "user": {
   "sb": "好人呢"
  }
 }
}
outputFile: /var/folders/0d/99l1ldnj1758v9zs8ydjb90m0000gn/T/0864f04b-6f93-4add-b2bb-b506f8b19881

问题定位: fmpp文档有描述原因http://fmpp.sourceforge.net/tdd.html

Character encoding issues

If you load TDD from a file, then FMPP have to use an encoding (charset) to interpret the bytes as text. The default of this encoding depends on how do you load the TDD file:

If it is a configuration file: ISO-8859-1 is used. If it is loaded with tdd data loader as tdd(fileName): sourceEncoding is used. If it is loaded with data loader tdd as tdd(fileName, encoding): the encoding suggested by the 2nd parameter is used.

文件内容稍加修改后正常输出中文字符:

/Users/xx/Downloads/freemarker.js/fmpp/fmpp /Users/xx/Downloads/freemarker.js/test/template/test.ftl -C /var/folders/0d/99l1ldnj1758v9zs8ydjb90m0000gn/T/4f1b37f1-717f-4dad-a622-5506a1b9dbf0

4f1b37f1-717f-4dad-a622-5506a1b9dbf0文件中的内容

# encoding: UTF-8
logFile: fmpp.log
sourceRoot: /Users/andy/Downloads/freemarker.js/test/template/
outputRoot: /var/folders/0d/99l1ldnj1758v9zs8ydjb90m0000gn/T
data: {
 "word": {
  "user": {
   "sb": "好人呢"
  }
 }
}
outputFile: /var/folders/0d/99l1ldnj1758v9zs8ydjb90m0000gn/T/0864f04b-6f93-4add-b2bb-b506f8b19881

建议方案: freemarker.js/index.js设置tdd的编码格式为sourceEncoding

function generateConfiguration(data, done) {
  var sName = Object.keys(data || {});
  var result = [];
  sName.forEach(function(x) {
    var value = data[x];
    if(typeof value !== 'boolean') {
      result.push(x + ': ' + value);
    } else if(value === true) {
      // For boolean settings, empty-string is considered as true
      result.push(x);
    }
  });
  if ( data.sourceEncoding ) {
    return `# encoding: ${data.sourceEncoding.toUpperCase()}\n${result.join('\n')}`;
  }
  return result.join('\n');
}
jeffery021121 commented 2 years ago

感谢解决方案,下面是我的场景


const fm = new Freemarker({
    viewRoot: path.resolve(__dirname, "../dist"), // view文件(.ftl)的目录,如果能换成devServer的目录的话,速度估计更快
    options: {
        sourceEncoding: "utf-8",// 我的data数据是json,这里utf-8的设置时必须的
    },
});

然后使用楼上的方法替换 freemarker.js/index.js下同名函数即可