Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(transloco): tree-shake errors #823

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion libs/transloco/src/lib/resolve-loader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { TranslocoLoader, TranslocoLoaderData } from './transloco.loader';
import { InlineLoader } from './types';
import { isFunction } from './helpers';
import {
formatTranslocoError,
TranslocoErrorCode,
} from './transloco-error-code';

interface Options {
inlineLoader?: InlineLoader;
Expand All @@ -15,7 +19,15 @@ export function resolveLoader(options: Options) {
if (inlineLoader) {
const pathLoader = inlineLoader[path];
if (isFunction(pathLoader) === false) {
throw `You're using an inline loader but didn't provide a loader for ${path}`;
let message: string;
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
message = `You're using an inline loader but didn't provide a loader for ${path}`;
} else {
message = formatTranslocoError(
TranslocoErrorCode.NoLoaderProvidedForPath,
);
}
throw new Error(message);
}

return inlineLoader[path]().then((res) =>
Expand Down
4 changes: 4 additions & 0 deletions libs/transloco/src/lib/tests/default-missing-handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ describe('TranslocoMissingHandler', () => {
});

it('should not notify a warning message for production mode', () => {
// @ts-expect-error does not exist on `typeof globalThis`.
globalThis.ngDevMode = false;
assertLog({ prodMode: true }, false);
// @ts-expect-error does not exist on `typeof globalThis`.
globalThis.ngDevMode = true;
});

it('should not notify a warning message when logMissingKey is false', () => {
Expand Down
12 changes: 12 additions & 0 deletions libs/transloco/src/lib/transloco-error-code.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const enum TranslocoErrorCode {
NoLoaderProvidedForPath = 1,
FunctionalTranspilerInvalidSyntax,
UnableToLoadTranslation,
NoFallbackLanguageProvided,
}

export function formatTranslocoError(code: TranslocoErrorCode) {
// Prints a message with an error code to notify the user that something is
// wrong. This might also be logged in production, but without the full message.
return `[transloco]:${code}`;
}
17 changes: 14 additions & 3 deletions libs/transloco/src/lib/transloco-fallback-strategy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Inject, Injectable, InjectionToken } from '@angular/core';

import { TRANSLOCO_CONFIG, TranslocoConfig } from './transloco.config';
import {
formatTranslocoError,
TranslocoErrorCode,
} from './transloco-error-code';

export const TRANSLOCO_FALLBACK_STRATEGY =
new InjectionToken<TranslocoFallbackStrategy>(
Expand All @@ -20,9 +24,16 @@ export class DefaultFallbackStrategy implements TranslocoFallbackStrategy {
getNextLangs() {
const fallbackLang = this.userConfig.fallbackLang;
if (!fallbackLang) {
throw new Error(
'When using the default fallback, a fallback language must be provided in the config!',
);
let message: string;
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
message =
'When using the default fallback, a fallback language must be provided in the config!';
} else {
message = formatTranslocoError(
TranslocoErrorCode.NoFallbackLanguageProvided,
);
}
throw new Error(message);
}

return Array.isArray(fallbackLang) ? fallbackLang : [fallbackLang];
Expand Down
8 changes: 5 additions & 3 deletions libs/transloco/src/lib/transloco-missing-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ export interface TranslocoMissingHandler {
@Injectable()
export class DefaultMissingHandler implements TranslocoMissingHandler {
handle(key: string, config: TranslocoConfig) {
if (config.missingHandler.logMissingKey && !config.prodMode) {
const msg = `Missing translation for '${key}'`;
console.warn(`%c ${msg}`, 'font-size: 12px; color: red');
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
if (config.missingHandler.logMissingKey) {
const msg = `Missing translation for '${key}'`;
console.warn(`%c ${msg}`, 'font-size: 12px; color: red');
}
}

return key;
Expand Down
1 change: 1 addition & 0 deletions libs/transloco/src/lib/transloco.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AvailableLangs } from './types';
export interface TranslocoConfig {
defaultLang: string;
reRenderOnLangChange: boolean;
/** @deprecated */
prodMode: boolean;
fallbackLang?: string | string[];
failedRetries: number;
Expand Down
21 changes: 16 additions & 5 deletions libs/transloco/src/lib/transloco.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ import {
} from './shared';
import { getFallbacksLoaders } from './get-fallbacks-loaders';
import { resolveLoader } from './resolve-loader';
import {
formatTranslocoError,
TranslocoErrorCode,
} from './transloco-error-code';

let service: TranslocoService;

Expand Down Expand Up @@ -234,7 +238,7 @@ export class TranslocoService implements OnDestroy {
this.handleSuccess(path, translation);
}),
catchError((error) => {
if (!this.config.prodMode) {
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
console.error(`Error while trying to load "${path}"`, error);
}

Expand Down Expand Up @@ -762,12 +766,19 @@ export class TranslocoService implements OnDestroy {
const isFallbackLang = nextLang === splitted[splitted.length - 1];

if (!nextLang || isFallbackLang) {
let msg = `Unable to load translation and all the fallback languages`;
if (splitted.length > 1) {
msg += `, did you misspelled the scope name?`;
let message: string;
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
message = `Unable to load translation and all the fallback languages`;
if (splitted.length > 1) {
message += `, did you misspelled the scope name?`;
}
} else {
message = formatTranslocoError(
TranslocoErrorCode.UnableToLoadTranslation,
);
}

throw new Error(msg);
throw new Error(message);
}

let resolveLang = nextLang;
Expand Down
22 changes: 18 additions & 4 deletions libs/transloco/src/lib/transloco.transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import {
TRANSLOCO_CONFIG,
TranslocoConfig,
} from './transloco.config';
import {
formatTranslocoError,
TranslocoErrorCode,
} from './transloco-error-code';

export const TRANSLOCO_TRANSPILER = new InjectionToken<TranslocoTranspiler>(
typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_TRANSPILER' : '',
Expand Down Expand Up @@ -164,6 +168,8 @@ export function getFunctionArgs(argsString: string): string[] {
return args;
}

const functionalCallRegExp = /\[\[\s*(\w+)\((.*?)\)\s*]]/g;

@Injectable()
export class FunctionalTranspiler
extends DefaultTranspiler
Expand All @@ -175,19 +181,27 @@ export class FunctionalTranspiler
let transpiled = value;
if (isString(value)) {
transpiled = value.replace(
/\[\[\s*(\w+)\((.*?)\)\s*]]/g,
functionalCallRegExp,
(match: string, functionName: string, args: string) => {
try {
const func: TranslocoTranspilerFunction =
this.injector.get(functionName);

return func.transpile(...getFunctionArgs(args));
} catch (e: unknown) {
let message = `There is an error in: '${value}'.
let message: string;
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
message = `There is an error in: '${value}'.
Check that the you used the right syntax in your translation and that the implementation of ${functionName} is correct.`;
if ((e as Error).message.includes('NullInjectorError')) {
message = `You are using the '${functionName}' function in your translation but no provider was found!`;
if ((e as Error).message.includes('NullInjectorError')) {
message = `You are using the '${functionName}' function in your translation but no provider was found!`;
}
} else {
message = formatTranslocoError(
TranslocoErrorCode.FunctionalTranspilerInvalidSyntax,
);
}

throw new Error(message);
}
},
Expand Down
Loading