首页 > 解决方案 > Rails 5 - 变音符号和参数化方法的问题

问题描述

我在 Rails 5.2.3 和 Ruby 2.5.1 上工作。在某些时候,当我希望我的字符串数组常量包含一些字符串但它没有时,我发现了一个问题。原来问题与德语变音符号(öäü)有关。

所以我有如下定义的常量:

# coding: utf-8
# frozen_string_literal: true
class MyClass
  module MyModule
    MY_CONSTANT = [
      'Breite in mm',
      'Höhe in mm',
      'Länge in mm'
    ].map(&:parameterize).freeze
  end
end

我希望常数看起来像["breite-in-mm", "hoehe-in-mm", "laenge-in-mm"]

但相反,它存储为["breite-in-mm", "hohe-in-mm", "lange-in-mm"]. 你看,“ö”已被转换为“o”而不是“oe”。“ä”也一样。现在是“a”,而不是“ae”。

它在生产中、在 RSpec 测试中甚至在我启动 Rails 控制台并调用此常量时都以这种方式工作。但是当我使用相同的代码从 Rails 控制台定义一个新常量时,字符串被成功转换为我期望的,即["breite-in-mm", "hoehe-in-mm", "laenge-in-mm"]

我可以轻松摆脱这种parameterize方法,只需在需要时输入字符串。也许我将不得不这样做。但我真的很好奇为什么会发生这一切,却无法自己找到答案。

所以提前感谢您的任何想法。

标签: ruby-on-railsrubyruby-on-rails-5

解决方案


Rails 中的parameterize方法(通过使用ActiveSupport::Inflector#transliterate)是区域感知的。因此,它使用依赖于语言环境的规则将诸如元音变音之类的字符转译为 ASCII 字符。

当您的应用程序处理请求时(或至少在启动后处理一次),您通常会设置 I18n 语言环境,例如 withI18n.locale = :de用于单个请求或 withI18n.default_locale = :de用于整个应用程序。之后,Rails(即 i18n gem)默认使用此语言环境作为其音译规则。

最初设置常量时,可能尚未设置此默认语言环境。因此,i18n gem 不知道德语音译规则,只使用基本的 Unicode 规范化规则。

作为一种解决方法,您可以将所需的语言环境传递给参数化方法,如

MY_CONSTANT = [
  'Breite in mm',
  'Höhe in mm',
  'Länge in mm'
].map { |const| const.parameterize(locale: :de).freeze }.freeze

或者您也可以在执行代码之前设置默认的 i18n 语言环境(例如,在 中的文件中config/initializers,具体取决于您初始化常量的确切位置):

I18n.default_locale = :de

推荐阅读