Stringer Zestaw przydatnych helperów językowych

A set of useful, string-related helpers.

composer require avris/stringer

$stringer = (new LocalisatorBuilder())
    ->registerExtension(new LocalisatorExtension('en'))
    ->registerExtension(new StringerExtension())
    ->build(Stringer::class);

If you register StringerTwig as a Twig extension, you can use all of the following helpers as Twig filters, for example:

echo $stringer->timeDiff('2017-03-04 20:56');

can also be used as:

{{ '2017-03-04 20:56'|timeDiff }} 

Some of the helpers need to be tailored to a specific language. English is built in and Polish can be added by Avris Polonisator. Check it out as a reference to adding more languages.

convertCase

convertCase converts strings to several programistic conventions:

Credits to Avro

clearUrl

A URL address treated with clearUrl will be trimmed of all the parts that don't have to be shown to the user:

<a href="{{ post.source }}" target="_blank">{{ post.source|clearUrl }}</a>

For https://9gag.com/gag/aVOBPxn?ref=fsidebar this code will produce a link to a valid URL, but displayed as 9gag.com/gag/aVOBPxn.

numberInWords

Function numberInWords accepts a number and returns a string with its representation in words:

375 → three hundred seventy-five
-279 → minus two hundred seventy-nine
146 → one hundred fourty-six
10000000 → ten million
5371.18 → five thousand three hundred seventy-one and eighteen hundrenth
5678 → five thousand six hundred seventy-eight
0.1 → one tenth
0.000908 → zero comma zero zero zero nine zero eight

timeInWords

Function numberInWords accepts a time (\DateTime or string parsable by \DateTime) and returns a string reading out this time. There are three modes available, with increasing details.

$stringer->timeInWords($time, TimeInWords::MODE_NICE) (default):

14:15:16 → quarter past two pm
05:13:32 → thirteen past five am
19:49:20 → eleven to eight pm
11:53:11 → seven to noon

$stringer->timeInWords($time, TimeInWords::MODE_SHORT):

14:15:16 → two fifteen pm
05:13:32 → five thirteen am
19:49:20 → seven fourty-nine pm
11:53:11 → eleven fifty-three pm

$stringer->timeInWords($time, TimeInWords::MODE_LONG):

14:15:16 → two fifteen pm and sixteen seconds
05:13:32 → five thirteen am and thirty-two seconds
19:49:20 → seven fourty-nine pm and twenty seconds
11:53:11 → eleven fifty-three pm and eleven seconds

timeDiff

Function timeDiff accepts a datetime (\DateTime or string parsable by \DateTime) and returns a string explaining how long ago it was / how far in the future it is. You can change the point of reference from "now" to a different date by specifying the second parameter.

echo $stringer->timeDiff('2018-03-04 20:56');

Will echo a text like "now", "5 minutes ago", "2 hours ago" etc., depending on current time.

listify

Function listify takes a list of elements and a number, how many of them can be displayed at most (default 0, meaning no limit), while the rest will be replaced by "and X others" or similar, for example:

$stringer->listify(['A','B','C','D','E','F'], 1);   // '6 people commented'
$stringer->listify(['A','B','C','D','E','F'], 2);   //  'A and 5 others commented'
$stringer->listify(['A','B','C','D','E','F'], 3);   //  'A, B and 4 others commented'
$stringer->listify(['A','B','C','D','E','F'], 4);   //  'A, B, C and 3 others commented'
$stringer->listify(['A','B','C','D','E','F'], 5);   //  'A, B, C, D and 2 others commented'
$stringer->listify(['A','B','C','D','E','F'], 6);   //  'A, B, C, D, E and F commented'
$stringer->listify(['A','B','C','D','E','F'], 7);   //  'A, B, C, D, E and F commented'
$stringer->listify(['A','B','C','D','E','F'], 8);   //  'A, B, C, D, E and F commented'
$stringer->listify(['A','B','C','D','E','F'], 0);   //  'A, B, C, D, E and F commented'
$stringer->listify(['A'], 0);                       //  'A commented'
$stringer->listify(['A', 'B'], 0);                  //  'A and B commented'

The elements of the array can be either strings or objects with __toString defined.

By default the "people commented" translation is used, but you can change the translation keys with the third parameter:

$stringer->listify($loadedProcesses, 3, 'app:answer.listify.');

and in app.en.yml:

answer:
  listify:
    simple: 'loaded'
    addition: '<> one process loaded|%count% processes loaded'
    others: '<> one other process loaded|%count% other processes loaded'
    and: 'and'

phone

Function phone provides a nice formatting of a phone number:

arabicToRoman

Function arabicToRoman converts natural numbers from range 1-3999 to roman.

Micrus

In your App\App:registerModules register the Localisator module and the Stringer module:

yield new \Avris\Localisator\LocalisatorModule;
yield new \Avris\Stringer\StringerModule;

