Skip to content

Commit

Permalink
feat(translator): add translate module and translator functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
sciborrudnicki committed Jul 10, 2023
1 parent e432710 commit 0ca2128
Show file tree
Hide file tree
Showing 9 changed files with 516 additions and 0 deletions.
4 changes: 4 additions & 0 deletions translator/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@forward 'dictionary' as dictionary-*;
@forward 'translate' as translate-*;
@forward 'translator.dictionary.function';
@forward 'translator.translate.function';
78 changes: 78 additions & 0 deletions translator/_translator.dictionary.function.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Sass.
@use 'sass:list';
@use 'sass:meta';

// Modules.
@use '../map';
@use 'dictionary';

// Status: DONE
// The `translator.dictionary()` function returns(flattened map) the global and/or given `$dictionary`, merging it with the dictionary
// retrieved by the provided `$key` from this dictionary.
// @param `$key` A key to deep merge the dictionary under this key with a global dictionary and/or with a given `$dictionary`.
// @param `$dictionary` Dictionary of (flatten) map or list(dictionary key) type to retrieve.
// @param `$global` A `bool` value indicates whether to use a global dictionary. Default, `null`.
// @return The return value is a flattened map dictionary consisting of (word:translation).
@function dictionary($key: null, $dictionary: (), $global: null) {
@if list.length($dictionary) > 0 {
$dictionary: if(meta.type-of($dictionary) == map or list.separator($dictionary) == space, ($dictionary,), $dictionary);
@for $i from 1 through list.length($dictionary) {
$retrieved-dictionary: list.nth($dictionary, $i);
$dictionary: list.set-nth(
$dictionary,
$i,
if(
meta.type-of($retrieved-dictionary) == list and list.length($retrieved-dictionary) > 1,
map.deep-merge-key(dictionary.pick(null, $retrieved-dictionary, false), list.nth($retrieved-dictionary, 2)...),
$retrieved-dictionary
)
);
}
}
@return map.remove-type(map.deep-merge-key(dictionary.merge(null, $dictionary, $global), $key...), map);
}

// Variables.
// $-dictionary-example: (
// general: (word: słowo, (wrapper, wrap): owijka, (technology, technologia): tech, color: c),
// class: (prefix: class-prefix, separator: class-separator, suffix: class-suffix, calendars: (calendar: cal), labels: (label: lab)),
// prefix: spectre,
// border: b,
// color: c,
// separator: '-',
// suffix: end,
// outline: o,
// var: (prefix: var-prefix, suffix: var-suffix),
// );

// Examples.
// $-test: dictionary.merge(null, $-dictionary-example class);
// $-test: dictionary.set(global, this is global translation);
// $-test: dictionary.set(example, $-dictionary-example class, $-dictionary-example, false);

// @debug $-test;
// @debug dictionary.$dictionary;
// @debug dictionary(class);
// @debug dictionary(null, ($-dictionary-example general, $-dictionary-example class));
// @debug dictionary(null, ($-dictionary-example general, $-dictionary-example class));
// @debug dictionary((general, class), $-dictionary-example);
// @debug dictionary((general, class), $-dictionary-example (class, general, var));

// Gets the global dictionary.
// @debug dictionary(); // (word: translation)

// Gets the global dictionary and class retrieved from the dictionary from the given `$key` of the global dictionary.
// @debug dictionary(class, $-dictionary-example class); // (word: translation, prefix: class-prefix, separator: class-separator, suffix: class-suffix)

// Gets common and class dictionary from the global and the given `$dictionary`.
// @debug dictionary(class, (prefix: modified prefix, suffix: modified suffix)); // (word: translation, prefix: modified prefix, suffix: modified suffix)

// Gets common and class dictionary from the global and the given `$dictionary`.
// @debug dictionary(class, (class: (prefix: modified prefix, suffix: modified suffix))); // (word: translation, prefix: modified prefix, suffix: modified suffix)

// Gets the dictionary without global dictionary.
// @debug dictionary(null, (dictionary: (prefix: modified prefix, suffix: modified suffix)), false); // ()
// @debug dictionary(dictionary, (dictionary: (prefix: modified prefix, suffix: modified suffix)), false); // (prefix: modified prefix, suffix: modified suffix)

// get nested dictionary
// @debug dictionary((class, class-1), (size: medium, class: (class-1: (prefix: modified prefix, suffix: modified suffix))), false); // (size: medium, prefix: modified prefix, suffix: modified suffix)
66 changes: 66 additions & 0 deletions translator/_translator.translate.function.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Sass.
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';

