首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >setDefaultLang ngx-翻译。获取错误异常:调用Node模块失败并出现错误:“JSON中位于0位置的意外令牌”

setDefaultLang ngx-翻译。获取错误异常:调用Node模块失败并出现错误:“JSON中位于0位置的意外令牌”
EN

Stack Overflow用户
提问于 2017-07-04 13:30:33
回答 3查看 2.9K关注 0票数 1

我是新的角,并已开始建立一个新的项目与下一个特点。如果解释不够清楚,很抱歉。我很高兴提供更多的信息,但不想通过我的整个项目有无关的信息。

我在用

  • Visual Studio 2015
  • ASPNET核
  • AspNetCore.Angular服务
  • ngx-翻译

我遵循了[https://github.com/ngx-translate/core][1]中提供的示例和说明

我的代码正在按预期工作,能够翻译4种语言,并在路由器内的多个组件中使用管道指令。这意味着我的json文件正在加载并被正确地构造。我看到了许多报告,其中json文件有错误,但这不是我的情况。

但是,我的问题是,我不能添加设置在构造函数中使用的默认语言和语言的行。

代码语言:javascript
复制
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
    selector: 'app',
    template: require('./app.component.html'),
    styles: [require('./app.component.css')]
})
export class AppComponent {
    constructor(private translate: TranslateService) {

        
        translate.addLangs(["en", "fr", "es", "de"]);
        //Error shows up when uncommenting any of the next two lines
        //translate.setDefaultLang('en');
        //translate.use('en');

    }
}

每当我取消注释这些行时,我就会得到错误。

异常:调用Node模块失败,错误: SyntaxError: JSON.parse ()位置0处JSON中的意外令牌

如果我评论这些行,我的应用程序启动时就没有问题,唯一的细节就是语言还没有被设置。我可以在下拉列表中手动选择它,然后一切都如预期的那样工作。

以下是html文件

代码语言:javascript
复制
<div id="MainContainer" class='container-fluid'>
    <div class='row'>
        <label>
          {{ "SELECT" | translate }}<br />
          <select #langSelect (change)="translate.use(langSelect.value)">
            <option *ngFor="let lang of translate.getLangs()" [value]="lang" [selected]="lang === translate.currentLang">{{ lang }}</option>
          </select>
        </label>
    </div>
</div>

这是我的应用模块

代码语言:javascript
复制
import { NgModule }                 from '@angular/core';
import { UniversalModule }          from 'angular2-universal'; // this automatically imports BrowserModule, HttpModule, and JsonpModule too.
import { Http }                     from '@angular/http';
import { FormsModule }              from '@angular/forms'; // <-- ngModel lives here
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader }      from '@ngx-translate/http-loader';

// main Routing
import { AppRoutingModule }         from './routers/app-routing.module';


// own Services
import { ImgService }               from './services/img.service';

// own components
import { AppComponent }             from './components/app/app.component';
import { NavMenuComponent }         from './components/nav-menu/nav-menu.component';
import { CompleteSystemComponent }  from './components/complete-system/complete-system.component';
import { VehicleComponent }         from './components/vehicle/vehicle.component';
import { RobotComponent }           from './components/robot/robot.component';
import { MapComponent }             from './components/map/map.component';
import { StatusBarComponent }       from './components/status-bar/status-bar.component';
import { RobotCameraComponent }     from './components/robot-camera/robot-camera.component';
import { ImageProcessingComponent } from './components/image-processing/image-processing.component';
import { Station1Component }        from './components/station1/station1.component';
import { Station2Component }        from './components/station2/station2.component';


//AoT requires an exported function for factories
export function HttpLoaderFactory(http: Http) {
    //return new TranslateHttpLoader(http, '/i18n/', '.json');
    //return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
    return new TranslateHttpLoader(http);
}