And it should work out of the box: Avris\Stringer\Stringer available in the container and the Twig extension registered.

Symfony

Example servies.yaml config:

Avris\Localisator\LocalisatorBuilder:
    calls:
        - [registerExtension, ['@Avris\Localisator\LocalisatorExtension']]
        - [registerExtension, ['@Avris\Stringer\StringerExtension']]
Avris\Localisator\LocalisatorExtension:
    arguments:
        $locale: '%locale%'
Avris\Stringer\StringerExtension: ~

Avris\Localisator\LocalisatorInterface:
    factory: ['@Avris\Localisator\LocalisatorBuilder', build]
    arguments: ['Avris\Localisator\LocalisatorInterface']
Avris\Localisator\LocalisatorTwig: ~

Avris\Stringer\Stringer:
    factory: ['@Avris\Localisator\LocalisatorBuilder', build]
    arguments: ['Avris\Stringer\Stringer']
Avris\Stringer\StringerTwig:
    public: true

WordStringer

Odmiana ze względu na liczbę (decline)

Mówimy "zdobyłeś 1 punkt", ale już "2 punkty" oraz "5 punktów". Dzięki Stringerowi nie musisz się martwić o odpowiednią odmianę. Wystarczy że napiszesz:

Zdobyłeś {{ points }} punkt{{ points|decline('','y','ów') }}

podając jako argumenty kolejno mianownik l.poj., mianownik l.mn. oraz dopełniacz l.mn. - i voilà! Filtr decline sam zajmie się dobraniem odpowiedniej końcówki/słowa.

Wołacze imion (vocative)

Miło, gdy czytelnika komunikatu czy mailingu powitają słowa "Drogi Andrzeju!" albo "Droga Renato!". Stringer umożliwia automatyczną odmianę imion do wołacza, niewymagającą odwołań do bazy i przetestowaną na tysiącu imion, polskich i nie tylko.

{{ user.firstName|vocative }}

Zwroty zależne od płci (genderify i guessGender)

Do mężczyzny powiemy "chciałbyś", do kobiety "chciałabyś". Podobnych przykładów jest wiele. Niestety, trudne i żmudne jest redagowanie osobnych tekstów dla kobiet i mężczyzn, a teksty unisex brzmią nienaturalnie. Znacznie lepiej i prościej jest wykorzystać filtr genderify:

{{ "Czy {_CHCIALBY}ś wziąć udział w..."|genderify(user.gender) }}

Powyższy kod dla user.gender='m' zwróci napis Czy chciałbyś wziąć udział, natomiast dla user.gender='k'Czy chciałabyś wziąć udział. Oczywiście można użyć genderify dla całego bloku oraz zagnieździć w nim inne filtry. Przykładowo:

{% filter genderify(user.gender) %}
<p>
    Drog{_I_A} {{ user.firstName|vocative|capitalize }}!<br/>
    Chcielibyśmy Cię poinformować, że zdobył{_ES_AS} {{ user.points }}
    {{ user.points|decline('punkt','punkty','punktów') }}!<br/>
</p>
<p>
    Pozdrawiamy,<br/>
    xyz
</p>
{% endfilter %}

może zwrócić dla pewnego użytkownika na przykład taki tekst:

Drogi Tomku!

Chcielibyśmy Cię poinformować, że zdobyłeś 932 punkty!

Pozdrawiamy,

xyz

Lista dostępnych tagów:

Tag Mężczyzna Kobieta
{_A} a
{_I_A} i a
{_ES_AS}
{_Y_A} y a
{_AL_ELA} ął ęła
{_CHCIALBY} chciałby chciałaby
{_POWINIEN} powinien powinna
{_MOGL} mógł mogła
{_WSZEDL} wszedł weszła
{_PAN_PANI_M} Pan Pani
{_PAN_PANI_C} Panu Pani
{_PAN_PANI_D} Pana Pani
{_PAN_PANI_B} Pana Panią
{_PAN_PANI_N} Panem Panią
{_PAN_PANI_W} Panie Pani

NumberStringer

Wyświetlanie liczb w polskiej notacji (polishNumber)

Filtr polishNumber otrzymuje zwykłego integera lub floata i zwraca odpowiedni string, w którym tysiące są oddzielone spacjami, a całość od części dziesiętnej – przecinkiem. Jest zatem lukrem składniowym dla funkcji number_format().

Przykładowo 123456 zostanie zmienione na 123 456, a 9298.3409 na 9 298,3409

Kwoty w złotówkach (pln)

Filtr pln również jest lukrem składniowym dla number_format() – zwraca liczbę w formacie z dwoma miejscami po przecinku i sufiksem .

Przykładowo {{ 123456.789|pln }} zostanie zmienione na 123 456,79 zł

Liczby słownie (numberInWords)