// Functions.
@use 'translator.dictionary.function';

// Modules.
@use 'dictionary';
@use 'translate';

// Status: DONE
// The `translator.translate()` function translates `string`, `map`, or `list` with a global dictionary and/or given `$dictionary`,
// optionally with a dictionary retrieved by the given `$key`.
// @param `$words` The words in `string`, `list`, or `map` to translate.
// @param `$key` A key of the dictionary that is used to translate given `$words`.
// @param `$dictionary` The dictionary of map or list type(dictionary key) used to translate given `$words`.
// @param `$global` A `bool` value indicates whether to use a global dictionary. Default, `null`.
// @return The return value is the translated `string`, `map`, or `list` depending on the given `$words`.
@function translate($words, $key: null, $dictionary: (), $global: null) {
@return meta.call(map.get((
list: meta.get-function(list, false, translate),
map: meta.get-function(map, false, translate),
string: meta.get-function(string, false, translate),
),
meta.type-of($words)),
$words,
null,
translator.dictionary($key, $dictionary, $global),
);
}

// Examples.
// $-dictionary-example: dictionary.merge(null, (
// (extra large, 'extra large', extra-large): xl,
// (extra small, 'extra small', extra-small): xs,
// class: (prefix: class-prefix, separator: class-separator, suffix: class-suffix, calendars: (calendar: cal), labels: (label: lab)),
// general: (word: słowo, (wrapper, wrap): owijka, (technology, technologia): tech, color: c),
// large: lg,
// medium: md,
// prefix: spectre,
// small: sm,
// suffix: end,
// ));

// List.
// @debug translate(prefix (border, outline) color); // prefix (border, outline) color

// Use `$dictionary` argument.
// @debug translate(prefix (border, outline) color, null, $-dictionary-example); // spectre (b, o) c
// @debug translate((wrapper, technology, prefix), null, $-dictionary-example); // wrapper, technology, spectre
// @debug translate((wrapper, technology), null, $-dictionary-example general); // owijka, tech
// @debug translate((wrapper, technology) color, null, $-dictionary-example general); // (owijka, tech) c

// Map.
// @debug translate((word: prefix (border, outline) color), null, $-dictionary-example); // (word: spectre (b, o) c)
// @debug translate((word: wrapper), null, $-dictionary-example general); // (word: owijka)
// @debug translate((limit: first), null, ((first, start): 1, (last, length, end): 50)); // (limit: 1)

// String.
// @debug translate(wrapper, null, $-dictionary-example general); // owijka
// @debug translate(technology, null, $-dictionary-example general); // tech

// Different dictionary.
// @debug translate(calendar, null, $-dictionary-example (class, calendars)); // cal
4 changes: 4 additions & 0 deletions translator/translate/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@forward 'translate.list.function';
@forward 'translate.map.function';
@forward 'translate.nth.function';
@forward 'translate.string.function';
90 changes: 90 additions & 0 deletions translator/translate/_translate.list.function.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Sass.
@use 'sass:list';

// Functions.
@use '../../list/has/has.list.function' as *;
@use '../translator.dictionary.function';
@use 'translate.nth.function';

// Modules.
@use '../dictionary';

// Status: DONE
// The `translate.list()` function translates `$list` with a global dictionary and/or given `$dictionary`.
// @param `$list` The list with a few nested lists to translate.
// @param `$key` A Key of the dictionary retrieved from a global(if in use) and/or `$dictionary` for translation.
// @param `$dictionary` The dictionary that is used to translate element`s `$list`.
// @param `$global` A `bool` value indicates whether to use a global dictionary. Default, `null`.
// @return The return value is the translated `$list`.
@function list($list, $key: null, $dictionary: (), $global: null) {
@if type-of($list) == list {
$translation: dictionary.translation($list, translator.dictionary($key, $dictionary, $global));
@if $translation {
@return $translation;
}
@for $i from 1 through list.length($list) {
$list: translate.nth($list, $i, $key, $dictionary, $global);
$sub-list-1: list.nth($list, $i);
@if type-of($sub-list-1) == list {
@for $j from 1 through list.length($sub-list-1) {
$sub-list-2: list.nth($sub-list-1, $j);
@if type-of($sub-list-2) == list {
@for $n from 1 through list.length($sub-list-2) {
$sub-list-2: translate.nth($sub-list-2, $n, $key, $dictionary, $global);
}

$sub-list-1: list.set-nth($sub-list-1, $j, $sub-list-2);
}

$sub-list-1: translate.nth($sub-list-1, $j, $key, $dictionary, $global);
}

$list: list.set-nth($list, $i, $sub-list-1);
}
}
}
@return $list;
}

