Angular 5 : Multiple languages requesting different layouts

标签 angular locale angular-template

我有一个默认语言为法语的 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 语言环境将导航到 MyComponentAR 语言环境将导航到 MyComponentAR

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

最佳答案

对于有相同场景的,下面是我的只使用一个组件并支持改变布局方向的解决方案。

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。使用 Bootstrap RTL

由于阿拉伯语要求布局方向是从右到左,我使用RTL Boostrap support执行此操作。我将此 rtl css 限定在 .rtl css 类中,并在选择阿拉伯语时使用 Angular Directive(指令)将此 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');
                }

            });


    }

}

3。当语言改变时重定向到正确的前缀路由

当语言改变时,用户必须被重定向到正确的前缀路由。为了动态地执行此操作,我在我的 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});
                        }
                    }
                }

            }


        });
}

就是这样!像这样你只使用一个组件。

希望对您有所帮助!

关于 Angular 5 : Multiple languages requesting different layouts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50494349/

相关文章:

angular - 组件包装时如何将formControl标记为已触摸

javascript - 在类的构造函数之外的任何地方操作 js $locale

angular - 使用异步管道在单个 ngIf 上组合两个或多个( bool )可观察量

ios - 当我在 iOS 中切换语言 RTL 时,UIPickerView 文本未居中对齐

angularjs - 具有动态生成的输入字段的 Angular 指令无法显示验证

Angular 4-如何将属性绑定(bind)到 * 指令

angular - 如何知道 Angular 5 及以上版本的 router-outlet 中加载了哪个组件

angular - 使用 Cypress 测试 Angular 时如何防止整页重新加载?

Angular 7 : Service instance working incorrectly

java - 如何获取系统语言?