delphi - 是否可以在 Delphi 中组合资源字符串?

标签 delphi delphi-xe4

我想替换看起来像的代码

resourcestring
    RESSTR_ERR1_TRYAGAIN = 'Error 1. Please try again.';
    RESSTR_ERR2_TRYAGAIN = 'Error 2. Please try again.';
    RESSTR_ERR3_TRYAGAIN = 'Error 3. Please try again.';        

像这样:
resourcestring
    RESSTR_ERR1 = 'Error 1.';
    RESSTR_ERR2 = 'Error 2.';
    RESSTR_ERR3 = 'Error 3.';        
    RESSTR_TRYAGAIN = 'Please try again.'; 

    RESSTR_ERR1_TRYAGAIN = RESSTR_ERR1 + ' ' + RESSTR_TRYAGAIN; //error
    RESSTR_ERR2_TRYAGAIN = RESSTR_ERR2 + ' ' + RESSTR_TRYAGAIN;
    RESSTR_ERR3_TRYAGAIN = RESSTR_ERR3 + ' ' + RESSTR_TRYAGAIN;

但这会导致错误 E2026 Constant expression expected. ,我所理解的。

不过,我想知道是否有一个解决方案,允许我定义 RESSTR_ERRx_TRYAGAIN以上述方式。 (目标是在不触及所有使用 RESSTR_ERRx_TRYAGAIN 的地方的情况下消除额外的翻译)。

到目前为止,我唯一的想法是以下,但我不想使用它,因为这很难看:
var
    RESSTR_ERR1_TRYAGAIN: string;
    //...

initialization
    RESSTR_ERR1_TRYAGAIN := RESSTR_ERR1 + ' ' + RESSTR_TRYAGAIN;
    //...

最佳答案

resourcestring字符串在运行时解析。每次您引用资源字符串时,实际发生的是您正在调用 LoadResString() 用于从应用程序资源加载(可能)翻译的字符串的 API。
const声明是常量,必须在编译时完全定义。

即使是类型化的常量(技术上是一个变量,受编译器设置的影响)也必须在编译时初始完全定义,即使它可能稍后在运行时进行修改。没有基于在运行时应用的翻译自动更新常量的机制。

即使您可以按照您尝试的方式组合资源字符串,也不会保存任何翻译,因为任何声明的资源字符串组合本身都必须是资源字符串,需要对该组合进行单独的翻译:

resourcestring
   foo = 'foo.';  // Requires translation of 'foo.'
   bar = 'bar';   // Requires translation of 'bar'
   foobar = foo + bar   // Would require translation of 'foo.bar'

当然,正如您所发现的,第三个声明是不可能的,但即使是这样,它也不会为您节省额外的翻译。

您不能使用常量来保存组合的翻译值的原因是这些不是常量:
resourcestring
   foo = 'foo.';  // Requires translation of 'foo.'
   bar = 'bar';   // Requires translation of 'bar'

const
   foobar = foo + bar   // When referenced, foo and bar are actually calls to a function and so are not constant

如果你主要关心减少声明常量的工作,那么你可以使用这个:
const
  foo = 'foo.';
  bar = 'bar';

resourcestring
  foobar = foo + bar;

但是您仍然需要提供所有生成的资源字符串及其完整的常量部分,因此无法实现避免额外翻译的目标。

恒定解决方案的问题

任何试图启用组合 resourcestring 声明的解决方案将要求对该特定组合进行单独的翻译,从而获得很少/没有 yield (实际上创造了更多的工作:额外的翻译)。

任何试图使用资源字符串的编译时值声明常量的解决方案都不会在运行时进行翻译。

的解决方法初始化 遭受一个相当微妙的复杂性,即您初始化的伪常量将在初始化时包含资源字符串的翻译值。如果您使用像 Sisulizer 这样允许 i18n 资源运行时更改的东西,那么任何此类更改都不会反射(reflect)在您的伪常量中。

你仍然可以使用这种技术,但是将你的初始化代码放在一个你在 调用的函数中。初始化 以及是否/何时在运行时更改翻译语言。

运行时问题的运行时解决方案

如前所述,根本问题是您试图声明一个编译时常量,该常量由仅在运行时解析的值组成。

相反,您需要的是一种方便、可靠的机制,可以在运行时组合两个运行时值。

如果“重试”示例是一个孤立的案例,那么将特定资源字符串附加到某个其他指定字符串(可能是资源字符串,也可能不是)的简单函数可能就足够了:
function MessageWithTranslatedTryAgain(const aMessage: String): String;
begin
  if aMessage[Length(aMessage)] <> '.' then
    result := aMessage + '. ' + RESSTR_TRYAGAIN
  else
    result := aMessage + ' ' + RESSTR_TRYAGAIN;
end;

如果您有许多这样的可能组合,那么您可能会选择使用许多静态实用程序方法来实现一个类:
type
  Translate = class
  public
    class function MessageWithTryAgain(const aMessage: String): String;
    class function MessageWithContinue(const aMessage: String): String;
    // etc
  end;

关于delphi - 是否可以在 Delphi 中组合资源字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37828260/

相关文章:

delphi - 如何阻止调试器进入delphi给定单元

delphi - 如何使用互斥体保护公共(public)资源?

delphi - 作为枚举类型的函数结果 - 如何证明所有变体都在案例部分

delphi - 在非 GUI 环境 (DLL) 中使用事件监听器 (Delphi)

delphi - 将 WinApi.Windows.TextOut 与擒纵装置一起使用时出现意外偏移

delphi - 异步 TADOQuery 的 OnFetchComplete 未同步到主线程

delphi - 我可以使用通配符来比较字符串吗?

string - 从字节数组创建字符串

delphi - 更改 JvLoginDialog 的标题

Delphi XE4 在访问 'object' 的通用列表项时给出 E2036