Spartacus Storefront Multisite I18n с серверной частью

Мы столкнулись с некоторыми проблемами при настройке нашего MultiSite Spartacus при выполнении I18n.

  1. Мы хотели бы иметь разные переводы для каждого сайта, поэтому мы помещаем их в API, который может возвращать сообщения в зависимости от baseSite, например: backend.org/baseSiteX/messages?group=common
    Но установка Спартака не позволяет нам пройти baseSite? Мы можем пройти {{lng}} а также {{ns}}, но не baseSite.
    См. Https://sap.github.io/spartacus-docs/i18n/#lazy-loading Мы могли бы сделать это, переопределив i18nextInit, но я не знаю, как этого добиться.

  2. В документации говорится, что вы можете использовать crossOrigin: trueв конфигурации, но это, похоже, не работает. Проверка типов говорит, что она не поддерживается, но все еще показывает проблемы с CORS.

Есть у кого-нибудь идеи по поводу этих проблем?

3 ответа

В настоящее время в конфигурации поддерживаются только язык {{lng}} и имя блока {{ns}} в качестве динамических параметров.

Для достижения своей цели можно реализовать кастомный Спартак. CONFIG_INITIALIZER чтобы заполнить ваш i18n.backend.loadPath config на основе значения из BaseSiteService.getActive():

      @Injectable({ providedIn: 'root' })
export class I18nBackendPathConfigInitializer implements ConfigInitializer {
  readonly scopes = ['i18n.backend.loadPath']; // declare config key that you will resolve
  readonly configFactory = () => this.resolveConfig().toPromise();

  constructor(protected baseSiteService: BaseSiteService) {}

  protected resolveConfig(): Observable<I18nConfig> {
    return this.baseSiteService.getActive().pipe(
      take(1),
      map((baseSite) => ({
        i18n: {
          backend: {
            // initialize your i18n backend path using the basesite value:
            loadPath: `https://backend.org/${baseSite}/messages?lang={{lng}}&group={{ns}}`,
          },
        },
      }))
    );
  }
}

и укажите его в своем модуле (например, в app.module):

      @NgModule({
  providers: [
    {
      provide: CONFIG_INITIALIZER,
      useExisting: I18nBackendPathConfigInitializer,
      multi: true,
    },
  ],
  /* ... */
})

Примечание: в приведенном выше решении предполагается, что активный базовый сайт устанавливается только один раз при запуске приложения (что по умолчанию имеет место в Spartacus).

@krzysztof-platis мы реализовали это предложение, похоже, оно работало в Spartacus 4.x локально и в CCV2, с новой версией 5.2 оно, похоже, больше не работает.. (ни локально, ни CCV2, пока нет URL-адреса occ определяется в файле среды)

наш инициализатор конфигурации:

      export class CustomI18nConfigInitializer extends I18nConfigInitializer {
  readonly scopes = ['i18n.backend.loadPath']; // declare config key that you will resolve
  readonly configFactory = () => this.resolveConfig().toPromise();

  constructor(
    protected configInit: ConfigInitializerService,
    private occEndpoints: OccEndpointsService,
    private baseSiteService: BaseSiteService
  ) {
    super(configInit);
  }

  protected resolveConfig(): Observable<I18nConfig> {
    return this.baseSiteService.getActive().pipe(
      take(1),
      map(() => {
        // eslint-disable-next-line no-console
        console.log('i18n config initializer, load path: ' + this.occEndpoints.buildUrl('i18n'));
        return {
          i18n: {
            backend: {
              loadPath: this.occEndpoints.buildUrl('i18n'),
            },
          },
        } as Config;
      })
    );
  }
}

наш модуль приложения:

      providers: [
    {
      provide: CONFIG_INITIALIZER,
      useExisting: CustomI18nConfigInitializer,
      multi: true,
    },
  ],

наша фабрика конфигурации i18n:

      export function i18nConfigFactory(): I18nConfig {
  const prefix = environment.occ.prefix ?? '';
  const baseUrl = environment.occ.baseUrl ?? '';

  const url = `${baseUrl}${prefix}<site-id>/i18n/{{lng}}/{{ns}}`;
  // eslint-disable-next-line no-console
  console.log('i18n config factory, base url: ' + baseUrl);
  return {
    i18n: {
      backend: {
        // value get's replaced in the CustomI18nConfigInitializer with the proper OCC url since we need the base site id in the url
        loadPath: url,
      },
      chunks: {
        ...translationChunksConfig,
        cart: [...cartBaseTranslationChunksConfig.cart],
        checkout: [...checkoutTranslationChunksConfig.checkout, 'checkoutGuest', 'checkoutShipping'],
        order: [...orderTranslationChunksConfig.order],
        storeFinder: [...storeFinderTranslationChunksConfig.storeFinder],
        userAccount: [...userAccountTranslationChunksConfig.userAccount],
        userProfile: [...userProfileTranslationChunksConfig.userProfile],
      },
      fallbackLang: 'de',
    },
  };
}

Является ли идея иметь как AND, так иi18nConfigInitializerили мне следует использовать только один из них?

Я пытался не использовать фабрику конфигурации и полностью использовать инициализатор динамической конфигурации, но тогда кажется, что Спартак думает, что переводы будут предоставлены внутри приложения, а не будут загружаться лениво.

Если я просто используюi18nConfigс заполнителемloadPathзначение, я получаю 404. Поэтому мне кажется, что логика инициализатора динамической конфигурации запускается слишком поздно после того, как переводы уже загружены.

Есть идеи?

Я могу подтвердить, что после обновления Spartacus до версии 5.x серверная часть Dynami i18n loadPath больше не работает :(

У нас немного другой подход, но так же, как и для @user2477219, он перестал работать :(

      const initializeBackendUrl = (meta: Meta) => {
    const backendUrlFromEnvConfig = environment.backend.occ.baseUrl; // local
    const backendUrlFromMetaTag = meta.getTag('name=occ-backend-base-url').content; // ccv2
    const backendUrlToUse = backendUrlFromEnvConfig ? backendUrlFromEnvConfig : backendUrlFromMetaTag; // env config has priority
    const baseUrl = backendUrlToUse.replace('https://int-', 'https://');
    i18Backend.loadPath = baseUrl + '/rest/v2/customerPortal/translations/{{ns}}.json';
    return {
        backend: {
            occ: {
                baseUrl: baseUrl,
            },
        },
    };
};

const occConfig: OccConfig = {
    backend: {
        occ: {
            prefix: '/rest/v2/',
        },
    },
};



provideConfigFactory(initializeBackendUrl, [Meta]),
provideConfig({
    backend: occConfig.backend,
    i18n: {
        backend: i18Backend,
        chunks: {
            ...translationChunksConfig,
            custom: ['tok'],
        },
        fallbackLang: 'en',
    },
});
Другие вопросы по тегам