代码之家  ›  专栏  ›  技术社区  ›  Radouane ROUFID Div

角度5:多语言请求不同的布局

  •  5
  • Radouane ROUFID Div  · 技术社区  · 6 年前

    我有一个 Angular 5 使用默认语言“法语”的应用程序。我必须添加阿拉伯语,这需要一个全局布局改变(事情必须显示从右到左…)。

    我想知道是否有一种方法可以只使用一个组件并进行条件模板选择。例如:

    --my-compenent_ar.html
    --my-compenent_fr.html
    --my-component.ts
    
    And in my @Component({
        moduleId: module.id,
        templateUrl: ==> condition here
        styleUrls: ['./sign-in.component.scss']
    })
    export class MyComponent
    

    当前版本的Angular(5)本机不支持此情况。

    有什么好办法吗?


    我想做的是

    --my-compenent_ar.html
    --my-compenent_fr.html
    --my-component.ts
    --my-component.ar.ts
    
    @Component({
        moduleId: module.id,
        templateUrl: './my-compenent_fr.html'
        styleUrls: ['./sign-in.component.scss']
    })
    export class MyComponent {
    ....
    }
    
    @Component({
        moduleId: module.id,
        templateUrl: './my-compenent_ar.html'
        styleUrls: ['./sign-in.component.scss']
    })
    export class MyComponentAR extends MyComponent {}
    

    有了这个配置, FR 区域设置将导航到 MyComponent AR 区域设置到 MyComponentAR .

    这很冗长。你有干净的方法吗?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Radouane ROUFID Div    6 年前

    对于具有相同场景的那些,在我的解决方案下面,它只使用一个组件并支持更改布局方向。

    1。为每种语言创建路由

    假设我的路线是:

    const routes: Routes = [
        {
            path: '',
            component: HomeComponent,
            pathMatch: 'full'
        },
        {
            path: 'users',
            children: [
                {
                    path: '',
                    component: UsersComponent
                },
                {
                    path: ':uid/profile',
                    component: ProfileViewComponent
                }
            ]
        }
    ]
    

    其思想是用支持的语言为这些路由加前缀。我动态地这样做如下(我只在这里加上阿拉伯语前缀):

    /**
     * Initialize language and routes
     * @param routes
     * @returns {Promise<any>}
     */
    init(routes: Routes): Promise<any> {
    
        this.routes = routes;
        let children: Routes = [...this.routes];
    
        /** exclude certain routes */
        for (let i = children.length - 1; i >= 0; i--) {
            if (children[i].data && children[i].data['skipRouteLocalization']) {
                children.splice(i, 1);
            }
        }
    
        /** append children routes */
        if (children && children.length) {
            if (this.locales.length > 1) {
                this.routes.unshift({path: 'ar', children: children});
            }
        }
    
        return of(this.routes).toPromise();
    }
    

    此方法在应用程序初始化时调用:

    @Injectable()
    export class ParserInitializer {
        parser: LocalizeParser;
        routes: Routes;
    
        /**
         * CTOR
         * @param injector
         */
        constructor(private injector: Injector) {
        }
    
        /**
         * @returns {Promise<any>}
         */
        appInitializer(): Promise<any> {
            const res = this.parser.init(this.routes);
    
            res.then(() => {
                let router = this.injector.get(Router);
                router.resetConfig(this.parser.routes);
            });
    
            return res;
        }
    
        /**
         * @param parser
         * @param routes
         * @returns {()=>Promise<any>}
         */
        generateInitializer(parser: LocalizeParser, routes: Routes[]): () => Promise<any> {
            this.parser = parser;
            this.routes = routes.reduce((a, b) => a.concat(b));
            return this.appInitializer;
        }
    }
    
    /**
     * @param p
     * @param parser
     * @param routes
     * @returns {any}
     */
    export function getAppInitializer(p: ParserInitializer, parser: LocalizeParser, routes: Routes[]): any {
        return p.generateInitializer(parser, routes).bind(p);
    }
    
    @NgModule({
        imports: [CommonModule, RouterModule, TranslateModule],
        declarations: [],
        exports: []
    })
    export class LocalizeRouterModule {
    
        static forRoot(routes: Routes, config: LocalizeRouterConfig = {}): ModuleWithProviders {
            return {
                ngModule: LocalizeRouterModule,
                providers: [
                    {
                        provide: RAW_ROUTES,
                        multi: true,
                        useValue: routes
                    },
                    config.parser,
                    // LocalizeParser,
                    ParserInitializer,
                    {
                        provide: APP_INITIALIZER,
                        multi: true,
                        useFactory: getAppInitializer,
                        deps: [ParserInitializer, LocalizeParser, RAW_ROUTES]
                    }
                ]
            };
        }
    
    
    }
    

    2。使用引导RTL

    因为阿拉伯语要求布局方向从右到左,所以我使用 RTL Boostrap support 执行此操作。我在一个 .rtl 当选择阿拉伯语时,CSS类并使用角度指令将此CSS类设置为顶层。

    @Directive({
        selector: '[yfLayoutClass]'
    })
    export class LayoutClassDirective implements OnInit {
    
        constructor(private elRef: ElementRef,
                    private renderer: Renderer2,
                    private store: Store<fromRoot.State>) {
        }
    
        ngOnInit(): void {
    
            this.store.select(fromRoot.getLocale)
                .filter(loc => loc != null)
                .subscribe(locale => {
    
                    if (locale.isArabic()) {
                        this.renderer.addClass(this.elRef.nativeElement, 'rtl');
                    } else {
                        this.renderer.removeClass(this.elRef.nativeElement, 'rtl');
                    }
    
                });
    
    
        }
    
    }
    

    三。当lang更改时重定向到正确的前缀路由

    当语言更改时,必须将用户重定向到正确的前缀路由。为了动态地执行此操作,我在 appComponent

    public ngOnInit(): void {
    
        this.translateService.onLangChange
            .combineLatest(this.router.events)
            .subscribe(([langEvent, event]) => {
    
                if (event instanceof RoutesRecognized) {
                    let currentUrl = event.url;
    
                    let locale = Locale.getLocaleByShortcut(langEvent.lang);
    
                    let queryParams = event.state.root.queryParams;
    
                    if (locale) {
                        if (locale.isArabic()) {
                            if (!ContextUtils.isArabicUrl(currentUrl)) {
                                this.router.navigateByUrl(ContextUtils.arabizeUrl(currentUrl), {queryParams: queryParams});
                            }
                        } else {
                            if (ContextUtils.isArabicUrl(currentUrl)) {
                                this.router.navigateByUrl(ContextUtils.frenchifyUrl(currentUrl), {queryParams: queryParams});
                            }
                        }
                    }
    
                }
    
    
            });
    }
    

    这就是全部!像这样,您只使用一个组件。

    希望有帮助!