// Examples.
// $-dictionary-example: dictionary.merge(null, (
// (extra large, 'extra large', extra-large): xl,
// (extra small, 'extra small', extra-small): xs,
// border: b,
// class: (prefix: class-prefix, separator: class-separator, suffix: class-suffix, calendars: (calendar: cal), labels: (label: lab)),
// color: c,
// general: (word: słowo, (wrapper, wrap): owijka, (technology, technologia): tech, color: c),
// large: lg,
// medium: md,
// outline: o,
// prefix: spectre,
// small: sm,
// suffix: end,
// ));

// @debug list(extra large);
// @debug list(extra-large (extra small)); // xl xs

// @debug list((extra-large,));
// @debug list(border (extra large)); // b xl

// List.
// Get dictionary with a `$key` parameter`.
// @debug list((prefix, border, suffix), class); // class-prefix, b, class-suffix

// Get dictionary with a `$dictionary` parameter of list type.
// @debug list((wrapper, technology), $dictionary: $-dictionary-example general); // owijka, tech
// @debug list((wrapper, technology) color, general, $-dictionary-example); // (owijka, tech) c
// @debug list((wrapper, (word,), ([word])), $dictionary: $-dictionary-example general); // owijka, (słowo,), [słowo]

// Translate by using global dictionary and `class` key.
// @debug list(prefix (separator, prefix) suffix, $key: class); // class-prefix (class-separator, class-prefix) class-suffix

// Custom dictionary.
// @debug list((wrapper,), general, $-dictionary-example); // (owijka,)
// @debug list((calendar, label), $dictionary: $-dictionary-example (class, calendars)); // cal, label
// @debug list((border, outline) color, $dictionary: (border: b, outline: o, 'gray': g, 'red': r)); // (b, o) c
// @debug list((border 'red', outline 'gray') color, $dictionary: (border: b, outline: o, 'gray': g, 'red': r)); // (b r, o g) c

// Nested lists
// @debug list((border 1 outline (border 2, outline, (border 3, outline, (border 4, outline))) color), $dictionary: (border: b, outline: o, 'gray': g, 'red': r)); // b 1 o (b 2, o, (b 3, o, (border 4, o))) c
58 changes: 58 additions & 0 deletions translator/translate/_translate.map.function.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Sass.
@use 'sass:map';

// Modules.
@use '../dictionary';

// Functions.
@use 'translate.list.function' as *;
@use 'translate.string.function' as *;

// Status: DONE
// The `translate.map()` function translates flatten `$map` with a global dictionary and/or `$dictionary`.
// @param `$map` A map in which values of `string` or `list` type are translated.
// @param `$key` A key of the dictionary retrieved from a global and/or given `$dictionary` for translation.
// @param `$dictionary` The dictionary that is used to translate `$map` values.
// @param `$global` A `bool` value indicates whether to use a global dictionary. Default, `null`.
// @return The return value is translated flatten `$map`.
@function map($map, $key: null, $dictionary: (), $global: null) {
@if type-of($map) == map {
@each $map-key, $value in $map {
@if type-of($value) == string {
$map: map.set($map, $map-key, string($value, $key, $dictionary, $global));
} @else if type-of($value) == list {
$map: map.set($map, $map-key, list($value, $key, $dictionary, $global));
}
}
}
@return $map;
}

// Examples.
// $-dictionary-example: dictionary.merge(null, (
// (extra large, 'extra large', extra-large): xl,
// (extra small, 'extra small', extra-small): xs,
// border: b,
// class: (prefix: class-prefix, separator: class-separator, suffix: class-suffix, calendars: (calendar: cal), labels: (label: lab)),
// color: c,
// general: (word: słowo, (wrapper, wrap): owijka, (technology, technologia): tech, color: c),
// large: lg,
// medium: md,
// outline: o,
// prefix: spectre,
// small: sm,
// suffix: end,
// ));