@NgModule({
    imports: [
        UniversalModule, // must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
        FormsModule,
        AppRoutingModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [Http]
            }
        }),

    ],
    declarations: [
        AppComponent,
        NavMenuComponent,
        RobotComponent,
        VehicleComponent,
        CompleteSystemComponent,
        MapComponent,
        StatusBarComponent,
        RobotCameraComponent,
        ImageProcessingComponent,
        Station1Component,
        Station2Component
    ],
    providers: [
        ImgService
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

如果有人能告诉我该怎么做,我会很感激的。到目前为止,这些都是我试图解决的问题

  • 将默认语言的定义移到ngOnInit (同样失败)
  • 将默认语言的定义移动到用按钮调用的函数(它工作正常,没有问题)
  • 尝试将默认语言的定义移到ngAfterViewInit()和ngAfterViewChecked()。

我怀疑问题在于json文件没有从wwwroot目录中加载,或者在应用程序启动时服务无法在那里找到它们。在应用程序启动后,它会发现它们没有问题,而且一切都如预期的那样工作。

再次感谢您的评论,并让我知道更多的信息是否有助于调试这个问题

EN

回答 3

Stack Overflow用户

发布于 2017-08-11 17:22:42

我最终成功地解决了这个问题的80% (我也是新手,希望看到更好的解决方案)。

  1. 更新所有的软件包到最新版本(对我来说,它是角4.3.4)。
  2. 更改为HttpClient,如在docs(https://github.com/ngx-translate/core)中一样

这是我的app.module.shared.ts文件:

代码语言:javascript
复制
import { NgModule,Inject } from '@angular/core';
import { RouterModule,Router } from '@angular/router';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { HttpModule } from '@angular/http';

import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http);
}

export const sharedConfig: NgModule = {
    bootstrap: [ AppComponent ],
    declarations: [
        AppComponent,
        NavMenuComponent,
        CounterComponent,
        FetchDataComponent,
        HomeComponent,
    ],
    imports: [
        HttpClientModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [HttpClient]
            }
        }),
        RouterModule.forRoot([
            { path: '', redirectTo: 'home', pathMatch: 'full' },
            { path: 'home', component: HomeComponent },
            { path: 'counter', component: CounterComponent },
            { path: 'fetch-data', component: FetchDataComponent },
            { path: '**', redirectTo: 'home' }
        ])
    ]
};

这是有趣的部分。唯一的问题是用户界面的转换是在浏览器中完成的,这对SEO不利。如果我想出了什么,我会更新的。

app.component.ts文件:

代码语言:javascript
复制
import { Component, OnInit, Inject } from '@angular/core';

import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

import { TranslateService } from '@ngx-translate/core';

@Component({
    selector: 'app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    isBrowser: boolean;


    constructor( @Inject(PLATFORM_ID) platformId: Object ,@Inject('ORIGIN_URL') originUrl: string, private translate: TranslateService) {
        this.isBrowser = isPlatformBrowser(platformId);

        if (this.isBrowser) {
            translate.setDefaultLang('en');
            translate.use('en');
        }

    }
    changeLang(lang: string) {
        this.translate.use(lang);
    }
}

这解决了它目前,如果你想出一个更好的解决方案,不会错过SEO分享它:)。

票数 1
EN

Stack Overflow用户

发布于 2017-09-18 15:03:42

我也有同样的问题,我就是这样解决的:

1)提供词汇以查看:

代码语言:javascript
复制
public async Task<IActionResult> Index()
{
    var serverData = new IndexViewModel
    {
        Vocabulary = await GetUserLanguage()
    };

    return View(serverData);
}

词汇表:

代码语言:javascript
复制
public class Vocabulary
{
    public String Language { get; set; }

    public Object Translations { get; set; }
}

GetUserLanguage():

