You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将ng-template中定义的翻译内容作为组件属性传入?

解决方案:将翻译文本作为组件属性传入

你现在的核心困扰是没法把模板里的翻译文本提取出来作为组件的label属性值,对吧?因为ngTemplateOutlet是用来渲染DOM节点的,而组件属性需要的是字符串值,两者没法直接打通。这里有几种实用的解决思路,你可以根据自己的场景选择:

方案1:直接在组件类中用$localize定义翻译映射(最推荐)

Angular的$localize支持直接在代码中调用翻译标记,你可以在组件类里创建一个路由到翻译文本的映射对象,然后在模板中直接绑定:

组件类代码

import { Component } from '@angular/core';
import { $localize } from '@angular/localize';

@Component({
  // ... 你的组件元数据
})
export class YourComponent {
  menuRoutes = ['/foo', '/bar'];
  // 定义路由对应的翻译文本,和模板里的i18n标记对应
  routeLabels: Record<string, string> = {
    '/foo': $localize`:@@foo:Foo`,
    '/bar': $localize`:@@bar:Bar`
  };
}

模板代码

<ng-container *ngFor="let menuRoute of menuRoutes">
  <some-component 
    [route]="menuRoute" 
    [label]="routeLabels[menuRoute]" 
  />
</ng-container>

这种方式最直接,翻译逻辑和组件绑定逻辑分离,维护起来也很方便。

方案2:使用自定义管道复用翻译逻辑

如果需要在多个组件中复用路由到翻译的转换逻辑,可以创建一个自定义管道:

管道代码

import { Pipe, PipeTransform } from '@angular/core';
import { $localize } from '@angular/localize';

@Pipe({ name: 'routeLabel' })
export class RouteLabelPipe implements PipeTransform {
  transform(route: string): string {
    switch(route) {
      case '/foo':
        return $localize`:@@foo:Foo`;
      case '/bar':
        return $localize`:@@bar:Bar`;
      default:
        return route; // 兜底返回原路由,避免空值
    }
  }
}

记得在你的模块中声明这个管道。

模板代码

<ng-container *ngFor="let menuRoute of menuRoutes">
  <some-component 
    [route]="menuRoute" 
    [label]="menuRoute | routeLabel" 
  />
</ng-container>

方案3:从模板中提取翻译文本(适合复杂翻译内容)

如果你的翻译内容包含复杂的HTML结构,必须用模板来定义,那可以通过代码渲染模板并提取文本内容:

组件类代码

import { Component, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core';

@Component({
  // ... 你的组件元数据
})
export class YourComponent {
  @ViewChild('translations') translationsTemplate!: TemplateRef<any>;
  menuRoutes = ['/foo', '/bar'];
  routeLabels: Record<string, string> = {};

  constructor(private vcRef: ViewContainerRef) {}

  ngOnInit() {
    this.menuRoutes.forEach(route => {
      // 创建嵌入式视图
      const embeddedView = this.translationsTemplate.createEmbeddedView({ $implicit: route });
      // 创建临时元素挂载视图,用于提取文本
      const tempElement = document.createElement('div');
      embeddedView.rootNodes.forEach(node => tempElement.appendChild(node));
      // 提取并保存翻译文本
      this.routeLabels[route] = tempElement.textContent?.trim() || '';
      // 清理临时元素和视图,避免内存泄漏
      tempElement.remove();
      embeddedView.destroy();
    });
  }
}

模板代码

保持你原来的translations模板不变,循环时绑定提取好的翻译文本:

<ng-container *ngFor="let menuRoute of menuRoutes">
  <some-component 
    [route]="menuRoute" 
    [label]="routeLabels[menuRoute]" 
  />
</ng-container>

<ng-template #translations let-menuRoute>
  <ng-container [ngSwitch]="menuRoute"> <!-- 注意这里你之前写错了,应该是menuRoute而非menuRoutes -->
    <ng-container *ngSwitchCase="'/foo'">
      <span i18n="@@foo">Foo</span>
    </ng-container>
    <ng-container *ngSwitchCase="'/bar'">
      <span i18n="@@bar">Bar</span>
    </ng-container>
  </ng-container>
</ng-template>

注意:这个方案比较繁琐,只推荐给翻译内容包含复杂DOM结构的场景,纯文本翻译用前两种方案更高效。

内容的提问来源于stack exchange,提问作者Remi

火山引擎 最新活动