// String.
// @debug map((word: wrapper), general, $-dictionary-example); // (word: owijka)
// @debug map((word: wrapper), null, $-dictionary-example general); // (word: owijka)
// @debug map((limit: first), null, ((first, start): 1, (last, length, end): 50)); // (limit: 1)

// List.
// @debug map((word: basic (wrapper, wrap) color), null, $-dictionary-example general); // (word: basic (owijka, owijka) c)
// @debug map((word: basic (wrapper, wrap) color), general, $-dictionary-example); // (word: basic (owijka, owijka) c)

// Different dictionary.
// @debug map((calendar: calendar), $dictionary: ($-dictionary-example, (class, calendars))); // (calendar: cal)
// @debug map((calendar: calendar), (class, calendars), $-dictionary-example); // (calendar: cal)
86 changes: 86 additions & 0 deletions translator/translate/_translate.nth.function.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Sass.
@use 'sass:list';

// Functions.
@use '../translator.dictionary.function';
@use 'translate.string.function';

// Modules.
@use '../dictionary';

// Status: DONE
// The `translate.nth()` function translates element at `$n` index in `$list` with a global dictionary and/or `$dictionary`.
// @param `$list` A list in which element at given `$n` index is translated.
// @param `$n` An index of `$list` to translate.
// @param `$key` A key of the dictionary retrieved from a global and/or given `$dictionary`.
// @param `$dictionary` The dictionary that is used to translate the `$n` element in `$list`.
// @param `$global` A `bool` value indicates whether to use a global dictionary. Default, `null`.
// @return The return value is the list with a translated `$n` element of `$list`.
@function nth($list, $n, $key: null, $dictionary: (), $global: null) {
@if type-of($list) == list {
$dictionary: translator.dictionary($key, $dictionary, $global);
$nth: list.nth($list, $n);
$translation: dictionary.translation($nth, $dictionary);
@if type-of($nth) == list {
@if $translation {
@return list.set-nth($list, $n, $translation);
} @else {
@for $i from 1 through list.length($nth) {
$translation: dictionary.translation(list.nth($nth, $i), $dictionary);
@if $translation {
$nth: list.set-nth($nth, $i, $translation);
}
}
@return list.set-nth($list, $n, $nth);
}
}
@return if($translation, list.set-nth($list, $n, $translation), $list);
}
@return $list;
}

// Examples.
// $-dictionary-example: dictionary.merge(null, (
// (extra large, 'extra large', extra-large): xl,
// (extra small, 'extra small', extra-small): xs,
// border: b,
// class: (prefix: class-prefix, separator: class-separator, suffix: class-suffix, calendars: (calendar: cal), labels: (label: lab)),
// color: c,
// general: (word: słowo, (wrapper, wrap): owijka, (technology, technologia): tech, color: c),
// large: lg,
// medium: md,
// outline: o,
// prefix: spectre,
// small: sm,
// suffix: end,
// ));

// String with space.
// @debug nth(border width 'extra small', 3); // border width xs

// String with delimiter.
// @debug nth(border width extra-large, 3); // border width xl

// Translate list as phrase.
// @debug nth(border width (extra small), 3); // border width xs

// Translate list as string.
// @debug nth(border width (extra-small, 'extra large'), 3); // border width (xs, xl)

// `$global` dictionary true
// @debug nth((prefix, suffix), 2, class); // prefix, class-suffix
// @debug nth((prefix, name, suffix), 1, class); // class-prefix, name, suffix

// `$global` dictionary false
// @debug nth((prefix, suffix), 1, class, $global: false); // prefix, suffix

// List.
// @debug nth(((prefix, suffix), suffix), 1, class); // (class-prefix, class-suffix), suffix
// @debug nth(((prefix, suffix, (prefix, suffix)), suffix), 1, class); // (class-prefix, class-suffix, (prefix, suffix)), suffix

// Custom `$dictionary`.
// @debug nth((prefix, suffix), 1, null, $-dictionary-example class); // class-prefix, suffix
// @debug nth((prefix, suffix), 1, class, (test: (class: (prefix: spectre-prefix))) test, false); // spectre-prefix, suffix
// @debug nth((wrapper, label, ), 1, null, $-dictionary-example general); // owijka, label
// @debug nth((wrapper, label, color), 3, general, $-dictionary-example); // wrapper, label, c
// @debug nth((wrapper, label, color), 3, $dictionary: $-dictionary-example general); // wrapper, label, c

0 comments on commit 0ca2128

Please sign in to comment.