代码语言:javascript
复制
private async Task<Vocabulary> GetUserLanguage()
    {
        // Get lang form request headers
        StringValues langs;
        HttpContext.Request.Headers.TryGetValue("Accept-Language", out langs);

        if(langs.Count == 0)
        {
            return null;
        }

        var langsArr = langs.ToArray();

        for(var i = 0; i < langsArr.Length; i++)
        {
            var lang = langsArr[i];

            if (lang.Contains("-"))
            {
                langsArr[i] = lang.Split("-")[0];
            }

            if (lang.Contains("_"))
            {
                langsArr[i] = lang.Split("_")[0];
            }
        }

        langsArr = langsArr == null
            ? new String[] { "en" }
            : langsArr;

        Vocabulary vocabulary = null;

        foreach (var userLang in langsArr)
        {
            var path = $"{_hostingEnvironment.WebRootPath}/assets/i18n/{userLang}.json";
            FileInfo fileInfo = new FileInfo(path);

            if (fileInfo.Exists)
            {
                vocabulary = new Vocabulary
                {
                    Language = userLang,
                    Translations = await System.IO.File.ReadAllTextAsync(path)
                };

                break;
            }
        }

        return vocabulary;
    }

2)将模型发送到boot.server。

Index.cshtml:

代码语言:javascript
复制
<app asp-prerender-module="ClientApp/dist/main-server" asp-prerender-data="@JavaScriptHelper.Json(Model)">Loading...</app>

JavaScriptHelper.Json():

代码语言:javascript
复制
public static string Json(object obj)
    {
        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new JsonConverter[]
            {
                new StringEnumConverter(),
            },
            StringEscapeHandling = StringEscapeHandling.EscapeHtml
        };

        return JsonConvert.SerializeObject(obj, settings);
    }

将数据从MVC传递到Angular2描述了here

在boot.server.ts中,您可以通过params.data: // Imports访问传递的服务器数据

代码语言:javascript
复制
declare var global: any;

enableProdMode();

export default createServerRenderer(params => {
    let serverData = JSON.parse(params.data);
    serverData.vocabulary.translations = 
JSON.parse(serverData.vocabulary.translations);

global.serverData = serverData;

// ...

return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
    const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
    const state = moduleRef.injector.get(PlatformState);
    const zone = moduleRef.injector.get(NgZone);

return new Promise<RenderResult>((resolve, reject) => {
        zone.onError.subscribe((errorInfo: any) => reject(errorInfo));
        appRef.isStable.first(isStable => isStable).subscribe(() => {
            // Because 'onStable' fires before 'onError', we have to delay slightly before
            // completing the request in case there's an error to report
            setImmediate(() => {
                resolve({
                    html: state.renderToString(),

                    globals: {
                        serverData: serverData
                    }
                });
                moduleRef.destroy();
            });
        });
    });

对象global在节点环境中的预录制过程中可用。

globals: { serverData: serverData }过去的数据到窗口对象,该窗口对象在浏览器中可用

3)在app.component.ts中设置默认lang :宣告var serverData: any;

代码语言:javascript
复制
@Component({
    selector: 'app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {

constructor(private translate: TranslateService, private http: Http, globalService: GlobalService, @Inject(PLATFORM_ID) platformId: Object) {
    let isBrowser = isPlatformBrowser(platformId);

    let lang = '';
    let translations = { };

    if (!isBrowser) {
        lang = serverData.vocabulary.language;
        translations = serverData.vocabulary.translations;
    } else {
        lang = (window as any).serverData.vocabulary.language;
        translations = (window as any).serverData.vocabulary.translations;
    }

    translate.setTranslation(lang, translations);
    translate.setDefaultLang(lang);
    translate.use(lang);
    }
}
票数 0
EN

Stack Overflow用户

发布于 2020-12-22 15:48:21

代码语言:javascript
复制
<div id="MainContainer" class='container-fluid'>
    <div class='row'>
        <label>
          {{ "SELECT" | translate }}<br />
          <select #langSelect (change)="translate.use(langSelect.value)">
            <option *ngFor="let lang of translate.getLangs()" [value]="lang" [selected]="lang === translate.currentLang">{{ lang }}</option>
          </select>
        </label>
    </div>
</div>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44907376

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档