Nano Hash - криптовалюты, майнинг, программирование

Динамически загружать различные файлы css в приложение angular2 в зависимости от языка пользователя.

У меня есть приложение Angular2, и оно должно поддерживать несколько языков. Некоторые из этих языков могут быть RTL (т. е. персидский), а некоторые — LTR (т. е. английский). Помимо локализации строк, мне нужно стилизовать компоненты в зависимости от направления языка.

Теперь, используя этот помощник, я могу иметь два отдельных файла (например, app-rtl.scss и app-ltr.scss), которые импортируют один файл scss (например, app.scss), что позволяет мне писать код scss в одном месте и автоматически выводить два файла; по одному на каждое направление.

Проблема в том, что теперь мне нужно как-то сослаться на подходящий файл css на основе языка пользователя. Так что, если язык пользователя английский, я должен иметь <link href="app-ltr.css" rel="stylesheet"> в заголовке, а если это RTL, <link href="app-rtl.css" rel="stylesheet">. Кроме того, я хочу добавить в свой проект начальную загрузку, которая также имеет два разных выходных файла для LTR и RTL.

Есть ли чистый способ достичь этой функциональности?

Что я пробовал:

Я создал два фиктивных компонента (один для LTR и один для RTL) без какого-либо шаблона, а затем назначил соответствующий файл scss с помощью styleUrls и установил encapsulation: ViewEncapsulation.None, чтобы он стал глобальным стилем. Затем я инициализирую их оба в своем шаблоне корневого компонента с помощью *ngIf и проверяю, является ли язык LTR или нет.

Это будет работать при загрузке первой страницы, потому что активен только один компонент (скажем, компонент LTR), но как только вы измените язык (т. е. второй компонент (RTL) станет активным и, таким образом, LTR будет удален), то стили, связанные с LTR остается на странице и не удаляется. Итак, на вашей странице есть стили RTL и LTR, которые не предназначены.


  • Это определенно можно сделать с помощью загрузчика, такого как SystemJS, но если вы полагаетесь на компиляцию Angular Ahead of Time, я подозреваю, что у вас возникнут проблемы. 18.05.2017
  • Стили ИМХО должны загружаться для каждого компонента и удаляться при его уничтожении. Пожалуйста, проверьте мой обновленный комментарий. 07.06.2017

Ответы:


1

Вам нужно будет условно добавить или удалить стиль из браузера:

добавить

loadIfNot(url,cssId){

     if (!document.getElementById(cssId)){
        var head  = document.getElementsByTagName('head')[0];
        var link  = document.createElement('link');
        link.id   = cssId;
        link.rel  = 'stylesheet';
        link.type = 'text/css';
        link.href = url;
        link.media = 'all';
        head.appendChild(link);
    }else{
        document.getElementById(cssId).disabled = false;///i fit's already there, enable it
    }

  }

и для удаления

 disable(cssId){
     document.getElementById(cssId).disabled = true
 }

Disable и Enable потому, что браузер имеет тенденцию кэшировать ваши стили, и чтобы включить или отключить их, вы должны изменить этот атрибут