Co tu dużo tłumaczyć –- filtr numberInWords pobiera liczbę i zwraca string z jej zapisem słownym. W mianowniku. Można zmienić rodzaj na żeński, podając jako pierwszy parametr 'k'.

375 → trzysta siedemdziesiąt pięć
-279 → minus dwieście siedemdziesiąt dziewięć
146 → sto czterdzieści sześć
10000000 → dziesięć milionów
5371.18 → pięć tysięcy trzysta siedemdziesiąt jeden i osiemnaście setnych
5678 → pięć i sześćset siedemdziesiąt osiem tysięcznych
0.1 → jedna dziesiąta
0.000908 → zero komma zero zero zero dziewięć zero osiem

Formatowanie numeru telefonu (phone)

Filtr phone umożliwia proste sformatowanie stringa z numerem telefonu:

TimeStringer

Godzina słownie (timeInWords)

Filtr pobiera godzinę (albo jako string, albo obiekt DateTime) i zwraca string z jej zapisem słownym. Dostępne są trzy tryby/formaty:

Tryb podaje się jako pierwszy parametr, np.: Jest {{ "20:23"|timeInWords(0) }}.

Tryb 0:
14:15:16 → Jest czternasta piętnaście.
05:13:32 → Jest piąta trzynaście.
19:49:20 → Jest dziewiętnasta czterdzieści dziewięć.
11:53:11 → Jest jedenasta pięćdziesiąt trzy.

Tryb 1:
14:15:16 → Jest czternasta piętnaście i szesnaście sekund.
05:13:32 → Jest piąta trzynaście i trzydzieści dwie sekundy.
19:49:20 → Jest dziewiętnasta czterdzieści dziewięć i dwadzieścia sekund.
11:53:11 → Jest jedenasta pięćdziesiąt trzy i jedenaście sekund.

Tryb 2:
14:15:16 → Jest kwadrans po czternastej.
05:13:32 → Jest trzynaście po piątej.
19:49:20 → Jest za jedenaście dwudziesta.
11:53:11 → Jest za siedem południe.

Słowny zapis różnicy dat (relativeDate)

Filtr relativeDate zwraca stringa z czytelnym dla człowieka, przybliżonym opisem różnicy między podaną datą a chwilą obecną, jak na przykład:

Jeśli podamy dodatkowy argument, będzie on uważany za punkt odniesienia zamiast domyślnego "teraz".

Obie daty mogą być podane zarówno w formie obiektu DateTime, jak i stringa.

UrlStringer

Czyszczenie adresu URL (clearUrl)

Adres URL przepuszczony przez filtr clearUrl zostanie obcięty ze zbędnych (zbędnych do wyświetlania userowi) elementów.

<a href="{{ post.source }}" target="_blank">{{ post.source|clearUrl }}</a>

Powyższy kod dla adresu http://9gag.com/gag/aVOBPxn?ref=fsidebar zwróci link do poprawnego URL-a, ale wyświetlony jako 9gag.com/gag/aVOBPxn.

ListStringer

Ładne wyliczanie elementów tablicy (listify)

Ten filtr najlepiej pokazać na przykładzie działania:

// controller
'commentators' => array('A','B','C','D','E','F'),

// view
{% set desc = [
    'osoba skomentowała',
    'osoby skomentowały',
    'osób skomentowało',
    'inne',
    'innych',
    'skomentował',
    'skomentowali'
] %}
{% for i in range(1,8) %}
    {{ commentators|listify(i, desc) }}<br/>
{% endfor %}
{{ commentators|listify(0, desc) }}<br/>
{{ ['A']|listify(0, desc) }}<br/>
{{ ['A','B']|listify(0, desc) }}<br/>

Da następujący efekt:

6 osób skomentowało
A i 5 innych osób skomentowało
A, B i 4 inne osoby skomentowały
A, B, C i 3 inne osoby skomentowały
A, B, C, D i 2 inne osoby skomentowały
A, B, C, D, E i F skomentowali
A, B, C, D, E i F skomentowali
A, B, C, D, E i F skomentowali
A, B, C, D, E i F skomentowali
A skomentował
A i B skomentowali

Pierwszy parametr to maksymalna długość wyświetlonej listy (licząc wraz z elementem "i X innych"). Zero (domyślne) oznacza brak ograniczenia.

Drugi parametr to tablica stringów, które mają być doklejone w odpowiednich miejscach, domyślnie pusta.

Elementami tablicy mogą być zarówno stringi, jak i obiekty, o ile mają zdefiniowaną metodę __toString()

RomanStringer

Konwersja liczb arabskich na rzymskie (arabicToRoman)

Filtr arabicToRoman umożliwia konwersję liczb naturalnych z zakresu 1-3999 do liczb rzymskich.

CaseStringer

Konwersja wielkości liter (convertCase i guessCase)

Filtr convertCase konwertuje napisy do różnych konwencji programistycznych:

Credits to Avro