% phonenumbers.sty
% LaTeX-Paket zur Formatierung von Telefonnummern
% LaTeX package for formatting telephone numbers
% Autor: K. Wehr
% Version: 2.4
% Datum: 13. Mai 2022

% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
% http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.


\ProvidesExplPackage {phonenumbers} {2022-05-13} {2.4} {Telephone number package}

\RequirePackage{l3keys2e}
\RequirePackage{ltxcmds}

\clist_const:Nn \c_phone_ziffern_clist {0,1,2,3,4,5,6,7,8,9}
\clist_const:Nn \c_phone_gliederungszeichen_clist {(,),[,],/}

\tl_const:Nn \c_phone_bindestrich_tl { \kern 1pt - \kern 1pt }
\tl_const:Nn \c_phone_schraegstrich_tl { \kern 1pt \slash \kern 1pt }
\tl_const:Nn \c_phone_pluszeichen_tl { + \kern 1pt }

\str_new:N \l_phone_land_str
\str_new:N \l_phone_heimatland_str
\str_new:N \l_phone_auslandsvorwahltyp_str
\str_new:N \l_phone_vorwahl_str
\str_new:N \l_phone_vorwahldarstellung_str
\str_new:N \l_phone_vorwahltrennung_str
\str_new:N \l_phone_auslandsvorwahltrennung_str
\str_new:N \l_phone_heimatvorwahl_str
\str_new:N \l_phone_bereinigte_nummer_str
\str_new:N \l_phone_bereinigte_durchwahl_str
\str_new:N \l_phone_linktext_str

\int_new:N \l_phone_ziffernzahl_int
\int_new:N \l_phone_nummerlaenge_int
\int_new:N \l_phone_gruppierungsminimum_int

\tl_new:N \l_phone_ausgabetext_tl
\tl_new:N \l_phone_formatierte_nummer_tl

\bool_new:N \l_phone_vorwahl_gefunden_bool
\bool_new:N \l_phone_zeilenumbruch_bool
\bool_new:N \l_phone_eingabe_leer_bool
\bool_new:N \l_phone_durchwahl_leer_bool
\bool_new:N \l_phone_nummer_verlinken_bool
\bool_new:N \l_phone_teilnehmerrufnummer_gueltig_bool

\cs_generate_variant:Nn \str_if_eq:nnT {xnT}
\cs_generate_variant:Nn \str_if_eq:nnF {xnF}
\cs_generate_variant:Nn \str_if_eq:nnTF {xnTF}
\cs_generate_variant:Nn \str_case:nn {xn}
\cs_generate_variant:Nn \str_case:nnT {xnT}
\cs_generate_variant:Nn \str_case:nnF {xnF}
\cs_generate_variant:Nn \str_case:nnTF {xnTF}
\cs_generate_variant:Nn \str_tail:n {x}
\cs_generate_variant:Nn \tl_put_right:Nn {Nv}
\cs_generate_variant:Nn \msg_warning:nnn {onn}
\cs_generate_variant:Nn \msg_warning:nnn {nnV}