19.05.2017
  • Это идеальное решение. Большое спасибо (у) 09.09.2020

  • 2

    основываясь на ответе @marbug, я бы попытался использовать службу и динамически загружать и выгружать ваши «языковые» компоненты.

    это будет работать следующим образом

    import { Injectable, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
    import { LanguageAComponent } from "./language-a.component";
    import { LanguageBComponent } from "./language-b.component";
    import { Router } from '@angular/router';
    
    @Injectable()
    export class LanguageComponentService {
        componentRef: any;
    
        constructor(private componentFactoryResolver: ComponentFactoryResolver, private router: Router
        ) { }
    
        loadLanguageA(viewContainerRef: ViewContainerRef) {
            let componentFactory = this.componentFactoryResolver.resolveComponentFactory(LanguageAComponent);
            this.componentRef = viewContainerRef.createComponent(componentFactory);
    
        }
    
       loadLanguageB(viewContainerRef: ViewContainerRef) {
            let componentFactory = this.componentFactoryResolver.resolveComponentFactory(LanguageBComponent);
            this.componentRef = viewContainerRef.createComponent(componentFactory);
    
        }
    
    
        unloadComponent() {
            this.componentRef.destroy();
        }
    
    }
    
    22.05.2017
  • Не могли бы вы рассказать подробнее и как я буду использовать это с файлами css? 30.11.2018
  • в сообщении говорилось об использовании фиктивных компонентов с разными таблицами стилей, и он может загружать и выгружать эти компоненты, чтобы стили менялись. 30.11.2018

  • 3

    Может быть, вы могли бы условно добавить класс в <body> на основе направления языка пользователя? Например, <body ng-class="{'dir-ltr': ltr, 'dir-rtl': !ltr}">. Тогда, конечно, вам придется обернуть все ваши стили sass в .dir-ltr и .dir-rtl соответственно, чтобы остальная часть DOM использовала правильный набор стилей. Это предполагает, что направление языка определяется при загрузке состояния, а также что <body> находится в пределах области действия вашего углового приложения.

    18.05.2017

    4

    1) Я бы посоветовал вам использовать лениво загружаемые модули вместо динамических файлов css (пожалуйста, взгляните на официальные документы Angular для получения дополнительной информации)

    2) Я бы также предложил использовать текущий язык для какой-либо службы, внедрить службу в соответствующий компонент и использовать необходимый класс css. Преимущества:

    2.1) стиль компонента не зависит от элемента тела - только от значения в сервисе - это более хорошо/правильнее для модульного тестирования

    2.2) могут быть случаи использования, когда недостаточно использовать классы LTR и RTL, а использовать некоторые дополнительные классы для определенных языков (например, столбцы таблицы могут иметь разную ширину для английского, немецкого и т. д. языков)

    3) динамическая загрузка css может вызвать проблемы с пользовательским интерфейсом: сначала применяются исходные стили, а затем они «переходят» к «другим» стилям (когда загружается соответствующий файл css). Так что 1) и 2) намного лучше (действительно ИМХО)

    ОБНОВЛЕНИЕ 2017-06-07 (просто для большей ясности)

    app-routing.module может выглядеть так:

    import { NgModule }             from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    
    export const routes: Routes = [
        { path: '', redirectTo: '/home', pathMatch: 'full'},
        { 
            path: 'home', 
            loadChildren: 'app/my-home-page/my-home-page.module#MyHomePageModule' 
        },
        ...
    ];
    
    @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule]
    })
    export class AppRoutingModule {}
    

    my-global.service может выглядеть так:

    @Injectable()
    export class MyGlobalService {
        currentLanguageDirection: string; // i.e. 'ltr' or 'rtl'
        currentLanguage: string;          // i.e. 'en', 'de', 'ru', etc
    }
    

    my-home-page.component.ts может быть:

    export class MyHomePageComponent {
        ...
    
        constructor(
            private myGlobalService: MyGlobalService, // inject global service
            ...
        ) {
        }
    
        ...
    }
    

    my-home-page.component.html может быть:

    <div [ngSwitch]="myGlobalService.currentLanguageDirection">
        <my-home-page-rtl *ngSwitchCase="'rtl'"></my-home-page-rtl>
        <my-home-page-ltr *ngSwitchDefault></my-home-page-ltr>
    </div>
    

    т.е. можно использовать два дополнительных компонента: my-home-page-ltr и my-home-page-rtl. У них будут отдельные файлы scss|css.

    Если вам нужна уникальная реализация для немецкого языка, тогда my-home-page-ltr.component.html может быть:

    <div [ngSwitch]="myGlobalService.currentLanguage">
        <my-home-page-ltr-de *ngSwitchCase="'de'"></my-home-page-ltr-de>
        <div *ngSwitchDefault>
            ... (default html code)
        </div>
    </div>
    

    т.е. отдельный компонент my-home-page-ltr-de будет иметь отдельный scss|css для немецкого языка.

    P.S. Обратите внимание, что вы можете повторно использовать html-файлы, установив их в @Component:

    @Component({
        selector: 'my-home-page...',
        templateUrl: './my-home-page....html', // <-------------- reuse here
        styleUrls: ['./my-home-page....scss']
    })
    

    П.П.С. Я бы рекомендовал не использовать ручное создание/удаление компонентов. Использование ngSwitch или ngIf является более правильным способом (ИМХО)

    П.П.П.С. Преимущества следующие. Компонент и его дочерние элементы должны быть загружены/выпущены с помощью angular автоматически. Переключение языка будет происходить очень быстро, так как текущий компонент загружается вместе со своими дочерними элементами - вам не нужно загружать стили всех компонентов при переключении языка.

    18.05.2017
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..