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
相关产品推荐
相关产品推荐

