You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ngx-translate切换语言时无法更新二维数组格式的questionsM1数据

解决Ngx-translate切换语言时二维数组翻译不更新的问题

我在开发Angular项目时使用Ngx-translate,已实现普通键值对的翻译功能,但二维数组格式的questionsM1数据在切换语言时无法同步更新,导致依赖questionList.length的单题展示、自动递进等功能失效。

现有代码核心问题

  • TranslateModule配置冲突:同时指定useClass和useFactory,导致自定义Loader逻辑无法正常执行
  • QuestionsService逻辑冗余错误:getTranslation中手动调用translate.use(lang)触发循环,且错误使用response.json()(HttpClient已自动解析JSON);getQuestionsJson重复订阅onLangChange导致内存泄漏
  • 组件未监听语言变化:仅在ngOnInit初始化时获取一次数据,语言切换时未触发重新加载

分步解决方案

1. 修复TranslateModule配置

修改translate.module.ts,移除冲突的useFactory配置,仅保留自定义QuestionsService作为TranslateLoader:

export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@NgModule({
  imports: [
    CommonModule,
    HttpClientModule,
    TranslateModule.forRoot({
      defaultLanguage: 'en',
      loader: {
        provide: TranslateLoader,
        useClass: QuestionsService,
        deps: [HttpClient, TranslateService], // 添加TranslateService依赖
      },
      compiler: {
        provide: TranslateCompiler,
        useClass: TranslateMessageFormatCompiler,
      },
    }),
  ],
  exports: [TranslateModule],
})
export class TranslateModule {}

2. 重构QuestionsService

简化Loader逻辑,利用Ngx-translate已加载的翻译数据,避免重复HTTP请求:

import { Injectable } from '@angular/core';
import { TranslateLoader } from '@ngx-translate/core';
import { HttpClient, Observable } from '@angular/common/http';
import { TranslateService } from '@ngx-translate/core';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class QuestionsService implements TranslateLoader {
  constructor(private http: HttpClient, private translate: TranslateService) {}

  // 实现TranslateLoader必要方法,加载对应语言的JSON文件
  getTranslation(lang: string): Observable<any> {
    const url = `assets/i18n/${lang}.json`;
    return this.http.get<any>(url); // HttpClient自动解析JSON,无需额外处理
  }

  // 获取当前语言的questionsM1数组,自动跟随语言变化
  getQuestions(): Observable<any[]> {
    return this.translate.get('questionsM1').pipe(
      map(questions => questions as any[])
    );
  }
}

3. 修改组件逻辑,监听语言变化

在q.component.ts中订阅语言变化事件,每次切换语言时重新加载问题数组:

import { Component, OnInit } from '@angular/core';
import { QuestionsService } from './questions.service';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'app-q',
  templateUrl: './q.component.html',
  styleUrls: ['./q.component.css']
})
export class QComponent implements OnInit {
  public questionList: any[] = [];
  public currentQuestion: number = 0;
  progress: string = '0';
  public points: number = 0;
  correctAnswer: number = 0;
  inCorrectAnswer: number = 0;
  isQuizCompleted: boolean = false;
  option: any;
  thisTypeOfKeyWorks = 'only 1-2 layer works not array of arrays';

  constructor(
    private questionService: QuestionsService,
    private translate: TranslateService
  ) {}

  ngOnInit(): void {
    this.loadQuestions();
    // 监听语言变化,重新加载问题并重置进度
    this.translate.onLangChange.subscribe(() => {
      this.loadQuestions();
      this.currentQuestion = 0;
      this.isQuizCompleted = false;
      this.points = 0;
      this.correctAnswer = 0;
      this.inCorrectAnswer = 0;
      this.progress = '0';
    });
  }

  // 统一加载问题的方法
  loadQuestions(): void {
    this.questionService.getQuestions().subscribe((questions) => {
      this.questionList = questions;
      this.updateProgress();
    });
  }

  // 更新进度条
  updateProgress(): void {
    this.progress = ((this.currentQuestion + 1) / this.questionList.length * 100).toString();
  }

  // 保留原有答题逻辑(示例)
  answer(questionIndex: number, option: any): void {
    // 原有答题判断逻辑...
    this.currentQuestion++;
    if (this.currentQuestion >= this.questionList.length) {
      this.isQuizCompleted = true;
    }
    this.updateProgress();
  }
}

4. 优化模板翻译使用

由于问题数组已从TranslateService获取对应语言的完整数据,模板中无需再使用| translate管道:

<ng-container *ngIf="!isQuizCompleted">
  <div class="d-inline-flex justify-content-center py-2">
    <div class="score float-start">
      <h5>{{ points }} Points</h5>
    </div>
    <div class="question-remain px-3">
      <span style="font-style: italic">
        Question {{ currentQuestion + 1 }} of {{ questionList.length }}
      </span>
    </div>
  </div>
  <div class="progress mb-2">
    <div
      class="progress-bar progress-bar-striped bg-success"
      role="progressbar"
      [ngStyle]="{ width: progress + '%' }"
      aria-valuenow="25"
      aria-valuemin="0"
      aria-valuemax="100"
    ></div>
  </div>

  <div class="question">
    <div class="card">
      <h3>{{ questionList[currentQuestion]?.questionText }}</h3>
    </div>
  </div>
  <div class="options">
    <ol *ngFor="let option of questionList[currentQuestion]?.options">
      <li (click)="answer(currentQuestion + 1, option)">
        <div appChangeBg [isCorrect]="option.correct" class="card">
          {{ option.text }}
        </div>
      </li>
    </ol>
  </div>
</ng-container>

<p>{{ thisTypeOfKeyWorks | lowercase | translate: { case: "lowercase" } }}</p>

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 03:54:57