\msg_new:nnn {phonenumbers} {illegal character}
   {
      illegal~character~'#1'~in~phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {empty input}
   {
      empty~phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {empty extension}
   {
      empty~extension~(Durchwahl)~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {illegal extension}
   {
      extension~(Durchwahl)~of~
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      phone~number~ignored~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {odd extension}
   {
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      non-geographic~number~should~not~contain~an~extension~(Durchwahl)~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {subscriber number too short}
   {
      subscriber~number~(Teilnehmerrufnummer)~has~less~than~#1~digits~in~
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {subscriber number too long}
   {
      subscriber~number~(Teilnehmerrufnummer)~has~more~than~#1~digits~in~
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {illegal start of subscriber number}
   {
      subscriber~number~(Teilnehmerrufnummer)~starts~with~#1~in~
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {missing subscriber number}
   {
      no~subscriber~number~(Teilnehmerrufnummer)~given~in~
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {invalid area code}
   {
      unknown~area~code~(Vorwahl)~in~
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      phone~number~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {number too short}
   {
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      #1~number~has~less~than~#2~digits~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {number too long}
   {
      \phone_landesadjektiv:V \l_phone_land_str
      \c_space_tl
      #1~number~has~more~than~#2~digits~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {home country set}
   {
      home~country~set~to~
      \l_phone_heimatland_str
      \c_space_tl
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {home country cleared}
   {
      home~country~
      \l_phone_heimatland_str
      \c_space_tl
      has~been~deleted~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {home area code set}
   {
      Your~home~is~in~
      \tl_use:c {c_phone_\l_phone_heimatland_str _ortsname_#1_tl}
      \c_space_tl
      (area~code~#1)~according~to~line~
      \msg_line_number:.
   }

\msg_new:nnn {phonenumbers} {home area code cleared}
   {
      home~area~code~
      \l_phone_heimatvorwahl_str
      \c_space_tl
      has~been~deleted~\msg_line_context:
   }

\msg_new:nnn {phonenumbers} {invalid home area code}
   {
      #1~unknown~as~
      \phone_landesadjektiv:V \l_phone_heimatland_str
      \c_space_tl
      geographic~area~code~(Ortsvorwahl)~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {invalid country code}
   {
      illegal~country~code~
      \msg_line_context:
   }

\msg_new:nnn {phonenumbers} {country code only}
   {
      phone~number~consists~of~a~country~code~only~
      \msg_line_context:
   }

\cs_new:Npn \phone_landesadjektiv:n #1
   {
      \str_case:nnF {#1}
         {
            {DE} {German}
            {AT} {Austrian}
            {FR} {French}
            {UK} {British}
            {US} {North~American}
         }
         {
            unsupported
         }
   }

\cs_generate_variant:Nn \phone_landesadjektiv:n {V}


\keys_define:nn {phonenumbers}
   {
      country .choices:nn = {DE,AT,FR,UK,US}
         {
            \str_set_eq:NN \l_phone_land_str \l_keys_choice_tl
         },
      country .initial:n = DE,
      country .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      home-country .choices:nn = {DE,AT,FR,UK,US,none}
         {
            \str_if_eq:VnTF \l_keys_choice_tl {none}
               {
                  \str_if_empty:NF \l_phone_heimatland_str
                     {
                        \msg_info:nn {phonenumbers} {home country cleared}
                        \str_clear:N \l_phone_heimatland_str
                     }
               }
               {
                  \str_set_eq:NN \l_phone_heimatland_str \l_keys_choice_tl
                  \msg_info:nn {phonenumbers} {home country set}
               }

            \str_if_empty:NF \l_phone_heimatvorwahl_str
               {
                  \msg_info:nn {phonenumbers} {home area code cleared}
                  \str_clear:N \l_phone_heimatvorwahl_str
               }
         },
      home-country .initial:n = none,
      home-country .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      foreign .choices:nn = {off,european,american,international}
         {
            \str_set_eq:NN \l_phone_auslandsvorwahltyp_str \l_keys_choice_tl
         },
      foreign .initial:n = off,
      foreign .default:n = international
   }

\keys_define:nn {phonenumbers}
   {
      area-code .choices:nn = {number,place,place-and-number}
         {
            \str_set_eq:NN \l_phone_vorwahldarstellung_str \l_keys_choice_tl
         },
      area-code .initial:n = number,
      area-code .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      area-code-sep .choices:nn = {space,slash,brackets,hyphen}
         {
            \str_set_eq:NN \l_phone_vorwahltrennung_str \l_keys_choice_tl
         },
      area-code-sep .initial:n = slash,
      area-code-sep .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      foreign-area-code-sep .choices:nn = {space,brackets}
         {
            \str_set_eq:NN \l_phone_auslandsvorwahltrennung_str \l_keys_choice_tl
         },
      foreign-area-code-sep .initial:n = space,
      foreign-area-code-sep .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      link .choices:nn = {on,off}
         {
            \str_if_eq:VnTF \l_keys_choice_tl {on}
               {
                  \bool_set_true:N \l_phone_nummer_verlinken_bool
               }
               {
                  \bool_set_false:N \l_phone_nummer_verlinken_bool
               }
         },
      link .initial:n = on,
      link .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      home-area-code .code:n =
         {
            \str_if_eq:nnTF {#1}{none}
               {
                  \str_if_empty:NF \l_phone_heimatvorwahl_str
                     {
                        \msg_info:nn {phonenumbers} {home area code cleared}
                        \str_clear:N \l_phone_heimatvorwahl_str
                     }
               }
               {
                  \str_if_empty:NT \l_phone_heimatland_str
                     {
                        \str_set_eq:NN \l_phone_heimatland_str \l_phone_land_str
                        \msg_info:nn {phonenumbers} {home country set}
                     }

                  \phone_heimatvorwahl_erlaubt:nT {#1}
                     {
                        % Auslassen der Vorwahl möglich, Heimatvorwahl setzen:
                        \str_set:Nn \l_phone_heimatvorwahl_str {#1}
                        \msg_info:nnn {phonenumbers} {home area code set} {#1}
                     }
               }
         },
      home-area-code .initial:n = none,
      home-area-code .value_required:n = true
   }

\keys_define:nn {phonenumbers}
   {
      group-min .choices:nn = {3,4,5,6,7}
         {
            \int_set_eq:NN \l_phone_gruppierungsminimum_int \l_keys_choice_tl
         },
      group-min .initial:n = {3} ,
      group-min .value_required:n = true
   }


% Prüfe, ob eine Vorwahl als Heimatvorwahl zulässig ist.
% #1: Heimatvorwahl
\prg_new_protected_conditional:Npnn \phone_heimatvorwahl_erlaubt:n #1 {T}
   {
      \clist_if_in:cnTF {c_phone_\l_phone_heimatland_str _ortsvorwahlen_clist} {#1}
         {
            \str_case:VnF \l_phone_heimatland_str
               {
                  % alle deutschen Ortsvorwahlen können Heimatvorwahl sein
                  {DE} { \prg_return_true: }
                  % alle österreichischen Ortsvorwahlen können Heimatvorwahl sein
                  {AT} { \prg_return_true: }
                  % in Frankreich kann nur 0508 Heimatvorwahl sein
                  {FR}
                     {
                        \str_if_eq:nnTF {#1} {0508} { \prg_return_true: }
                           {
                              \msg_warning:nnn {phonenumbers} {FR/illegal home area code} {#1}
                              \prg_return_false:
                           }
                     }
               }
               {
                  % Name der Liste mit den obligatorischen Ortsvorwahlen
                  \str_set:Nx \l_tmpa_str {c_phone_\l_phone_heimatland_str _obligatorische_ortsvorwahlen_clist}

                  % in anderen Ländern können nur nicht obligatorische Ortsvorwahlen Heimatvorwahl sein
                  \clist_if_exist:cTF {\l_tmpa_str}
                     {
                        \clist_if_in:cnTF {\l_tmpa_str} {#1}
                           {
                              \msg_warning:onn {phonenumbers} {\l_phone_heimatland_str/illegal home area code} {#1}
                              \prg_return_false:
                           }
                           {
                              \prg_return_true:
                           }
                     }
                     {
                        \prg_return_true:
                     }
               }
         }
         {
            \msg_warning:nnn {phonenumbers} {invalid home area code} {#1}
            \prg_return_false:
         }
   }


% einen Nummernteil von vorne in Zweiergruppen gruppiert schreiben, sofern er nicht kürzer als das Gruppierungsminimum ist
\cs_new_protected:Npn \phone_von_vorne_gruppiert_schreiben:n #1
   {
      \int_set:Nn \l_phone_ziffernzahl_int { \tl_count:n {#1} }
      \tl_clear:N \l_phone_formatierte_nummer_tl

      \int_step_inline:nn {\l_phone_ziffernzahl_int}
         {
            \tl_put_right:Nx \l_phone_formatierte_nummer_tl { \tl_item:nn {#1} {##1} }

            % Nach jeder zweiten Ziffer wird ein kleiner Abstand eingefügt, wenn die Ziffernzahl nicht unterhalb des Gruppierungsminimums liegt.
            \bool_lazy_all:nT
               {
                  { ! \int_compare_p:nNn { \l_phone_ziffernzahl_int } < { \l_phone_gruppierungsminimum_int } }
                  { \int_if_even_p:n {##1} }
                  { \int_compare_p:nNn {##1} < { \l_phone_ziffernzahl_int } }
               }
               {
                  \tl_put_right:Nn \l_phone_formatierte_nummer_tl {\,}
               }
         }

      \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_formatierte_nummer_tl
   }

\cs_generate_variant:Nn \phone_von_vorne_gruppiert_schreiben:n {x,V}


% einen Nummernteil von in Zweiergruppen gruppiert mit führender Einzelziffer schreiben, sofern er nicht kürzer als das Gruppierungsminimum ist
\cs_new_protected:Npn \phone_versetzt_gruppiert_schreiben:n #1
   {
      \int_set:Nn \l_phone_ziffernzahl_int { \tl_count:n {#1} }
      \tl_clear:N \l_phone_formatierte_nummer_tl

      \int_step_inline:nn {\l_phone_ziffernzahl_int}
         {
            \tl_put_right:Nx \l_phone_formatierte_nummer_tl { \tl_item:nn {#1} {##1} }

            % Nach der 1., 3., 5., ... Ziffer wird ein kleiner Abstand eingefügt, wenn die Ziffernzahl nicht unterhalb des Gruppierungsminimums liegt.
            \bool_lazy_all:nT
               {
                  { ! \int_compare_p:nNn { \l_phone_ziffernzahl_int } < { \l_phone_gruppierungsminimum_int } }
                  { \int_if_odd_p:n {##1} }
                  { \int_compare_p:nNn {##1} < { \l_phone_ziffernzahl_int } }
               }
               {
                  \tl_put_right:Nn \l_phone_formatierte_nummer_tl {\,}
               }
         }

      \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_formatierte_nummer_tl
   }

\cs_generate_variant:Nn \phone_versetzt_gruppiert_schreiben:n {x}


% einen Nummernteil von hinten in Zweiergruppen gruppiert schreiben, sofern er nicht kürzer als das Gruppierungsminimum ist
\cs_new_protected:Npn \phone_von_hinten_gruppiert_schreiben:n #1
   {
      \int_set:Nn \l_phone_ziffernzahl_int { \tl_count:n {#1} }
      \tl_clear:N \l_phone_formatierte_nummer_tl

      \int_step_inline:nnnn {\l_phone_ziffernzahl_int} {-1} {1}
         {
            \tl_put_left:Nx \l_phone_formatierte_nummer_tl { \tl_item:nn {#1} {##1} }

            % Nach jeder zweiten Ziffer wird ein kleiner Abstand eingefügt, wenn die Ziffernzahl nicht unterhalb des Gruppierungsminimums liegt.
            \bool_lazy_all:nT
               {
                  { ! \int_compare_p:nNn { \l_phone_ziffernzahl_int } < { \l_phone_gruppierungsminimum_int } }
                  { \int_if_even_p:n { \l_phone_ziffernzahl_int + 1 - ##1 } }
                  { \int_compare_p:nNn {##1} > {1} }
               }
               {
                  \tl_put_left:Nn \l_phone_formatierte_nummer_tl {\,}
               }
         }

      \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_formatierte_nummer_tl
   }

\cs_generate_variant:Nn \phone_von_hinten_gruppiert_schreiben:n {x,V}


% #1: Landeskennzahl
\cs_new_protected:Npn \phone_auslandsvorwahl_schreiben:n #1
   {
      \str_case:VnTF \l_phone_land_str
         {
            {DE} { }
            {AT} { }
            {FR} { }
         }
         {
            \str_case:Vn \l_phone_auslandsvorwahltyp_str
               {
                  {international} { \tl_put_right:Nn \l_phone_ausgabetext_tl { \c_phone_pluszeichen_tl #1 } }
                  {european} { \phone_von_hinten_gruppiert_schreiben:n {00#1} }
                  {american} { \phone_von_hinten_gruppiert_schreiben:n {011#1} }
               }
         }
         {
            \tl_put_right:Nx \l_phone_ausgabetext_tl
               {
                  \str_case:VnF \l_phone_auslandsvorwahltyp_str
                     {
                        {european} {00 #1}
                        {american} {011 #1}
                     }
                     {
                        \c_phone_pluszeichen_tl #1
                     }
               }
         }
   }

\cs_generate_variant:Nn \phone_auslandsvorwahl_schreiben:n {x,V}


\bool_new:N \l_phone_erstes_zeichen_bool
\bool_new:N \l_phone_zweites_zeichen_bool
\bool_new:N \l_phone_auslandsnummer_bool
\bool_new:N \l_phone_null_am_anfang_bool
\int_new:N \l_phone_bindestrichposition_int

% #1: eingebene Nummer
\cs_new_protected:Npn \phone_nummer_ueberpruefen:n #1
   {
      \tl_if_blank:nTF {#1}
         {
            \msg_warning:nn {phonenumbers} {empty input}
            \bool_set_true:N \l_phone_eingabe_leer_bool
         }
         {
            \bool_set_false:N \l_phone_eingabe_leer_bool
         }

      \str_clear:N \l_phone_bereinigte_nummer_str

      \bool_set_true:N \l_phone_erstes_zeichen_bool
      \bool_set_false:N \l_phone_zweites_zeichen_bool
      \bool_set_false:N \l_phone_auslandsnummer_bool
      \bool_set_false:N \l_phone_null_am_anfang_bool

      \tl_map_inline:nn {#1}
         {
            \clist_if_in:NnTF \c_phone_ziffern_clist {##1}
               {
                  % Ziffer eingelesen
                  \str_put_right:Nn \l_phone_bereinigte_nummer_str {##1}

                  \bool_lazy_and:nnT {\l_phone_erstes_zeichen_bool} { \str_if_eq_p:nn {##1} {0} }
                     {
                        \bool_set_true:N \l_phone_null_am_anfang_bool
                     }

                  \bool_if:NT \l_phone_zweites_zeichen_bool
                     {
                        \bool_set_false:N \l_phone_zweites_zeichen_bool

                        \bool_lazy_and:nnT {\l_phone_null_am_anfang_bool} { \str_if_eq_p:nn {##1} {0} }
                           {
                              \bool_set_true:N \l_phone_auslandsnummer_bool
                              \str_clear:N \l_phone_bereinigte_nummer_str
                           }
                     }

                  \bool_if:NT \l_phone_erstes_zeichen_bool
                     {
                        \bool_set_false:N \l_phone_erstes_zeichen_bool
                        \bool_set_true:N \l_phone_zweites_zeichen_bool
                     }
               }
               {
                  % keine Ziffer eingelesen
                  \bool_lazy_and:nnTF {\l_phone_erstes_zeichen_bool} { \str_if_eq_p:nn {##1} {+} }
                     {
                        % führendes + eingelesen
                        \bool_set_true:N \l_phone_auslandsnummer_bool
                        \bool_set_false:N \l_phone_erstes_zeichen_bool
                     }
                     {
                        \clist_if_in:NnF \c_phone_gliederungszeichen_clist {##1}
                           {
                              \str_if_eq:nnTF {##1} {-}
                                 {
                                    % Bindestrich eingelesen
                                    \str_put_right:Nn \l_phone_bereinigte_nummer_str {-}
                                 }
                                 {
                                    % unerlaubtes Zeichen (z. B. Buchstaben) eingelesen
                                    \msg_warning:nnx {phonenumbers} {illegal character} {##1}
                                 }
                           }
                     }
               }
         }

      \bool_if:NT \l_phone_auslandsnummer_bool
         {
            \int_set:Nn \l_tmpa_int { \str_count:N \l_phone_bereinigte_nummer_str }

            \int_compare:nNnTF {\l_tmpa_int} > {1}
               {
                  \str_if_eq:xnTF { \str_head:N \l_phone_bereinigte_nummer_str } {1}
                     {
                        \str_set:Nn \l_phone_land_str {US}
                        \str_set:Nx \l_phone_bereinigte_nummer_str { \str_tail:N \l_phone_bereinigte_nummer_str }
                     }
                     {
                        \int_compare:nNnTF {\l_tmpa_int} > {2}
                           {
                              \str_case:xnTF { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {2} }
                                 {
                                    {33} { \str_set:Nn \l_phone_land_str {FR} }
                                    {43} { \str_set:Nn \l_phone_land_str {AT} }
                                    {44} { \str_set:Nn \l_phone_land_str {UK} }
                                    {49} { \str_set:Nn \l_phone_land_str {DE} }
                                 }
                                 {
                                    \str_set:Nx \l_phone_bereinigte_nummer_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {3} {-1} }
                                    \str_put_left:Nn \l_phone_bereinigte_nummer_str {0}
                                 }
                                 {
                                    \int_compare:nNnTF {\l_tmpa_int} > {3}
                                       {
                                          \str_case:xnTF { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {3} }
                                             {
                                                {262} { \str_set:Nx \l_phone_bereinigte_nummer_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {4} {-1} } }
                                                {508} { } % Saint-Pierre-et-Miquelon
                                                {590} { \str_set:Nx \l_phone_bereinigte_nummer_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {4} {-1} } }
                                                {594} { \str_set:Nx \l_phone_bereinigte_nummer_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {4} {-1} } }
                                                {596} { \str_set:Nx \l_phone_bereinigte_nummer_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {4} {-1} } }
                                             }
                                             {
                                                \str_set:Nn \l_phone_land_str {FR}
                                                \str_put_left:Nn \l_phone_bereinigte_nummer_str {0}
                                             }
                                             {
                                                \str_clear:N \l_phone_land_str % Länge größer 3, nicht mit 262, 508, 590, 594 oder 596 beginnend
                                             }
                                       }
                                       {
                                          \str_clear:N \l_phone_land_str % Länge 3, nicht mit 49 oder 33 beginnend
                                       }
                                 }
                           }
                           {
                              \str_clear:N \l_phone_land_str % Länge 2, nicht mit 1 beginnend
                           }
                     }
               }
               {
                  \str_clear:N \l_phone_land_str % Länge kleiner oder gleich 1
               }
         }

      \bool_lazy_and:nnT
         {
            \bool_lazy_or_p:nn { \str_if_eq_p:Vn \l_phone_land_str {DE} } { \str_if_eq_p:Vn \l_phone_land_str {AT} }
         }
         {
            \str_if_empty_p:N \l_phone_bereinigte_durchwahl_str
         }
         {
            % deutsche oder österreichische Nummer ohne explizite Durchwahl
            \int_set:Nn \l_phone_bindestrichposition_int {-1}

            \int_step_inline:nnnn { \str_count:N \l_phone_bereinigte_nummer_str } {-1} {1}
               {
                  \int_compare:nNnT {\l_phone_bindestrichposition_int} = {-1}
                     {
                        \str_if_eq:xnT { \str_item:Nn \l_phone_bereinigte_nummer_str {##1} } {-}
                           {
                              \int_set:Nn \l_phone_bindestrichposition_int {##1}
                           }
                     }
               }

            \int_compare:nNnF {\l_phone_bindestrichposition_int} = {-1}
               {
                  % Nummer enthält einen Bindestrich
                  \str_set:Nx \l_tmpa_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} { \l_phone_bindestrichposition_int - 1 } }
                  \tl_remove_all:Nn \l_tmpa_str {-}

                  \phone_enthaelt_vorwahl:NT \l_tmpa_str
                     {
                        \int_compare:nNnT { \str_count:N \l_phone_vorwahl_str } < { \str_count:N \l_tmpa_str }
                           {
                              % dem Bindestrich geht eine Vorwahl voran und der Teil vor dem Bindestrich ist länger als die bloße Vorwahl
                              \bool_set_true:N \l_tmpa_bool
                           }
                     }

                  \str_if_eq:xnF { \str_head:N \l_tmpa_str } {0}
                     {
                        \bool_set_true:N \l_tmpa_bool
                        % Nummer beginnt nicht mit 0 (ist also eine reine Teilnehmerrufnummer)
                     }

                  \bool_if:NT \l_tmpa_bool
                     {
                        % Teil nach dem Bindestrich als Durchwahl abtrennen
                        \phone_durchwahl_ueberpruefen:x { \str_range:Nnn \l_phone_bereinigte_nummer_str { \l_phone_bindestrichposition_int + 1 } {-1} }
                        \str_set_eq:NN \l_phone_bereinigte_nummer_str \l_tmpa_str
                     }
               }
         }

         \tl_remove_all:Nn \l_phone_bereinigte_nummer_str {-}
   }

\cs_generate_variant:Nn \phone_nummer_ueberpruefen:n {x}


% #1: eingebene Durchwahl
\cs_new_protected:Npn \phone_durchwahl_ueberpruefen:n #1
   {
      \tl_if_blank:nTF {#1}
         {
            \msg_warning:nn {phonenumbers} {empty extension}
            \bool_set_true:N \l_phone_durchwahl_leer_bool
         }
         {
            \bool_set_false:N \l_phone_durchwahl_leer_bool
         }

      \str_clear:N \l_phone_bereinigte_durchwahl_str

      \tl_map_inline:nn {#1}
         {
            \clist_if_in:NnTF \c_phone_ziffern_clist {##1}
               {
                  \str_put_right:Nn \l_phone_bereinigte_durchwahl_str {##1}
               }
               {
                  \msg_warning:nnx {phonenumbers} {illegal character} {##1}
               }
         }
   }

\cs_generate_variant:Nn \phone_durchwahl_ueberpruefen:n {x}


\cs_new_protected:Npn \phone_nummer_ausgeben:
   {
      \bool_if:NF \l_phone_eingabe_leer_bool
         {
            \str_case:VnF \l_phone_land_str
               {
                  {DE} {\phone_DE_AT_nummer_schreiben:}
                  {AT} {\phone_DE_AT_nummer_schreiben:}
                  {FR} {\phone_FR_nummer_schreiben:}
                  {UK} {\phone_UK_nummer_schreiben:}
                  {US} {\phone_US_nummer_schreiben:}
               }
               {
                  \phone_SONST_nummer_schreiben:
               }
         }

      \bool_lazy_and:nnTF {\l_phone_nummer_verlinken_bool} { ! \str_if_empty_p:N \l_phone_linktext_str }
         {
            \ltx@ifpackageloaded {hyperref}
               {
                  \href { tel \c_colon_str \l_phone_linktext_str } {\l_phone_ausgabetext_tl}
               }
               {
                  \l_phone_ausgabetext_tl
               }
         }
         {
            \l_phone_ausgabetext_tl
         }
   }

\cs_new_protected:Npn \phone_vorwahlliste_ausgeben:n #1
   {
      \begin{tabbing}
      \str_case:VnF \l_phone_land_str
         {
            {US} { \hspace {3em} }
         }
         {
            \hspace {4em}
         }
      \=
      \kill

      \bool_set_false:N \l_phone_zeilenumbruch_bool

      \clist_map_inline:cn {c_phone_\l_phone_land_str _#1_clist}
         {
            \bool_if:NTF \l_phone_zeilenumbruch_bool
               {
                  \\
               }
               {
                  \bool_gset_true:N \l_phone_zeilenumbruch_bool
               }

            \str_case:VnTF \l_phone_land_str
               {
                  {DE} { }
                  {AT} { }
                  {UK} { }
               }
               {
                  \phone_gruppierte_vorwahl_schreiben:nN {##1} \c_true_bool
                  \tl_use:N \l_phone_ausgabetext_tl
               }
               {
                  \bool_if:nTF { \str_if_eq_p:Vn \l_phone_land_str {FR} }
                     {
                        \phone_von_vorne_gruppiert_schreiben:n {##1}
                        \tl_use:N \l_phone_ausgabetext_tl
                     }
                     {
                        ##1
                     }
               }
            \>
            \tl_if_exist:cTF {c_phone_\l_phone_land_str _ortsname_##1_tl}
               {
                  \tl_use:c {c_phone_\l_phone_land_str _ortsname_##1_tl}
               }
               {
                  UNKNOWN~PLACE
               }
         }
      \end{tabbing}
   }

\NewDocumentCommand \setphonenumbers {m}
   {
      \keys_set:no {phonenumbers} {#1}
   }

\NewDocumentCommand \phonenumber {omo}
   {
      \group_begin:
      \IfValueT {#1}
         {
            \keys_set:no {phonenumbers} {#1}
         }

      \IfValueT {#3}
         {
            \phone_durchwahl_ueberpruefen:x {#3}
         }

      \phone_nummer_ueberpruefen:x {#2}

      \IfValueT {#3}
         {
            \bool_lazy_or:nnF { \str_if_eq_p:Vn \l_phone_land_str {DE} } { \str_if_eq_p:Vn \l_phone_land_str {AT} }
               {
                  \bool_if:NF \l_phone_durchwahl_leer_bool
                     {
                        \msg_warning:nn {phonenumbers} {illegal extension}
                     }
               }
         }

      \phone_nummer_ausgeben:
      \group_end:
   }

\NewDocumentCommand \AreaCodesGeographic {o}
   {
      \group_begin:
      \IfValueT {#1}
         {
            \keys_set:no {phonenumbers} {#1}
         }

      \phone_vorwahlliste_ausgeben:n {ortsvorwahlen}
      \group_end:
   }

\NewDocumentCommand \AreaCodesNonGeographic {o}
   {
      \group_begin:
      \IfValueT {#1}
         {
            \keys_set:no {phonenumbers} {#1}
         }

      \phone_vorwahlliste_ausgeben:n {sondervorwahlen}
      \group_end:
   }

\file_input:n {phn-Landeskennzahlen}

\NewDocumentCommand \CountryCodes { }
   {
      \bool_set_false:N \l_phone_zeilenumbruch_bool

      \clist_map_inline:Nn \c_phone_landeskennzahlen_clist
         {
            \bool_if:NTF \l_phone_zeilenumbruch_bool
               {
                  \\
               }
               {
                  \bool_set_true:N \l_phone_zeilenumbruch_bool
               }

            ##1
         }
   }


\int_new:N \l_phone_pruefnummerlaenge_int

% #1: Nummer, die auf Enthaltensein einer Vorwahl überprüft wird
\prg_new_protected_conditional:Npnn \phone_enthaelt_vorwahl:N #1 {TF,T}
   {
      \bool_set_false:N \l_phone_vorwahl_gefunden_bool

      \int_set:Nn \l_phone_pruefnummerlaenge_int { \str_count:N #1 }

      \int_step_inline:nnnn {6} {-1} {2}
         {
            \bool_if:NF \l_phone_vorwahl_gefunden_bool
               {
                  \int_compare:nT { \l_phone_pruefnummerlaenge_int >= ##1 }
                     {
                        \str_set:Nx \l_phone_vorwahl_str { \str_range:Nnn #1 {1} {##1} }

                        \clist_if_in:cVT {c_phone_\l_phone_land_str _vorwahlen_clist} \l_phone_vorwahl_str
                           {
                              \bool_set_true:N \l_phone_vorwahl_gefunden_bool
                           }
                     }
               }
         }

      \bool_if:NTF \l_phone_vorwahl_gefunden_bool
         {
            \prg_return_true:
         }
         {
            \prg_return_false:
         }
   }


% #1: Vorwahl, #2: Soll die führende null ausgegeben werden?
\cs_new_protected:Npn \phone_gruppierte_vorwahl_schreiben:nN #1#2
   {
      \str_if_eq:VnTF \l_phone_land_str {UK}
         {
            % britische Vorwahl
            \int_compare:nNnTF { \str_count:n {#1} } = {6}
               {
                  % sechsstellige britische Vorwahl: Gliederung vor der zweitletzten Ziffer
                  \bool_if:NTF #2
                     {
                        \int_compare:nNnTF {\l_phone_gruppierungsminimum_int} > {6}
                           {
                              \tl_put_right:Nn \l_phone_ausgabetext_tl {#1}
                           }
                           {
                              \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_range:nnn {#1} {1} {4} }
                              \tl_put_right:Nn \l_phone_ausgabetext_tl {\,}
                              \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_range:nnn {#1} {5} {6} }
                           }
                     }
                     {
                        \int_compare:nNnTF {\l_phone_gruppierungsminimum_int} > {5}
                           {
                              \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_tail:n {#1} }
                           }
                           {
                              \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_range:nnn {#1} {2} {4} }
                              \tl_put_right:Nn \l_phone_ausgabetext_tl {\,}
                              \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_range:nnn {#1} {5} {6} }
                           }
                     }
               }
               {
                  % nicht sechsstellige britische Vorwahl
                  \bool_if:NTF #2
                     {
                        \tl_put_right:Nn \l_phone_ausgabetext_tl {#1}
                     }
                     {
                        \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_tail:n {#1} }
                     }
               }
         }
         {
            % nichtbritische Vorwahl
            \bool_lazy_and:nnTF { \str_if_eq_p:Vn \l_phone_land_str {DE} } { \int_compare_p:nNn { \str_count:n {#1} } = {5} }
               {
                  \str_set:Nx \l_tmpa_str { \str_range:nnn {#1} {1} {4} }

                  % fünfstellige deutsche Vorwahl
                  \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_tmpa_str {0137} } { \str_if_eq_p:Vn \l_tmpa_str {0180} }
                     {
                        % fünfstellige deutsche Vorwahl mit Tarifkennung: letzte Ziffer steht allein
                        \bool_if:NTF #2
                           {
                              \phone_von_vorne_gruppiert_schreiben:n {#1}
                           }
                           {
                              \phone_versetzt_gruppiert_schreiben:x { \str_tail:n {#1} }
                           }
                     }
                     {
                        % fünfstellige deutsche Vorwahl ohne Tarifkennung
                        \bool_if:NTF #2
                           {
                              \phone_von_hinten_gruppiert_schreiben:n {#1}
                           }
                           {
                              \phone_von_hinten_gruppiert_schreiben:x { \str_tail:n {#1} }
                           }
                     }
               }
               {
                  % sonstige Vorwahl
                  \bool_if:NTF #2
                     {
                        \phone_von_hinten_gruppiert_schreiben:n {#1}
                     }
                     {
                        \phone_von_hinten_gruppiert_schreiben:x { \str_tail:n {#1} }
                     }
               }
         }
   }

% #1: Vorwahl, #2: Soll die führende null ausgegeben werden?
\cs_new_protected:Npn \phone_geklammerte_vorwahl_schreiben:nN #1#2
   {
      % Klammern werden nur bei Ortsvorwahlen gesetzt
      \clist_if_in:cnTF {c_phone_\l_phone_land_str _ortsvorwahlen_clist} {#1}
         {
            \tl_put_right:Nn \l_phone_ausgabetext_tl {(}
            \phone_gruppierte_vorwahl_schreiben:nN {#1} #2
            \tl_put_right:Nn \l_phone_ausgabetext_tl {)}
         }
         {
            \phone_gruppierte_vorwahl_schreiben:nN {#1} #2
         }
   }

% #1: Nummer, #2: Mindestlänge, #3: Höchstlänge, #4: Nummernart
\cs_new_protected:Npn \phone_nummernlaenge_ueberpruefen:nnnn #1#2#3#4
   {
      \int_set:Nn \l_tmpa_int { \str_count:n {#1} }

      \int_compare:nNnTF {\l_tmpa_int} < {#2}
         {
            \msg_warning:nnnn {phonenumbers} {number too short} {#4} {#2}
         }
         {
            \int_compare:nNnTF {\l_tmpa_int} > {#3}
               {
                  \msg_warning:nnnn {phonenumbers} {number too long} {#4} {#3}
               }
               {
                  \bool_set_true:N \l_phone_teilnehmerrufnummer_gueltig_bool
               }
         }
   }

\cs_generate_variant:Nn \phone_nummernlaenge_ueberpruefen:nnnn {V,o}


%%%%%%%%%%%%%%%%%%%% DEUTSCHLAND %%%%%%%%%%%%%%%%%%%%

\file_input:n {phn-DE_Vorwahlen}
\file_input:n {phn-DE_Ortsnamen}

\clist_new:N \c_phone_DE_vorwahlen_clist
\clist_concat:NNN \c_phone_DE_vorwahlen_clist \c_phone_DE_ortsvorwahlen_clist \c_phone_DE_sondervorwahlen_clist


% #1: Vorwahl, #2: Folgt eine Rufnummer?
\cs_new_protected:Npn \phone_DE_AT_vorwahl_schreiben:nn #1 #2
   {
      \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_phone_auslandsvorwahltyp_str {off} } { \str_if_eq_p:NN \l_phone_heimatland_str \l_phone_land_str }
         {
            \clist_if_in:cnT {c_phone_\l_phone_land_str _sondervorwahlen_clist} {#1}
               {
                  \str_if_eq:VnT \l_phone_vorwahldarstellung_str {place}
                     {
                        \str_set:Nn \l_phone_vorwahldarstellung_str {number}
                     }
               }

            \bool_lazy_and:nnF { \str_if_eq_p:NN \l_phone_heimatland_str \l_phone_land_str } { \str_if_eq_p:Vn \l_phone_heimatvorwahl_str {#1} }
               {
                  \str_case:Vn \l_phone_vorwahldarstellung_str
                     {
                        {number}
                           {
                              \bool_if:nTF {#2}
                                 {
                                    \str_if_eq:VnTF \l_phone_vorwahltrennung_str {brackets}
                                       {
                                          \phone_geklammerte_vorwahl_schreiben:nN {#1} \c_true_bool
                                          \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                       }
                                       {
                                          \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool

                                          \tl_put_right:Nx \l_phone_ausgabetext_tl
                                             {
                                                \str_case:VnF \l_phone_vorwahltrennung_str
                                                   {
                                                      {space} {\c_space_tl}
                                                      {hyphen} {\c_phone_bindestrich_tl}
                                                   }
                                                   {
                                                      \c_phone_schraegstrich_tl
                                                   }
                                             }
                                       }
                                 }
                                 {
                                    \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                 }
                           }
                        {place}
                           {
                              \bool_if:nTF {#2}
                                 {
                                    \str_if_eq:VnT \l_phone_vorwahltrennung_str {brackets}
                                       {
                                          \tl_put_right:Nn \l_phone_ausgabetext_tl {(}
                                       }

                                    \tl_if_exist:cTF {c_phone_\l_phone_land_str _ortsname_#1_tl}
                                       {
                                          \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_\l_phone_land_str _ortsname_#1_tl}
                                       }
                                       {
                                          \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                       }

                                    \tl_put_right:Nx \l_phone_ausgabetext_tl
                                       {
                                          \str_case:VnF \l_phone_vorwahltrennung_str
                                             {
                                                {brackets} {) \c_space_tl}
                                                {space} {\c_space_tl}
                                                {hyphen} {\c_phone_bindestrich_tl}
                                             }
                                             {
                                                \c_phone_schraegstrich_tl
                                             }
                                       }
                                 }
                                 {
                                    \tl_if_exist:cTF {c_phone_\l_phone_land_str _ortsname_#1_tl}
                                       {
                                          \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_\l_phone_land_str _ortsname_#1_tl}
                                       }
                                       {
                                          \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                       }
                                 }
                           }
                        {place-and-number}
                           {
                              \tl_if_exist:cT {c_phone_\l_phone_land_str _ortsname_#1_tl}
                                 {
                                    \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_\l_phone_land_str _ortsname_#1_tl}
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                 }

                              \str_if_eq:VnTF \l_phone_vorwahltrennung_str {brackets}
                                 {
                                    \phone_geklammerte_vorwahl_schreiben:nN {#1} \c_true_bool

                                    \bool_if:nT {#2}
                                       {
                                          \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                       }
                                 }
                                 {
                                    \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool

                                    \bool_if:nT {#2}
                                       {
                                          \tl_put_right:Nx \l_phone_ausgabetext_tl
                                             {
                                                \str_case:VnF \l_phone_vorwahltrennung_str
                                                   {
                                                      {space} {\c_space_tl}
                                                      {hyphen} {\c_phone_bindestrich_tl}
                                                   }
                                                   {
                                                      \c_phone_schraegstrich_tl
                                                   }
                                             }
                                       }
                                 }
                           }
                     }
               }
         }
         {
            \str_if_eq:VnTF \l_phone_land_str {DE}
               {
                  \phone_auslandsvorwahl_schreiben:n {49}
               }
               {
                  \phone_auslandsvorwahl_schreiben:n {43}
               }

            \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl

            \str_if_eq:VnTF \l_phone_auslandsvorwahltrennung_str {brackets}
               {
                  \phone_geklammerte_vorwahl_schreiben:nN {#1} \c_false_bool
               }
               {
                  \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_false_bool
               }

            \bool_if:nT {#2}
               {
                  \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
               }
         }

      % Linktext schreiben, falls eine Rufnummer folgt
      \bool_if:nT {#2}
         {
            \str_put_right:Nx \l_phone_linktext_str
               {
                  \str_if_eq:VnTF \l_phone_land_str {DE} {+49} {+43}
               }
            \str_put_right:Nx \l_phone_linktext_str { \str_tail:n {#1} }
         }
   }

\cs_generate_variant:Nn \phone_DE_AT_vorwahl_schreiben:nn {Vx}


% #1: Vorwahl, #2: Teilnehmerrufnummer
\cs_new_protected:Npn \phone_DE_festnetzteilnehmerrufnummernlaenge_ueberpruefen:Nn #1#2
   {
      \int_set:Nn \l_tmpa_int { \str_count:N #1 }
      \int_add:Nn \l_tmpa_int { \str_count:n {#2} }
      \int_add:Nn \l_tmpa_int { \str_count:N \l_phone_bereinigte_durchwahl_str }

      \int_compare:nNnTF {\l_tmpa_int} > {13}
         {
            % Gesamtnummer hat mehr als 13 Stellen
            \msg_warning:nnnn {phonenumbers} {number too long} {landline} {13}
         }
         {
            \int_set:Nn \l_tmpa_int { \str_count:n {#2} }
            \int_add:Nn \l_tmpa_int { \str_count:N \l_phone_bereinigte_durchwahl_str }

            \int_compare:nNnTF {\l_tmpa_int} < {3}
               {
                  % Teilnehmerrufnummer hat weniger als 3 Stellen
                  \msg_warning:nnn {phonenumbers} {subscriber number too short} {3}
               }
               {
                  \bool_set_true:N \l_phone_teilnehmerrufnummer_gueltig_bool
               }
         }
   }

% #1: Nummer
\cs_new_protected:Npn \phone_DE_MABEZnummernlaenge_ueberpruefen:N #1
   {
      \int_set:Nn \l_tmpa_int { \str_count:N #1 }
      \int_add:Nn \l_tmpa_int { \str_count:N \l_phone_bereinigte_durchwahl_str }

      \int_compare:nNnTF {\l_tmpa_int} > {11}
         {
            % Gesamtnummer hat mehr als 11 Stellen
            \msg_warning:nnnn {phonenumbers} {number too long} {0137~(MABEZ)} {11}
         }
         {
            \int_compare:nNnTF {\l_tmpa_int} < {11}
               {
                  % Gesamtnummer hat weniger als 11 Stellen
                  \msg_warning:nnnn {phonenumbers} {number too short} {0137~(MABEZ)} {11}
               }
               {
                  \bool_set_true:N \l_phone_teilnehmerrufnummer_gueltig_bool
               }
         }
   }

% #1: Vorwahl, #2: Teilnehmerrufnummer
\cs_new_protected:Npn \phone_DE_teilnehmerrufnummer_schreiben:Nn #1 #2
   {
      % Überprüfen der Nummernlänge
      \str_if_empty:NTF #1
         {
            % Festnetznummer ohne Vorwahl
            \bool_if:NF \l_phone_eingabe_leer_bool
               {
                  \phone_DE_festnetzteilnehmerrufnummernlaenge_ueberpruefen:Nn #1 {#2}
               }
         }
         {
            \clist_if_in:NVTF \c_phone_DE_ortsvorwahlen_clist #1
               {
                  % Festnetznummer
                  \str_if_eq:xnTF { \str_head:n {#2} } {0}
                     {
                        \msg_warning:nnn {phonenumbers} {illegal start of subscriber number} {0}
                     }
                     {
                        \phone_DE_festnetzteilnehmerrufnummernlaenge_ueberpruefen:Nn #1 {#2}
                     }
               }
               {
                  % Mobilfunk-/Sondernummer
                  \str_set_eq:NN \l_tmpa_str #1
                  \str_put_right:Nn \l_tmpa_str {#2}

                  \str_if_eq:xnTF { \str_range:Nnn #1 {1} {5} } {09009}
                     {
                        \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {12} {12} {09009}
                     }
                     {
                        \str_case:xnF { \str_range:Nnn #1 {1} {4} }
                           {
                              {0137} { \phone_DE_MABEZnummernlaenge_ueberpruefen:N \l_tmpa_str }
                              {0160} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {12} {mobile~phone} }
                              {0162} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {12} {mobile~phone} }
                              {0163} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {12} {mobile~phone} }
                              {0164} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {5} {14} {0164} } % Funkruf
                              {0168} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {5} {15} {0168} } % Funkruf
                              {0169} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {5} {15} {0169} } % Funkruf
                              {0180} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {11} {0180} }
                              {0181} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {8} {15} {0181} }
                              {0191} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {5} {14} {0191} }
                              {0192} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {5} {14} {0192} }
                              {0193} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {5} {14} {0193} }
                              {0194} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {7} {14} {0194} }
                              {0700} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {12} {12} {0700} }
                              {0800} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {14} {freephone} }
                              {0900} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {11} {premium~service} }
                           }
                           {
                              \str_case:xn {\str_range:Nnn #1 {1} {3}}
                                 {
                                    {015} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {12} {12} {mobile~phone} }
                                    {017} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {11} {12} {mobile~phone} }
                                    {018} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {12} {12} {018} }
                                    {032} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {12} {12} {032} }
                                 }
                           }
                     }

                  \str_if_empty:NF \l_phone_bereinigte_durchwahl_str
                     {
                        % Mobilfunk- und Sondernummern dürfen keine Durchwahl enthalten (ausgenommen MABEZ-Nummern)
                        \str_if_eq:xnF { \str_range:Nnn #1 {1} {4} } {0137}
                           {
                              \msg_warning:nn {phonenumbers} {odd extension}
                           }
                     }
               }

            \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
               {
                  % Für gültige Nummern mit Vorwahl Linktext schreiben:
                  \str_put_right:Nn \l_phone_linktext_str {#2}
                  \str_put_right:NV \l_phone_linktext_str \l_phone_bereinigte_durchwahl_str
               }
               {
                  % Für ungültige Nummern mit Vorwahl Linktext löschen:
                  \str_clear:N \l_phone_linktext_str
               }
         }

      \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
         {
            \phone_von_hinten_gruppiert_schreiben:n {#2}
         }
         {
            \str_put_right:Nn \l_phone_ausgabetext_tl {#2}
         }

      \str_if_empty:NF \l_phone_bereinigte_durchwahl_str
         {
            \tl_put_right:NV \l_phone_ausgabetext_tl \c_phone_bindestrich_tl
            \phone_von_hinten_gruppiert_schreiben:V \l_phone_bereinigte_durchwahl_str
         }
   }

\cs_generate_variant:Nn \phone_DE_teilnehmerrufnummer_schreiben:Nn {Nx,NV}


\int_new:N \l_phone_DE_AT_hauptnummerlaenge_int
\int_new:N \l_phone_DE_AT_vorwahllaenge_int

\cs_new_protected:Npn \phone_DE_AT_nummer_schreiben:
   {
      \str_if_eq:xnTF { \str_head:N \l_phone_bereinigte_nummer_str } {0}
         {
            \phone_enthaelt_vorwahl:NTF \l_phone_bereinigte_nummer_str
               {
                  \int_set:Nn \l_phone_DE_AT_hauptnummerlaenge_int { \str_count:N \l_phone_bereinigte_nummer_str }
                  \int_set:Nn \l_phone_DE_AT_vorwahllaenge_int { \str_count:N \l_phone_vorwahl_str }

                  \phone_DE_AT_vorwahl_schreiben:Vx \l_phone_vorwahl_str
                     {
                        \int_compare_p:nNn {\l_phone_DE_AT_vorwahllaenge_int} < {\l_phone_DE_AT_hauptnummerlaenge_int}
                     }

                  \int_compare:nNnTF {\l_phone_DE_AT_vorwahllaenge_int} = {\l_phone_DE_AT_hauptnummerlaenge_int}
                     {
                        \msg_warning:nn {phonenumbers} {missing subscriber number}
                     }
                     {
                        \use:c {phone_\l_phone_land_str _teilnehmerrufnummer_schreiben:Nx} \l_phone_vorwahl_str
                           {
                              \str_range:Nnn \l_phone_bereinigte_nummer_str { \l_phone_DE_AT_vorwahllaenge_int + 1 } {-1}
                           }
                     }
               }
               {
                  \msg_warning:nn {phonenumbers} {invalid area code}
                  \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                  \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_durchwahl_str
               }
         }
         {
            \use:c {phone_\l_phone_land_str _teilnehmerrufnummer_schreiben:NV} \c_empty_tl \l_phone_bereinigte_nummer_str
         }
   }


%%%%%%%%%%%%%%%%%%%% ÖSTERREICH %%%%%%%%%%%%%%%%%%%%

\file_input:n {phn-AT_Vorwahlen}
\file_input:n {phn-AT_Ortsnamen}

\clist_new:N \c_phone_AT_vorwahlen_clist
\clist_concat:NNN \c_phone_AT_vorwahlen_clist \c_phone_AT_ortsvorwahlen_clist \c_phone_AT_sondervorwahlen_clist


% #1: Vorwahl, #2: Teilnehmerrufnummer
\cs_new_protected:Npn \phone_AT_festnetzteilnehmerrufnummernlaenge_ueberpruefen:Nn #1#2
   {
      \int_set:Nn \l_tmpa_int { \str_count:N #1 }
      \int_add:Nn \l_tmpa_int { \str_count:n {#2} }
      \int_add:Nn \l_tmpa_int { \str_count:N \l_phone_bereinigte_durchwahl_str }

      \int_compare:nNnTF {\l_tmpa_int} > {13}
         {
            % Gesamtnummer hat mehr als 13 Stellen
            \msg_warning:nnnn {phonenumbers} {number too long} {landline} {13}
         }
         {
            \int_set:Nn \l_tmpa_int { \str_count:n {#2} }
            \int_add:Nn \l_tmpa_int { \str_count:N \l_phone_bereinigte_durchwahl_str }

            \int_compare:nNnTF {\l_tmpa_int} < {5}
               {
                  % Teilnehmerrufnummer hat weniger als 5 Stellen
                  \msg_warning:nnn {phonenumbers} {subscriber number too short} {5}
               }
               {
                  \bool_lazy_and:nnTF { \str_if_eq_p:Vn #1 {01} } { \int_compare_p:nNn {\l_tmpa_int} < {7} }
                     {
                        % Wiener Teilnehmerrufnummer hat weniger als 7 Stellen
                        \msg_warning:nnn {phonenumbers} {subscriber number too short} {7}
                     }
                     {
                        \bool_lazy_and:nnTF
                           {
                              \bool_lazy_any_p:n
                                 {
                                    { \str_if_eq_p:Vn #1 {02236} }
                                    { \str_if_eq_p:Vn #1 {02252} }
                                    { \str_if_eq_p:Vn #1 {0316} }
                                    { \str_if_eq_p:Vn #1 {0463} }
                                    { \str_if_eq_p:Vn #1 {0512} }
                                    { \str_if_eq_p:Vn #1 {05572} }
                                    { \str_if_eq_p:Vn #1 {0662} }
                                    { \str_if_eq_p:Vn #1 {07242} }
                                    { \str_if_eq_p:Vn #1 {0732} }
                                 }
                           }
                           {
                              \int_compare_p:nNn {\l_tmpa_int} < {6}
                           }
                           {
                              % Teilnehmerrufnummer in bestimmten Ortsnetzen hat weniger als 6 Stellen
                              \msg_warning:nnn {phonenumbers} {subscriber number too short} {6}
                           }
                           {
                              \int_compare:nNnTF {\l_tmpa_int} > {9}
                                 {
                                    % Teilnehmerrufnummer hat mehr als 9 Stellen
                                    \msg_warning:nnn {phonenumbers} {subscriber number too long} {9}
                                 }
                                 {
                                    \bool_set_true:N \l_phone_teilnehmerrufnummer_gueltig_bool
                                 }
                           }
                     }
               }
         }
   }

% #1: Vorwahl, #2: Teilnehmerrufnummer
\cs_new_protected:Npn \phone_AT_festnetzteilnehmerrufnummer_ueberpruefen:Nn #1#2
   {
      \str_set:Nx \l_tmpa_str { \str_head:n {#2} }

      \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_tmpa_str {0} } { \str_if_eq_p:Vn \l_tmpa_str {1} }
         {
            \msg_warning:nnV {phonenumbers} {illegal start of subscriber number} \l_tmpa_str
         }
         {
            \phone_AT_festnetzteilnehmerrufnummernlaenge_ueberpruefen:Nn #1 {#2}
         }
   }

% #1: Vorwahl, #2: Teilnehmerrufnummer
\cs_new_protected:Npn \phone_AT_teilnehmerrufnummer_schreiben:Nn #1 #2
   {
      \str_if_empty:NTF #1
         {
            % Festnetznummer ohne Vorwahl
            \bool_if:NF \l_phone_eingabe_leer_bool
               {
                  \phone_AT_festnetzteilnehmerrufnummer_ueberpruefen:Nn #1 {#2}
               }
         }
         {
            \clist_if_in:NVTF \c_phone_AT_ortsvorwahlen_clist #1
               {
                  % Festnetznummer mit Vorwahl
                  \phone_AT_festnetzteilnehmerrufnummer_ueberpruefen:Nn #1 {#2}
               }
               {
                  % Mobilfunk-/Sondernummer
                  \str_set_eq:NN \l_tmpa_str #1
                  \str_put_right:Nn \l_tmpa_str {#2}

                  \str_case:VnF #1
                     {
                        {0517} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {VPN} }
                        {0718} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {dial~up} }
                        {0720} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {location~independant} }
                        {0780} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {convergent~service} }
                        {0800} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {freephone} }
                        {0804} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {dial~up} }
                        {0810} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {service} }
                        {0820} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {service} }
                        {0821} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {service} }
                        {0828} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {service} }
                        {0900} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {premium~service} }
                        {0901} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {premium~service} }
                        {0930} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {premium~service} }
                        {0931} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {premium~service} }
                        {0939} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {10} {13} {premium~service} }
                     }
                     {
                        \str_case:xn { \str_range:Nnn #1 {1} {3} }
                           {
                              {050} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {VPN} }
                              {057} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {VPN} }
                              {059} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {VPN} }
                              {065} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {mobile~phone} }
                              {066} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {mobile~phone} }
                              {067} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {mobile~phone} }
                              {068} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {mobile~phone} }
                              {069} { \phone_nummernlaenge_ueberpruefen:Vnnn \l_tmpa_str {9} {13} {mobile~phone} }
                           }
                     }

                  \str_if_empty:NF \l_phone_bereinigte_durchwahl_str
                     {
                        \msg_warning:nn {phonenumbers} {odd extension}
                     }
               }

            \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
               {
                  % Für gültige Nummern mit Vorwahl Linktext schreiben:
                  \str_put_right:Nn \l_phone_linktext_str {#2}
                  \str_put_right:NV \l_phone_linktext_str \l_phone_bereinigte_durchwahl_str
               }
               {
                  % Für ungültige Nummern mit Vorwahl Linktext löschen:
                  \str_clear:N \l_phone_linktext_str
               }
         }

      \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
         {
            \phone_von_hinten_gruppiert_schreiben:n {#2}
         }
         {
            \str_put_right:Nn \l_phone_ausgabetext_tl {#2}
         }

      \str_if_empty:NF \l_phone_bereinigte_durchwahl_str
         {
            \tl_put_right:NV \l_phone_ausgabetext_tl \c_phone_bindestrich_tl
            \phone_von_hinten_gruppiert_schreiben:V \l_phone_bereinigte_durchwahl_str
         }
   }

\cs_generate_variant:Nn \phone_AT_teilnehmerrufnummer_schreiben:Nn {Nx,NV}


%%%%%%%%%%%%%%%%%%%% FRANKREICH %%%%%%%%%%%%%%%%%%%%

\file_input:n {phn-FR_Vorwahlen}
\file_input:n {phn-FR_Ortsnamen}

\clist_new:N \c_phone_FR_vorwahlen_clist
\clist_concat:NNN \c_phone_FR_vorwahlen_clist \c_phone_FR_ortsvorwahlen_clist \c_phone_FR_sondervorwahlen_clist

\msg_new:nnn {phonenumbers} {FR/illegal home area code}
   {
      The~only~legal~home~area~code~in~France~is~0508~(Saint-Pierre-et-Miquelon).~#1~cannot~be~set~as~home~area~code~\msg_line_context:.
   }

\msg_new:nnn {phonenumbers} {FR/missing zero}
   {
      French~phone~number~has~no~zero~in~the~beginning~\msg_line_context:
   }


% #1: Vorwahl
\cs_new:Npn \phone_FR_ermittle_landeskennzahl:n #1
   {
      \str_case:nnF {#1}
         {
            {0262} {262}
            {026200} {262}
            {0263} {262}
            {0269} {262}
            {0508} {508}
            {0590} {590}
            {0594} {594}
            {0596} {596}
            {0639} {262}
            {0690} {590}
            {0691} {590}
            {0692} {262}
            {0693} {262}
            {0694} {594}
            {0696} {596}
            {0697} {596}
            {07005} {590}
            {07006} {594}
            {07007} {596}
            {07008} {262}
            {07009} {262}
            {09475} {590}
            {09476} {594}
            {09477} {596}
            {09478} {262}
            {09479} {262}
            {09760} {590}
            {09761} {590}
            {09762} {262}
            {09763} {262}
            {09764} {594}
            {09765} {594}
            {09766} {596}
            {09767} {596}
            {09768} {590}
            {09769} {262}
         }
         {
            33
         }
   }

% #1: Vorwahl, #2: Rufnummer
\cs_new_protected:Npn \phone_FR_vorwahl_und_rufnummer_schreiben:nn #1#2
   {
      \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_phone_auslandsvorwahltyp_str {off} } { \str_if_eq_p:Vn \l_phone_heimatland_str {FR} }
         {
            \clist_if_in:NnT \c_phone_FR_sondervorwahlen_clist {#1}
               {
                  \str_if_eq:VnT \l_phone_vorwahldarstellung_str {place}
                     {
                        \str_set:Nn \l_phone_vorwahldarstellung_str {number}
                     }
               }

            \bool_lazy_and:nnTF { \str_if_eq_p:Vn \l_phone_heimatland_str {FR} } { \str_if_eq_p:Vn \l_phone_heimatvorwahl_str {#1} }
               {
                   \phone_von_hinten_gruppiert_schreiben:n {#2}   % reine Teilnehmerrufnummer in Saint-Pierre-et-Miquelon
               }
               {
                  \str_case:Vn \l_phone_vorwahldarstellung_str
                     {
                        {number}
                           {
                              \phone_von_vorne_gruppiert_schreiben:V \l_phone_bereinigte_nummer_str
                           }
                        {place}
                           {
                              \tl_if_exist:cTF {c_phone_FR_ortsname_#1_tl}
                                 {
                                    \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_FR_ortsname_#1_tl}
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                    \phone_von_vorne_gruppiert_schreiben:n {#2}
                                 }
                                 {
                                    \phone_von_vorne_gruppiert_schreiben:V \l_phone_bereinigte_nummer_str
                                 }
                           }
                        {place-and-number}
                           {
                              \tl_if_exist:cT {c_phone_FR_ortsname_#1_tl}
                                 {
                                    \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_FR_ortsname_#1_tl}
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                 }

                              \phone_von_vorne_gruppiert_schreiben:V \l_phone_bereinigte_nummer_str
                           }
                     }
               }
         }
         {
            \phone_auslandsvorwahl_schreiben:x { \phone_FR_ermittle_landeskennzahl:n {#1} }

            \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl

            \str_if_eq:nnTF {#1} {0508}   % in Saint-Pierre-et-Miquelon entfällt die Ortsvorwahl
               {
                  \phone_von_hinten_gruppiert_schreiben:n {#2}
               }
               {
                  \phone_von_hinten_gruppiert_schreiben:x { \str_tail:N \l_phone_bereinigte_nummer_str }
               }
         }

      % Linktext schreiben:
      \str_put_right:Nx \l_phone_linktext_str { + \phone_FR_ermittle_landeskennzahl:n {#1} }
      \str_if_eq:nnF {#1} {0508}   % in Saint-Pierre-et-Miquelon entfällt die Ortsvorwahl
         {
            \str_put_right:Nx \l_phone_linktext_str { \str_tail:n {#1} }
         }
      \str_put_right:Nn \l_phone_linktext_str {#2}
   }

\cs_generate_variant:Nn \phone_FR_vorwahl_und_rufnummer_schreiben:nn {Vx,xx}


\cs_new_protected:Npn \phone_FR_nummer_schreiben:
   {
      \int_set:Nn \l_phone_nummerlaenge_int { \str_count:N \l_phone_bereinigte_nummer_str }

      \int_compare:nNnTF {\l_phone_nummerlaenge_int} < {10}
         {
            \str_if_eq:xnTF { \str_head:N \l_phone_bereinigte_nummer_str } {3}
               {
                  \int_compare:nNnTF {\l_phone_nummerlaenge_int} < {4}
                     {
                        \msg_warning:nnnn {phonenumbers} {number too short} {short} {4}
                        \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                     }
                     {
                        \int_compare:nNnTF {\l_phone_nummerlaenge_int} > {4}
                           {
                              \msg_warning:nnnn {phonenumbers} {number too long} {short} {4}
                              \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                           }
                           {
                              \phone_von_vorne_gruppiert_schreiben:V \l_phone_bereinigte_nummer_str
                              \str_put_right:NV \l_phone_linktext_str \l_phone_bereinigte_nummer_str
                           }
                     }
               }
               {
                  \msg_warning:nnnn {phonenumbers} {number too short} {phone} {10}
                  \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
               }
         }
         {
            \int_compare:nNnTF {\l_phone_nummerlaenge_int} > {10}
               {
                  \str_if_eq:xnTF { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {4} } {0700}
                     {
                        \int_compare:nNnTF { \str_item:Nn \l_phone_bereinigte_nummer_str {5} } < {5}
                           {
                              % überlange Mobilfunknummer (machine to machine) im Mutterland (14 Stellen)
                              \phone_nummernlaenge_ueberpruefen:Vnnn \l_phone_bereinigte_nummer_str {14} {14} {machine~to~machine}
                              \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
                                 {
                                    \phone_FR_vorwahl_und_rufnummer_schreiben:xx
                                       {
                                          \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {4}
                                       }
                                       {
                                          \str_range:Nnn \l_phone_bereinigte_nummer_str {5} {-1}
                                       }
                                 }
                                 {
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                                 }
                           }
                           {
                              % überlange Mobilfunknummer (machine to machine) in den Überseegebieten (13 Stellen)
                              \phone_nummernlaenge_ueberpruefen:Vnnn \l_phone_bereinigte_nummer_str {13} {13} {machine~to~machine}
                              \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
                                 {
                                    \phone_FR_vorwahl_und_rufnummer_schreiben:xx
                                       {
                                           \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {5}
                                       }
                                       {
                                          \str_range:Nnn \l_phone_bereinigte_nummer_str {6} {-1}
                                       }
                                 }
                                 {
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                                 }
                           }
                     }
                     {
                        \msg_warning:nnnn {phonenumbers} {number too long} {phone} {10}
                        \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                     }
               }
               {
                  \str_if_eq:xnTF { \str_head:N \l_phone_bereinigte_nummer_str } {0}
                     {
                        \bool_set_false:N \l_phone_vorwahl_gefunden_bool

                        \int_step_inline:nnnn {6} {-1} {2}
                           {
                              \bool_if:NF \l_phone_vorwahl_gefunden_bool
                                 {
                                    \int_compare:nT { \l_phone_nummerlaenge_int >= ##1 }
                                       {
                                          \str_set:Nx \l_tmpa_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {##1} }

                                          \clist_if_in:NVT \c_phone_FR_vorwahlen_clist \l_tmpa_str
                                             {
                                                \bool_set_true:N \l_phone_vorwahl_gefunden_bool
                                                \phone_FR_vorwahl_und_rufnummer_schreiben:Vx \l_tmpa_str
                                                   {
                                                      \str_range:Nnn \l_phone_bereinigte_nummer_str {##1 + 1} {-1}
                                                   }
                                             }
                                       }
                                 }
                           }

                        \bool_if:NF \l_phone_vorwahl_gefunden_bool
                           {
                              \msg_warning:nn {phonenumbers} {invalid area code}
                              \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                           }
                     }
                     {
                        \msg_warning:nn {phonenumbers} {FR/missing zero}
                        \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
                     }
               }
         }
   }


%%%%%%%%%%%%%%%%%%%% GROSSBRITANNIEN %%%%%%%%%%%%%%%%%%%%

\file_input:n {phn-UK_Vorwahlen}
\file_input:n {phn-UK_Ortsnamen}

\clist_new:N \c_phone_UK_vorwahlen_clist
\clist_concat:NNN \c_phone_UK_vorwahlen_clist \c_phone_UK_ortsvorwahlen_clist \c_phone_UK_sondervorwahlen_clist

\msg_new:nnn {phonenumbers} {UK/illegal home area code}
   {
      National~dialling~is~required~in~\tl_use:c {c_phone_UK_ortsname_#1_tl}.~#1~cannot~be~set~as~home~area~code~\msg_line_context:.
   }

\msg_new:nnn {phonenumbers} {UK/national dialling required}
   {
      British~subscriber~number~starting~with~0~or~1~requires~an~area~code~\msg_line_context:
   }


% #1: Vorwahl, #2: Folgt eine Rufnummer?
\cs_new_protected:Npn \phone_UK_vorwahl_schreiben:nn #1 #2
   {
      \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_phone_auslandsvorwahltyp_str {off} } { \str_if_eq_p:Vn \l_phone_heimatland_str {UK} }
         {
            \clist_if_in:NnT \c_phone_UK_sondervorwahlen_clist {#1}
               {
                  \str_if_eq:VnT \l_phone_vorwahldarstellung_str {place}
                     {
                        \str_set:Nn \l_phone_vorwahldarstellung_str {number}
                     }
               }

            \bool_lazy_and:nnF { \str_if_eq_p:Vn \l_phone_heimatland_str {UK} } { \str_if_eq_p:Vn \l_phone_heimatvorwahl_str {#1} }
               {
                  \str_case:Vn \l_phone_vorwahldarstellung_str
                     {
                        {number}
                           {
                              \bool_if:nTF {#2}
                                 {
                                    \str_if_eq:VnTF \l_phone_vorwahltrennung_str {space}
                                       {
                                          \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                       }
                                       {
                                          \phone_geklammerte_vorwahl_schreiben:nN {#1} \c_true_bool
                                       }

                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                 }
                                 {
                                    \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                 }
                           }
                        {place}
                           {
                              \bool_if:nTF {#2}
                                 {
                                    \str_if_eq:VnF \l_phone_vorwahltrennung_str {space}
                                       {
                                          \tl_put_right:Nn \l_phone_ausgabetext_tl {(}
                                       }

                                    \tl_if_exist:cTF {c_phone_UK_ortsname_#1_tl}
                                       {
                                          \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_UK_ortsname_#1_tl}
                                       }
                                       {
                                          \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                       }

                                    \str_if_eq:VnF \l_phone_vorwahltrennung_str {space}
                                       {
                                          \tl_put_right:Nn \l_phone_ausgabetext_tl {)}
                                       }

                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                 }
                                 {
                                    \tl_if_exist:cTF {c_phone_UK_ortsname_#1_tl}
                                       {
                                          \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_UK_ortsname_#1_tl}
                                       }
                                       {
                                          \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                       }
                                 }
                           }
                        {place-and-number}
                           {
                              \tl_if_exist:cT {c_phone_UK_ortsname_#1_tl}
                                 {
                                    \tl_put_right:Nv \l_phone_ausgabetext_tl {c_phone_UK_ortsname_#1_tl}
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                 }

                              \str_if_eq:VnTF \l_phone_vorwahltrennung_str {space}
                                 {
                                    \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_true_bool
                                 }
                                 {
                                    \phone_geklammerte_vorwahl_schreiben:nN {#1} \c_true_bool
                                 }

                              \bool_if:nT {#2}
                                 {
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                 }
                           }
                     }
               }
         }
         {
            \phone_auslandsvorwahl_schreiben:n {44}

            \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl

            \str_if_eq:VnTF \l_phone_auslandsvorwahltrennung_str {space}
               {
                  \phone_gruppierte_vorwahl_schreiben:nN {#1} \c_false_bool
               }
               {
                  \phone_geklammerte_vorwahl_schreiben:nN {#1} \c_false_bool
               }

            \bool_if:nT {#2}
               {
                  \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
               }
         }

      % Linktext schreiben, falls eine Rufnummer folgt
      \bool_if:nT {#2}
         {
            \str_put_right:Nn \l_phone_linktext_str {+44}
            \str_put_right:Nx \l_phone_linktext_str { \str_tail:n {#1} }
         }
   }

\cs_generate_variant:Nn \phone_UK_vorwahl_schreiben:nn {Vx}


% #1: Vorwahl, #2: Teilnehmerrufnummer
\cs_new_protected:Npn \phone_UK_teilnehmerrufnummer_schreiben:Nn #1 #2
   {
      % Überprüfen der Nummernlänge
      \str_if_empty:NTF #1
         {
            % Festnetznummer ohne Vorwahl (kann zwischen 4 und 8 Ziffern haben)
            \phone_nummernlaenge_ueberpruefen:nnnn {#2} {4} {8} {landline}

            % Nummern, die mit 0 oder 1 beginnen, erfordern das Wählen der Vorwahl
            \str_case:xnT { \str_head:n {#2} }
               {
                  {0} { }
                  {1} { }
               }
               {
                  \msg_warning:nn {phonenumbers} {UK/national dialling required}
               }
         }
         {
            \clist_if_in:NVTF \c_phone_UK_ortsvorwahlen_clist #1
               {
                  % Festnetznummer, muss in der Regel 11 Ziffern umfassen
                  % Ausnahme: Bei den Vorwahlen 01XXX und 016977 sind auch 10 Ziffern möglich.
                  \bool_lazy_or:nnTF { \str_if_eq_p:Vn #1 {016977} } { \int_compare_p:nNn { \str_count:N #1 } = {5} }
                     {
                        \phone_nummernlaenge_ueberpruefen:onnn {#1#2} {10} {11} {landline}
                     }
                     {
                        \phone_nummernlaenge_ueberpruefen:onnn {#1#2} {11} {11} {landline}
                     }
               }
               {
                  % Mobilfunk-/Sondernummer
                  \str_if_eq:xnTF { \str_range:Nnn #1 {1} {4} } {0800}
                     {
                        % 0800er-Nummern haben 10 oder 11 Ziffern; Ausnahme: 0800 1111
                        \str_if_eq:nnTF {#2} {1111}
                           {
                              \bool_set_true:N \l_phone_teilnehmerrufnummer_gueltig_bool
                           }
                           {
                              \phone_nummernlaenge_ueberpruefen:onnn {#1#2} {10} {11} {freephone}
                           }
                     }
                     {
                        % alle anderen Sondernummern haben 11 Ziffern
                        \phone_nummernlaenge_ueberpruefen:onnn {#1#2} {11} {11} {non-geographic}
                     }
               }

            \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
               {
                  % Für gültige Nummern mit Vorwahl Linktext schreiben:
                  \str_put_right:Nn \l_phone_linktext_str {#2}
               }
               {
                  % Für ungültige Nummern mit Vorwahl Linktext löschen:
                  \str_clear:N \l_phone_linktext_str
               }
         }

      \bool_if:NTF \l_phone_teilnehmerrufnummer_gueltig_bool
         {
            \int_compare:nNnTF { \str_count:n {#2} } > {6}
               {
                  % Nummern mit mehr als 6 Ziffern werden in Vierergruppen gegliedert
                  \str_put_right:Nx \l_phone_ausgabetext_tl { \str_range:nnn {#2} {1} {-5} }
                  \tl_put_right:Nn \l_phone_ausgabetext_tl {\,}
                  \str_put_right:Nx \l_phone_ausgabetext_tl { \str_range:nnn {#2} {-4} {-1} }
               }
               {
                  \str_put_right:Nn \l_phone_ausgabetext_tl {#2}
               }
         }
         {
            \str_put_right:Nn \l_phone_ausgabetext_tl {#2}
         }
   }

\cs_generate_variant:Nn \phone_UK_teilnehmerrufnummer_schreiben:Nn {Nx,NV}


\cs_new_protected:Npn \phone_UK_nummer_schreiben:
   {
      \int_set:Nn \l_phone_nummerlaenge_int { \str_count:N \l_phone_bereinigte_nummer_str }

      \str_if_eq:xnTF { \str_head:N \l_phone_bereinigte_nummer_str } {0}
         {
            \bool_set_false:N \l_phone_vorwahl_gefunden_bool

            \int_step_inline:nnnn {6} {-1} {3}
               {
                  \bool_if:NF \l_phone_vorwahl_gefunden_bool
                     {
                        \int_compare:nT { \l_phone_nummerlaenge_int >= ##1 }
                           {
                              \str_set:Nx \l_phone_vorwahl_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {##1} }

                              \clist_if_in:NVT \c_phone_UK_vorwahlen_clist \l_phone_vorwahl_str
                                 {
                                    \bool_set_true:N \l_phone_vorwahl_gefunden_bool

                                    \phone_UK_vorwahl_schreiben:Vx \l_phone_vorwahl_str { \int_compare_p:nNn {##1} < {\l_phone_nummerlaenge_int} }

                                    \int_compare:nNnTF {##1} = {\l_phone_nummerlaenge_int}
                                       {
                                          \msg_warning:nn {phonenumbers} {missing subscriber number}
                                       }
                                       {
                                          \phone_UK_teilnehmerrufnummer_schreiben:Nx \l_phone_vorwahl_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {##1 + 1} {-1} }
                                       }
                                 }
                           }
                     }
               }

            \bool_if:NF \l_phone_vorwahl_gefunden_bool
               {
                  \msg_warning:nn {phonenumbers} {invalid area code}
                  \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
               }
         }
         {
            \phone_UK_teilnehmerrufnummer_schreiben:NV \c_empty_tl \l_phone_bereinigte_nummer_str
         }
   }


%%%%%%%%%%%%%%%%%%%% NORDAMERIKA %%%%%%%%%%%%%%%%%%%%

\file_input:n {phn-US_Vorwahlen}
\file_input:n {phn-US_Ortsnamen}

\clist_new:N \c_phone_US_vorwahlen_clist
\clist_concat:NNN \c_phone_US_vorwahlen_clist \c_phone_US_ortsvorwahlen_clist \c_phone_US_sondervorwahlen_clist

\msg_new:nnn {phonenumbers} {US/illegal home area code}
   {
      10-digit~dialling~is~required~in~\tl_use:c {c_phone_US_ortsname_#1_tl}.~#1~cannot~be~set~as~home~area~code~\msg_line_context:.
   }

\msg_new:nnn {phonenumbers} {US/invalid area code}
   {
      unknown~area~code~#1~in~North~American~phone~number~\msg_line_context:
   }

\msg_new:nnn {phonenumbers} {US/invalid central office code}
   {
      invalid~central~office~code~#1~in~North~American~phone~number~\msg_line_context:
   }

\bool_new:N \l_phone_US_ferngespraechspraefix_bool

\keys_define:nn {phonenumbers}
   {
      trunk-prefix .choices:nn = {on,off}
         {
            \str_if_eq:VnTF \l_keys_choice_tl {on}
               {
                  \bool_set_true:N \l_phone_US_ferngespraechspraefix_bool
               }
               {
                  \bool_set_false:N \l_phone_US_ferngespraechspraefix_bool
               }
         },
      trunk-prefix .initial:n = off,
      trunk-prefix .default:n = on
   }


% #1: Vorwahl, #2: Folgt eine Rufnummer?
\cs_new_protected:Npn \phone_US_vorwahl_schreiben:nN #1 #2
   {
      \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_phone_auslandsvorwahltyp_str {off} } { \str_if_eq_p:Vn \l_phone_heimatland_str {US} }
         {
            \bool_lazy_and:nnF { \str_if_eq_p:Vn \l_phone_heimatland_str {US} } { \str_if_eq_p:Vn \l_phone_heimatvorwahl_str {#1} }
               {
                  \bool_if:NTF \l_phone_US_ferngespraechspraefix_bool
                     {
                        \tl_put_right:Nx \l_phone_ausgabetext_tl
                           {
                              \str_if_eq:VnT \l_phone_vorwahldarstellung_str {place-and-number}
                                 {
                                    \tl_if_exist:cT {c_phone_US_ortsname_#1_tl}
                                       {
                                          \tl_use:c {c_phone_US_ortsname_#1_tl}
                                          \c_space_tl
                                       }
                                 }

                              \bool_if:NTF #2
                                 {
                                    \str_case:VnF \l_phone_vorwahltrennung_str
                                       {
                                          {brackets} {1 \c_space_tl (#1) \c_space_tl}
                                          {space} {1 \c_space_tl #1 \c_space_tl}
                                       }
                                       {
                                          1 \c_phone_bindestrich_tl #1 \c_phone_bindestrich_tl
                                       }
                                 }
                                 {
                                    \str_case:VnF \l_phone_vorwahltrennung_str
                                       {
                                          {brackets} {1 \c_space_tl (#1)}
                                          {space} {1 \c_space_tl #1}
                                       }
                                       {
                                          1 \c_phone_bindestrich_tl #1
                                       }
                                 }
                           }
                     }
                     {
                        \str_if_eq:VnT \l_phone_vorwahldarstellung_str {place}
                           {
                              \clist_if_in:NnT \c_phone_US_sondervorwahlen_clist {#1}
                                 {
                                    \str_set:Nn \l_phone_vorwahldarstellung_str {number}
                                 }
                           }

                        \tl_put_right:Nx \l_phone_ausgabetext_tl
                           {
                              \str_case:Vn \l_phone_vorwahldarstellung_str
                                 {
                                    {number}
                                       {
                                          \bool_if:NTF #2
                                             {
                                                \str_case:VnF \l_phone_vorwahltrennung_str
                                                   {
                                                      {brackets} {(#1) \c_space_tl}
                                                      {space} {#1 \c_space_tl}
                                                   }
                                                   {
                                                      #1 \c_phone_bindestrich_tl
                                                   }
                                             }
                                             {
                                                #1
                                             }
                                       }
                                    {place}
                                       {
                                          \bool_if:NTF #2
                                             {
                                                \str_case:VnF \l_phone_vorwahltrennung_str
                                                   {
                                                      {brackets}
                                                         {
                                                            (
                                                            \tl_if_exist:cTF {c_phone_US_ortsname_#1_tl}
                                                               {
                                                                  \tl_use:c {c_phone_US_ortsname_#1_tl}
                                                               }
                                                               {
                                                                  #1
                                                               }
                                                            )
                                                            \c_space_tl
                                                         }
                                                   }
                                                   {
                                                      \tl_if_exist:cTF {c_phone_US_ortsname_#1_tl}
                                                         {
                                                            \tl_use:c {c_phone_US_ortsname_#1_tl}
                                                            \c_space_tl
                                                         }
                                                         {
                                                            #1 \c_phone_bindestrich_tl
                                                         }
                                                   }
                                             }
                                             {
                                                \tl_if_exist:cTF {c_phone_US_ortsname_#1_tl}
                                                   {
                                                      \tl_use:c {c_phone_US_ortsname_#1_tl}
                                                   }
                                                   {
                                                      #1
                                                   }
                                             }
                                       }
                                    {place-and-number}
                                       {
                                          \tl_if_exist:cT {c_phone_US_ortsname_#1_tl}
                                             {
                                                \tl_use:c {c_phone_US_ortsname_#1_tl}
                                                \c_space_tl
                                             }

                                          \bool_if:NTF #2
                                             {
                                                \str_case:VnF \l_phone_vorwahltrennung_str
                                                   {
                                                      {brackets} {(#1) \c_space_tl}
                                                      {space} {#1 \c_space_tl}
                                                   }
                                                   {
                                                      #1 \c_phone_bindestrich_tl
                                                   }
                                             }
                                             {
                                                \str_if_eq:VnTF \l_phone_vorwahltrennung_str {brackets}
                                                   {
                                                      (#1)
                                                   }
                                                   {
                                                      #1
                                                   }
                                             }
                                       }
                                 }
                           }
                     }
               }
         }
         {
            \phone_auslandsvorwahl_schreiben:n {1}

            \tl_put_right:Nn \l_phone_ausgabetext_tl {\c_space_tl}

            \str_if_eq:VnTF \l_phone_auslandsvorwahltrennung_str {brackets}
               {
                  \tl_put_right:Nn \l_phone_ausgabetext_tl {(#1)}
               }
               {
                  \tl_put_right:Nn \l_phone_ausgabetext_tl {#1}
               }

            \bool_if:NT #2
               {
                  \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
               }
         }

      % Linktext schreiben, falls eine Rufnummer folgt
      \bool_if:NT #2
         {
            \str_put_right:Nn \l_phone_linktext_str {+1 #1}
         }
   }

\cs_generate_variant:Nn \phone_US_vorwahl_schreiben:nN {VN}


% #1: Ortsvorwahl, #2: Vermittlungsstellennummer
\cs_new_protected:Npn \phone_US_vermittlungsstellennummer_schreiben:nn #1 #2
   {
      \str_case:xnTF { \str_head:n {#2} }
         {
            {0} { }
            {1} { }
         }
         {
            \msg_warning:nnn {phonenumbers} {US/invalid central office code} {#2}
         }
         {
            \bool_set_false:N \l_tmpa_bool % Regionalnummer?

            \tl_if_empty:nTF {#1}
               {
                  \bool_set_true:N \l_tmpa_bool
               }
               {
                  \clist_if_in:NnT \c_phone_US_ortsvorwahlen_clist {#1}
                     {
                        \bool_set_true:N \l_tmpa_bool
                     }
               }

            \bool_if:NTF \l_tmpa_bool
               {
                  \str_if_eq:xnT { \str_range:nnn {#2} {2} {3} } {11}
                     {
                        \msg_warning:nnn {phonenumbers} {US/invalid central office code} {#2}
                     }
               }
               {
                  \str_if_eq:nnT {#2} {911}
                     {
                        \msg_warning:nnn {phonenumbers} {US/invalid central office code} {#2}
                     }
               }
         }

      \tl_put_right:Nn \l_phone_ausgabetext_tl {#2}

      \bool_lazy_or:nnTF { \str_if_eq_p:Vn \l_phone_auslandsvorwahltyp_str {off} } { \str_if_eq_p:Vn \l_phone_heimatland_str {US} }
         {
            \tl_put_right:NV \l_phone_ausgabetext_tl \c_phone_bindestrich_tl
         }
         {
            \tl_if_empty:nTF {#1}
               {
                  \tl_put_right:NV \l_phone_ausgabetext_tl \c_phone_bindestrich_tl
               }
               {
                  \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
               }
         }

      % Linktext schreiben, falls eine Vorwahl vorangeht
      \tl_if_empty:nF {#1}
         {
            \str_put_right:Nn \l_phone_linktext_str {#2}
         }
   }

\cs_generate_variant:Nn \phone_US_vermittlungsstellennummer_schreiben:nn {Vx}


\cs_new_protected:Npn \phone_US_nummer_schreiben:
   {
      \int_case:nnF { \str_count:N \l_phone_bereinigte_nummer_str }
         {
            {3}
               {
                  \clist_if_in:NVTF \c_phone_US_vorwahlen_clist \l_phone_bereinigte_nummer_str
                     {
                        \msg_warning:nn {phonenumbers} {missing subscriber number}
                     }
                     {
                        \msg_warning:nnV {phonenumbers} {US/invalid area code} \l_phone_bereinigte_nummer_str
                     }

                  \phone_US_vorwahl_schreiben:VN \l_phone_bereinigte_nummer_str \c_false_bool
               }
            {7}
               {
                  \phone_US_vermittlungsstellennummer_schreiben:Vx \c_empty_tl { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {3} }

                  \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_range:Nnn \l_phone_bereinigte_nummer_str {4} {7} }
               }
            {10}
               {
                  \str_set:Nx \l_tmpa_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {3} }

                  \clist_if_in:NVF \c_phone_US_vorwahlen_clist \l_tmpa_str
                     {
                        \msg_warning:nnx {phonenumbers} {US/invalid area code} {\l_tmpa_str}
                     }

                  \phone_US_vorwahl_schreiben:VN \l_tmpa_str \c_true_bool

                  \phone_US_vermittlungsstellennummer_schreiben:Vx \l_tmpa_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {4} {6} }

                  \tl_put_right:Nx \l_phone_ausgabetext_tl { \str_range:Nnn \l_phone_bereinigte_nummer_str {7} {10} }
                  \str_put_right:Nx \l_phone_linktext_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {7} {10} }
               }
         }
         {
            \int_compare:nNnTF { \str_count:N \l_phone_bereinigte_nummer_str } < {10}
               {
                  \msg_warning:nnnn {phonenumbers} {number too short} {phone} {10}
               }
               {
                  \msg_warning:nnnn {phonenumbers} {number too long} {phone} {10}
               }

            \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
         }
   }


%%%%%%%%%%%%%%%%%%%% SONSTIGE LÄNDER %%%%%%%%%%%%%%%%%%%%

\cs_new_protected:Npn \phone_SONST_nummer_schreiben:
   {
      \int_set:Nn \l_phone_nummerlaenge_int { \str_count:N \l_phone_bereinigte_nummer_str }

      \bool_set_false:N \l_phone_vorwahl_gefunden_bool

      \int_step_inline:nnnn {3} {-1} {1}
         {
            \bool_if:NF \l_phone_vorwahl_gefunden_bool
               {
                  \int_compare:nT { \l_phone_nummerlaenge_int >= ##1 }
                     {
                        \str_set:Nx \l_tmpa_str { \str_range:Nnn \l_phone_bereinigte_nummer_str {1} {##1} }

                        \clist_if_in:NVT \c_phone_landeskennzahlen_clist \l_tmpa_str
                           {
                              \bool_set_true:N \l_phone_vorwahl_gefunden_bool

                              \phone_auslandsvorwahl_schreiben:V \l_tmpa_str

                              \int_compare:nNnTF {##1} = {\l_phone_nummerlaenge_int}
                                 {
                                    \msg_warning:nn {phonenumbers} {country code only}
                                 }
                                 {
                                    \tl_put_right:NV \l_phone_ausgabetext_tl \c_space_tl
                                    \phone_von_hinten_gruppiert_schreiben:x { \str_range:Nnn \l_phone_bereinigte_nummer_str {##1 + 1} {-1} }

                                    \str_put_right:Nn \l_phone_linktext_str {+}
                                    \str_put_right:NV \l_phone_linktext_str \l_phone_bereinigte_nummer_str
                                 }
                           }
                     }
               }
         }

      \bool_if:NF \l_phone_vorwahl_gefunden_bool
         {
            \msg_warning:nnn {phonenumbers} {invalid country code}
            \tl_put_right:NV \l_phone_ausgabetext_tl \c_phone_pluszeichen_tl
            \tl_put_right:NV \l_phone_ausgabetext_tl \l_phone_bereinigte_nummer_str
         }
   }


\ProcessKeysPackageOptions {phonenumbers}
