#!/usr/bin/env php
<?php

/*
 * Generated by Humbug Box 4.6.1@048e634.
 *
 * @link https://github.com/humbug/box
 */

Phar::mapPhar('box-auto-generated-alias-f58d5a798fbc.phar');

$_SERVER['SCRIPT_FILENAME'] = 'phar://box-auto-generated-alias-f58d5a798fbc.phar/bin/laravel';
require 'phar://box-auto-generated-alias-f58d5a798fbc.phar/bin/laravel';

__HALT_COMPILER(); ?>
[                  src/NewCommand.php        {N      )   src/Concerns/InteractsWithHerdOrValet.php        G-      "   src/Concerns/ConfiguresPrompts.php                  src/Enums/NodePackageManager.php        $h`=         src/Agent.php        O         bin/laravel        ǥ      T   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeImmutableType.php        pBl      R   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonTypeConverter.php        2      Q   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonDoctrineType.php        E      W   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeDefaultPrecision.php7      7  Pa      I   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonType.php          +&      K   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeType.php+      +  ש      R   vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonImmutableType.php          "ɤ      .   vendor/carbonphp/carbon-doctrine-types/LICENSE'      '  t.      >   vendor/beyondcode/herd-configuration/src/HerdConfiguration.php        ߵb         vendor/composer/ClassLoader.php?      ?  2@u      %   vendor/composer/autoload_classmap.php      L      !   vendor/composer/autoload_psr4.php
      
  ?Dr      %   vendor/composer/InstalledVersions.phpC      C  <nw      '   vendor/composer/autoload_namespaces.php          /t         vendor/composer/LICENSE.      .         "   vendor/composer/autoload_files.php        Hs6s      "   vendor/composer/platform_check.php        !K      !   vendor/composer/autoload_real.php        <s      #   vendor/composer/autoload_static.php      gCG         vendor/composer/installed.php_      _  x W      0   vendor/laravel/agent-detector/src/KnownAgent.php        ;|Ĥ      /   vendor/laravel/agent-detector/src/functions.php          -      3   vendor/laravel/agent-detector/src/AgentDetector.php	      	  "1P      1   vendor/laravel/agent-detector/src/AgentResult.phpZ      Z  a      ,   vendor/laravel/prompts/src/SuggestPrompt.php.      .  V      0   vendor/laravel/prompts/src/MultiSelectPrompt.php_      _  Q{      *   vendor/laravel/prompts/src/FormBuilder.php?&      ?&  `      +   vendor/laravel/prompts/src/NumberPrompt.php        ߪ      $   vendor/laravel/prompts/src/Clear.phpZ      Z  ̟(      -   vendor/laravel/prompts/src/PasswordPrompt.php        s      '   vendor/laravel/prompts/src/Progress.phph      h  a}8      B   vendor/laravel/prompts/src/Themes/Default/NumberPromptRenderer.phpA      A  F      ;   vendor/laravel/prompts/src/Themes/Default/TableRenderer.php2      2  -@      <   vendor/laravel/prompts/src/Themes/Default/StreamRenderer.phpX      X  >6e      @   vendor/laravel/prompts/src/Themes/Default/TextPromptRenderer.php        ~Qk      :   vendor/laravel/prompts/src/Themes/Default/TaskRenderer.php7
      7
  w_A      =   vendor/laravel/prompts/src/Themes/Default/SpinnerRenderer.phpC      C  5\      C   vendor/laravel/prompts/src/Themes/Default/ConfirmPromptRenderer.phpz	      z	  3ؤ      ;   vendor/laravel/prompts/src/Themes/Default/ClearRenderer.php          5      6   vendor/laravel/prompts/src/Themes/Default/Renderer.phpe      e  W      C   vendor/laravel/prompts/src/Themes/Default/SuggestPromptRenderer.php        7&?      H   vendor/laravel/prompts/src/Themes/Default/AutoCompletePromptRenderer.php        (դ      D   vendor/laravel/prompts/src/Themes/Default/TextareaPromptRenderer.php
      
  GA      G   vendor/laravel/prompts/src/Themes/Default/MultiSearchPromptRenderer.php        gL      :   vendor/laravel/prompts/src/Themes/Default/NoteRenderer.phpk      k  :      B   vendor/laravel/prompts/src/Themes/Default/SearchPromptRenderer.php        AQ!B      >   vendor/laravel/prompts/src/Themes/Default/ProgressRenderer.php              A   vendor/laravel/prompts/src/Themes/Default/PausePromptRenderer.php
      
  wMm      :   vendor/laravel/prompts/src/Themes/Default/GridRenderer.php
      
  rYQ      B   vendor/laravel/prompts/src/Themes/Default/SelectPromptRenderer.php        洤      A   vendor/laravel/prompts/src/Themes/Default/Concerns/DrawsBoxes.php        \      K   vendor/laravel/prompts/src/Themes/Default/Concerns/InteractsWithStrings.phpX      X  ȿ      F   vendor/laravel/prompts/src/Themes/Default/Concerns/DrawsScrollbars.php        '      G   vendor/laravel/prompts/src/Themes/Default/MultiSelectPromptRenderer.php        +ܣ      D   vendor/laravel/prompts/src/Themes/Default/PasswordPromptRenderer.php        V      ;   vendor/laravel/prompts/src/Themes/Default/TitleRenderer.php        n|      ?   vendor/laravel/prompts/src/Themes/Default/DataTableRenderer.phpF      F  )2      9   vendor/laravel/prompts/src/Themes/Contracts/Scrolling.php                -   vendor/laravel/prompts/src/TextareaPrompt.php)      )  +O      #   vendor/laravel/prompts/src/Grid.php        C6      %   vendor/laravel/prompts/src/Prompt.php{+      {+  Oo      0   vendor/laravel/prompts/src/MultiSearchPrompt.php        +3      $   vendor/laravel/prompts/src/Title.php=      =        '   vendor/laravel/prompts/src/Terminal.php        !       *   vendor/laravel/prompts/src/PausePrompt.php8      8  I      '   vendor/laravel/prompts/src/FormStep.phpV      V  ̈́W      -   vendor/laravel/prompts/src/Support/Result.php        מ      ,   vendor/laravel/prompts/src/Support/Utils.php        ֩      -   vendor/laravel/prompts/src/Support/Logger.php	      	  p      %   vendor/laravel/prompts/src/Stream.php              +   vendor/laravel/prompts/src/NotifyPrompt.php        \r/      ;   vendor/laravel/prompts/src/Output/BufferedConsoleOutput.php        i+ᩤ      3   vendor/laravel/prompts/src/Output/ConsoleOutput.php        [      +   vendor/laravel/prompts/src/SearchPrompt.php
      
  ͢      +   vendor/laravel/prompts/src/SelectPrompt.php        \Aݎ      1   vendor/laravel/prompts/src/AutoCompletePrompt.php        h(      )   vendor/laravel/prompts/src/TextPrompt.phpu      u  gҒ      .   vendor/laravel/prompts/src/DataTablePrompt.php        jq      "   vendor/laravel/prompts/src/Key.php;      ;  ٛx      &   vendor/laravel/prompts/src/helpers.php1      1  )ä      ?   vendor/laravel/prompts/src/Exceptions/FormRevertedException.php          _O      K   vendor/laravel/prompts/src/Exceptions/NonInteractiveValidationException.php          COx5      &   vendor/laravel/prompts/src/Spinner.php        e?;      2   vendor/laravel/prompts/src/Concerns/HasSpinner.php^      ^  7U      5   vendor/laravel/prompts/src/Concerns/Interactivity.php              .   vendor/laravel/prompts/src/Concerns/Cursor.php"      "  ;cN      0   vendor/laravel/prompts/src/Concerns/Termwind.php        ^VN      -   vendor/laravel/prompts/src/Concerns/Erase.phpc      c  eM      /   vendor/laravel/prompts/src/Concerns/HasInfo.phpJ      J  *V      8   vendor/laravel/prompts/src/Concerns/FakesInputOutput.phpp      p  ɢ      .   vendor/laravel/prompts/src/Concerns/Events.php        Q_      .   vendor/laravel/prompts/src/Concerns/Themes.php{      {  ws[      2   vendor/laravel/prompts/src/Concerns/TypedValue.php        Ѥ      .   vendor/laravel/prompts/src/Concerns/Colors.php        L䠤      2   vendor/laravel/prompts/src/Concerns/Truncation.php        3>      0   vendor/laravel/prompts/src/Concerns/Fallback.php        CM      1   vendor/laravel/prompts/src/Concerns/Scrolling.php        ]      #   vendor/laravel/prompts/src/Note.php        9S      #   vendor/laravel/prompts/src/Task.php7(      7(  $U      $   vendor/laravel/prompts/src/Table.phpQ      Q  ߦ      ,   vendor/laravel/prompts/src/ConfirmPrompt.phpr      r  >         vendor/autoload.php        I}      .   vendor/psr/simple-cache/src/CacheException.php          ٭q      .   vendor/psr/simple-cache/src/CacheInterface.php        {)      8   vendor/psr/simple-cache/src/InvalidArgumentException.php        3      7   vendor/psr/container/src/NotFoundExceptionInterface.php          >悤      /   vendor/psr/container/src/ContainerInterface.php              8   vendor/psr/container/src/ContainerExceptionInterface.php          ^33         vendor/psr/container/LICENSEy      y  Op      '   vendor/psr/clock/src/ClockInterface.php          maW         vendor/psr/clock/LICENSE8      8  l      V   vendor/nesbot/carbon/lazy/Carbon/MessageFormatter/MessageFormatterMapperStrongType.php          4      T   vendor/nesbot/carbon/lazy/Carbon/MessageFormatter/MessageFormatterMapperWeakType.phpr      r  s\      :   vendor/nesbot/carbon/lazy/Carbon/UnprotectedDatePeriod.phpz      z  H       8   vendor/nesbot/carbon/lazy/Carbon/ProtectedDatePeriod.phpy      y  ԡe      9   vendor/nesbot/carbon/lazy/Carbon/TranslatorStrongType.php        K      7   vendor/nesbot/carbon/lazy/Carbon/TranslatorWeakType.php-      -  8Q      +   vendor/nesbot/carbon/src/Carbon/Factory.php0      0  }      3   vendor/nesbot/carbon/src/Carbon/CarbonImmutable.phpv     v 2x      0   vendor/nesbot/carbon/src/Carbon/WrapperClock.phpZ      Z  ioԳ      K   vendor/nesbot/carbon/src/Carbon/MessageFormatter/MessageFormatterMapper.php/      /  [8      2   vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php%      %  oe      0   vendor/nesbot/carbon/src/Carbon/CarbonPeriod.phpge     ge 0      2   vendor/nesbot/carbon/src/Carbon/CarbonInterval.phpH     H ߿      /   vendor/nesbot/carbon/src/Carbon/Cli/Invoker.php        Q      ;   vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.phpp      p        .   vendor/nesbot/carbon/src/Carbon/Translator.phpA      A  O?o      4   vendor/nesbot/carbon/src/Carbon/FactoryImmutable.phpb      b  ϵa      2   vendor/nesbot/carbon/src/Carbon/List/languages.phps      s  9      0   vendor/nesbot/carbon/src/Carbon/List/regions.php          y4Z      7   vendor/nesbot/carbon/src/Carbon/Constants/UnitValue.php        |      9   vendor/nesbot/carbon/src/Carbon/Constants/DiffOptions.php        S      4   vendor/nesbot/carbon/src/Carbon/Constants/Format.phpP      P  #6i      @   vendor/nesbot/carbon/src/Carbon/Constants/TranslationOptions.php        7r?Ԥ      +   vendor/nesbot/carbon/src/Carbon/WeekDay.phpe      e  ~      )   vendor/nesbot/carbon/src/Carbon/Month.php	      	  {v      (   vendor/nesbot/carbon/src/Carbon/Unit.phpI      I  r;      <   vendor/nesbot/carbon/src/Carbon/CarbonConverterInterface.php        h      ?   vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php        J2[      5   vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php`      `  ?      =   vendor/nesbot/carbon/src/Carbon/Traits/StaticLocalization.phpS	      S	  f      5   vendor/nesbot/carbon/src/Carbon/Traits/Mutability.php        Rm2      /   vendor/nesbot/carbon/src/Carbon/Traits/Cast.php        ,l      8   vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php        &˖      ;   vendor/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php        ֤      /   vendor/nesbot/carbon/src/Carbon/Traits/Test.php        zu3      4   vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php        8?(      9   vendor/nesbot/carbon/src/Carbon/Traits/ToStringFormat.php              0   vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php        Pj      3   vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php              /   vendor/nesbot/carbon/src/Carbon/Traits/Week.php.      .  Ǥ      5   vendor/nesbot/carbon/src/Carbon/Traits/Difference.php        F      /   vendor/nesbot/carbon/src/Carbon/Traits/Date.php            2   vendor/nesbot/carbon/src/Carbon/Traits/Creator.php|      |  Ay      0   vendor/nesbot/carbon/src/Carbon/Traits/Units.php?9      ?9  ]      7   vendor/nesbot/carbon/src/Carbon/Traits/LocalFactory.phpZ      Z  I      0   vendor/nesbot/carbon/src/Carbon/Traits/Macro.php
      
  <      E   vendor/nesbot/carbon/src/Carbon/Traits/DeprecatedPeriodProperties.php        Xr      8   vendor/nesbot/carbon/src/Carbon/Traits/StaticOptions.php        }F      9   vendor/nesbot/carbon/src/Carbon/Traits/MagicParameter.php        Ƥ      5   vendor/nesbot/carbon/src/Carbon/Traits/Boundaries.php0      0  ν      4   vendor/nesbot/carbon/src/Carbon/Traits/Converter.php}8      }8  Xݤ      7   vendor/nesbot/carbon/src/Carbon/Traits/Localization.php/h      /h  1 _      7   vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.phpq	      q	  !      4   vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php[6      [6  Ĥ      2   vendor/nesbot/carbon/src/Carbon/Traits/Options.php        P1%      A   vendor/nesbot/carbon/src/Carbon/TranslatorStrongTypeInterface.phpA      A  F      ,   vendor/nesbot/carbon/src/Carbon/Language.php        ͒      *   vendor/nesbot/carbon/src/Carbon/Carbon.phpr     r sI      7   vendor/nesbot/carbon/src/Carbon/TranslatorImmutable.phpe	      e	  Іqդ      ,   vendor/nesbot/carbon/src/Carbon/Callback.php/      /  _      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_SC.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/da.php
      
  + e      .   vendor/nesbot/carbon/src/Carbon/Lang/sw_KE.php        ?щ      ,   vendor/nesbot/carbon/src/Carbon/Lang/hne.phpO      O  ~@      +   vendor/nesbot/carbon/src/Carbon/Lang/ug.php        lk      ,   vendor/nesbot/carbon/src/Carbon/Lang/nso.phpO      O  -GY      .   vendor/nesbot/carbon/src/Carbon/Lang/en_UM.phpG      G        +   vendor/nesbot/carbon/src/Carbon/Lang/no.phpn      n  KN      .   vendor/nesbot/carbon/src/Carbon/Lang/ms_BN.php#      #  W;      ,   vendor/nesbot/carbon/src/Carbon/Lang/mjw.phpO      O  z      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MU.php        ''x      0   vendor/nesbot/carbon/src/Carbon/Lang/pa_Arab.php        ƪ      ,   vendor/nesbot/carbon/src/Carbon/Lang/sah.phpO      O  zC      .   vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php        p      ,   vendor/nesbot/carbon/src/Carbon/Lang/shi.php	      	  猪N      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php~      ~  q      +   vendor/nesbot/carbon/src/Carbon/Lang/hu.php        DC      0   vendor/nesbot/carbon/src/Carbon/Lang/az_Arab.php4      4  M      +   vendor/nesbot/carbon/src/Carbon/Lang/eo.phpj
      j
  UZ      ,   vendor/nesbot/carbon/src/Carbon/Lang/the.phpO      O  o֤      /   vendor/nesbot/carbon/src/Carbon/Lang/mni_IN.php        mj      ,   vendor/nesbot/carbon/src/Carbon/Lang/teo.php\      \  +      ,   vendor/nesbot/carbon/src/Carbon/Lang/nnh.php              .   vendor/nesbot/carbon/src/Carbon/Lang/aa_ER.php$      $  ߟ      .   vendor/nesbot/carbon/src/Carbon/Lang/km_KH.php        ,      .   vendor/nesbot/carbon/src/Carbon/Lang/es_HN.php        d      +   vendor/nesbot/carbon/src/Carbon/Lang/ia.phpN      N  4      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MP.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/mk.php        6      3   vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php        w^      ,   vendor/nesbot/carbon/src/Carbon/Lang/asa.phpA      A  M2      .   vendor/nesbot/carbon/src/Carbon/Lang/en_VU.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/fy_NL.php        D1e      ,   vendor/nesbot/carbon/src/Carbon/Lang/ksf.php        ڼͤ      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CA.php        6      .   vendor/nesbot/carbon/src/Carbon/Lang/lo_LA.php        CL
      0   vendor/nesbot/carbon/src/Carbon/Lang/pa_Guru.php              .   vendor/nesbot/carbon/src/Carbon/Lang/en_ER.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SE.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/es_US.phpk      k  (RH      +   vendor/nesbot/carbon/src/Carbon/Lang/kn.php        %      ,   vendor/nesbot/carbon/src/Carbon/Lang/tlh.php	      	  Zk      .   vendor/nesbot/carbon/src/Carbon/Lang/en_TO.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/fy.phpU
      U
  	      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SD.php`      `  k      +   vendor/nesbot/carbon/src/Carbon/Lang/ca.php        |[3      +   vendor/nesbot/carbon/src/Carbon/Lang/oc.php        fpؤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_VG.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/es_UY.php        4ͤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SX.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/ur_IN.php}      }  qh      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MY.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/de.phpk      k  QDR      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_MZ.phpG      G  C~s      .   vendor/nesbot/carbon/src/Carbon/Lang/es_SV.php        [ɤ      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_EG.php        , ۤ      +   vendor/nesbot/carbon/src/Carbon/Lang/uz.php        ':      /   vendor/nesbot/carbon/src/Carbon/Lang/fur_IT.php        y      +   vendor/nesbot/carbon/src/Carbon/Lang/ro.php        ,͹      .   vendor/nesbot/carbon/src/Carbon/Lang/es_DO.php        Yb1      0   vendor/nesbot/carbon/src/Carbon/Lang/az_Latn.phpL      L  а      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MR.php
      
  wȤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_DK.php        s:m      /   vendor/nesbot/carbon/src/Carbon/Lang/gsw_FR.phpl      l  $ r      ,   vendor/nesbot/carbon/src/Carbon/Lang/kea.php        hu      3   vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.phpN      N  r      .   vendor/nesbot/carbon/src/Carbon/Lang/de_IT.phpZ      Z  b3      +   vendor/nesbot/carbon/src/Carbon/Lang/ha.php        b      .   vendor/nesbot/carbon/src/Carbon/Lang/fo_FO.php        b      +   vendor/nesbot/carbon/src/Carbon/Lang/cv.php
      
  X0~      +   vendor/nesbot/carbon/src/Carbon/Lang/te.php        	P      ,   vendor/nesbot/carbon/src/Carbon/Lang/yue.phpO      O  lIQ      ,   vendor/nesbot/carbon/src/Carbon/Lang/miq.phpO      O  {      +   vendor/nesbot/carbon/src/Carbon/Lang/dz.phpN      N  nd      +   vendor/nesbot/carbon/src/Carbon/Lang/ur.php?
      ?
  y      .   vendor/nesbot/carbon/src/Carbon/Lang/ro_MD.php	      	  Z      ,   vendor/nesbot/carbon/src/Carbon/Lang/vai.php          {r	      /   vendor/nesbot/carbon/src/Carbon/Lang/yuw_PG.php        }S      .   vendor/nesbot/carbon/src/Carbon/Lang/en_PG.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/nl_BQ.php        &5      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_GQ.php        [ia      .   vendor/nesbot/carbon/src/Carbon/Lang/es_PY.php        d      +   vendor/nesbot/carbon/src/Carbon/Lang/ms.php        7ݤ      +   vendor/nesbot/carbon/src/Carbon/Lang/aa.phpN      N  җ1k      .   vendor/nesbot/carbon/src/Carbon/Lang/ta_MY.php        *v      +   vendor/nesbot/carbon/src/Carbon/Lang/ml.php&      &  7N      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CF.php        ''x      /   vendor/nesbot/carbon/src/Carbon/Lang/en_001.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/rm.php        	       ,   vendor/nesbot/carbon/src/Carbon/Lang/mhr.phpO      O  vR`      +   vendor/nesbot/carbon/src/Carbon/Lang/gl.phpm      m  9u      +   vendor/nesbot/carbon/src/Carbon/Lang/si.php]      ]  \M      +   vendor/nesbot/carbon/src/Carbon/Lang/mr.php        M^3      +   vendor/nesbot/carbon/src/Carbon/Lang/in.php        Zб      .   vendor/nesbot/carbon/src/Carbon/Lang/be_BY.php)      )  Ť      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MC.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MA.php`      `  A      .   vendor/nesbot/carbon/src/Carbon/Lang/en_KI.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/en_BW.phpG      G        3   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_TW.php        ʷ      +   vendor/nesbot/carbon/src/Carbon/Lang/gd.php
      
        .   vendor/nesbot/carbon/src/Carbon/Lang/da_GL.php              /   vendor/nesbot/carbon/src/Carbon/Lang/pap_AW.phpk      k  6Ĥ      ,   vendor/nesbot/carbon/src/Carbon/Lang/dsb.phpO      O  ڗ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_PH.php              +   vendor/nesbot/carbon/src/Carbon/Lang/om.php        婤      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CM.phpM      M  a$      +   vendor/nesbot/carbon/src/Carbon/Lang/bm.php	      	  Ǥ      .   vendor/nesbot/carbon/src/Carbon/Lang/hr_BA.php        oR      .   vendor/nesbot/carbon/src/Carbon/Lang/it_SM.php        q
a      5   vendor/nesbot/carbon/src/Carbon/Lang/nan_TW@latin.php              .   vendor/nesbot/carbon/src/Carbon/Lang/li_NL.php        5Ϥ      ,   vendor/nesbot/carbon/src/Carbon/Lang/gsw.php        5ƭ      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_ST.php        [ia      .   vendor/nesbot/carbon/src/Carbon/Lang/en_KY.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/vun.phpC      C  T.      ,   vendor/nesbot/carbon/src/Carbon/Lang/sgs.phpO      O  5      .   vendor/nesbot/carbon/src/Carbon/Lang/qu_BO.phpG      G  \      .   vendor/nesbot/carbon/src/Carbon/Lang/fi_FI.php        Z
Y      .   vendor/nesbot/carbon/src/Carbon/Lang/os_RU.php        F      +   vendor/nesbot/carbon/src/Carbon/Lang/vo.php\      \  j      .   vendor/nesbot/carbon/src/Carbon/Lang/ca_IT.php)      )  }      ,   vendor/nesbot/carbon/src/Carbon/Lang/luo.php=      =  $      ,   vendor/nesbot/carbon/src/Carbon/Lang/cmn.phpO      O  O%ė      .   vendor/nesbot/carbon/src/Carbon/Lang/de_LU.php        "       .   vendor/nesbot/carbon/src/Carbon/Lang/en_MT.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/ar_QA.php        , ۤ      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_JO.php>      >  -!b      ,   vendor/nesbot/carbon/src/Carbon/Lang/tpi.phpO      O  {kĤ      +   vendor/nesbot/carbon/src/Carbon/Lang/to.phpN      N  -jI      +   vendor/nesbot/carbon/src/Carbon/Lang/nr.phpN      N  /      /   vendor/nesbot/carbon/src/Carbon/Lang/nds_DE.php        1      /   vendor/nesbot/carbon/src/Carbon/Lang/mas_TZ.phpH      H  ߜϤ      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_GP.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/mt_MT.php        }<      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MQ.php        ''x      ,   vendor/nesbot/carbon/src/Carbon/Lang/nyn.phpf      f  Ȍ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_NZ.php        Qؤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_KN.php        ?Ej      /   vendor/nesbot/carbon/src/Carbon/Lang/byn_ER.php=      =  U]      /   vendor/nesbot/carbon/src/Carbon/Lang/quz_PE.php        6ڤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GH.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/ia_FR.phpu      u  %֤      +   vendor/nesbot/carbon/src/Carbon/Lang/ee.phpj      j  !Hä      /   vendor/nesbot/carbon/src/Carbon/Lang/csb_PL.php        8      .   vendor/nesbot/carbon/src/Carbon/Lang/nb_NO.php              .   vendor/nesbot/carbon/src/Carbon/Lang/ln_AO.php        ^٤      .   vendor/nesbot/carbon/src/Carbon/Lang/en_JM.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/nb_SJ.php        2=P      /   vendor/nesbot/carbon/src/Carbon/Lang/gez_ET.php        i      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GB.php        s      ,   vendor/nesbot/carbon/src/Carbon/Lang/lij.phpO      O  BkФ      +   vendor/nesbot/carbon/src/Carbon/Lang/so.php
      
  f&      /   vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php        KLR      +   vendor/nesbot/carbon/src/Carbon/Lang/gv.phpN      N  
ĩ      4   vendor/nesbot/carbon/src/Carbon/Lang/be_BY@latin.php        FcK      ,   vendor/nesbot/carbon/src/Carbon/Lang/guz.php        G69      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_YE.php        +3      .   vendor/nesbot/carbon/src/Carbon/Lang/tn_ZA.phpA      A  nZ      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_GN.php        ''x      ,   vendor/nesbot/carbon/src/Carbon/Lang/mni.phpO      O  a      .   vendor/nesbot/carbon/src/Carbon/Lang/sq_XK.php               .   vendor/nesbot/carbon/src/Carbon/Lang/en_MO.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/tl_PH.phpS      S   S      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_SN.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/af.phps
      s
  TR      .   vendor/nesbot/carbon/src/Carbon/Lang/ps_AF.php        Bk      .   vendor/nesbot/carbon/src/Carbon/Lang/am_ET.php        ~H      +   vendor/nesbot/carbon/src/Carbon/Lang/lu.phpV      V  ܤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_IO.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_GW.php        [ia      +   vendor/nesbot/carbon/src/Carbon/Lang/nb.php        !~P      ,   vendor/nesbot/carbon/src/Carbon/Lang/pap.php9      9  	J      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SC.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_GF.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SH.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_ER.php)      )  Ϥ      ,   vendor/nesbot/carbon/src/Carbon/Lang/yav.php        |=}      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_BH.php        , ۤ      .   vendor/nesbot/carbon/src/Carbon/Lang/nl_SR.php        &5      ,   vendor/nesbot/carbon/src/Carbon/Lang/jmc.phpC      C  T.      +   vendor/nesbot/carbon/src/Carbon/Lang/ce.phpN      N  bM      .   vendor/nesbot/carbon/src/Carbon/Lang/es_PH.php9      9  n      .   vendor/nesbot/carbon/src/Carbon/Lang/es_EA.phpG      G  (|@z      +   vendor/nesbot/carbon/src/Carbon/Lang/bg.php        ?      .   vendor/nesbot/carbon/src/Carbon/Lang/es_ES.phpD      D  EV?      ,   vendor/nesbot/carbon/src/Carbon/Lang/shs.phpO      O  ]jw      ,   vendor/nesbot/carbon/src/Carbon/Lang/brx.phpO      O  L      .   vendor/nesbot/carbon/src/Carbon/Lang/hr_HR.php              .   vendor/nesbot/carbon/src/Carbon/Lang/et_EE.php        e>      .   vendor/nesbot/carbon/src/Carbon/Lang/ru_RU.php        C=5      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_MA.php        h      .   vendor/nesbot/carbon/src/Carbon/Lang/lv_LV.php        Ci      +   vendor/nesbot/carbon/src/Carbon/Lang/sn.php              9   vendor/nesbot/carbon/src/Carbon/Lang/ks_IN@devanagari.php         a      +   vendor/nesbot/carbon/src/Carbon/Lang/sk.phpb      b  jl      4   vendor/nesbot/carbon/src/Carbon/Lang/en_US_Posix.php        N      /   vendor/nesbot/carbon/src/Carbon/Lang/hsb_DE.phpK      K  
      +   vendor/nesbot/carbon/src/Carbon/Lang/lo.php        3UL      .   vendor/nesbot/carbon/src/Carbon/Lang/en_BS.phpG      G        +   vendor/nesbot/carbon/src/Carbon/Lang/ti.phpN      N  l      /   vendor/nesbot/carbon/src/Carbon/Lang/hif_FJ.php        <.      .   vendor/nesbot/carbon/src/Carbon/Lang/en_NA.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_TN.php#      #  9      .   vendor/nesbot/carbon/src/Carbon/Lang/it_IT.phpD      D  HӤ      +   vendor/nesbot/carbon/src/Carbon/Lang/cu.php        M      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_BI.php        ''x      ,   vendor/nesbot/carbon/src/Carbon/Lang/mas.php        j(      .   vendor/nesbot/carbon/src/Carbon/Lang/en_TV.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/ti_ET.php        Pפ      /   vendor/nesbot/carbon/src/Carbon/Lang/mag_IN.php        g      +   vendor/nesbot/carbon/src/Carbon/Lang/ff.php        /      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_LU.php        [ia      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_AE.php        NU&      +   vendor/nesbot/carbon/src/Carbon/Lang/iu.phpN      N  'J      .   vendor/nesbot/carbon/src/Carbon/Lang/ln_CG.php        ^٤      .   vendor/nesbot/carbon/src/Carbon/Lang/en_VC.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/es.php0      0  Τ      .   vendor/nesbot/carbon/src/Carbon/Lang/es_PR.php        -|K      +   vendor/nesbot/carbon/src/Carbon/Lang/zu.phpN      N  1      +   vendor/nesbot/carbon/src/Carbon/Lang/ht.phpN      N  <      .   vendor/nesbot/carbon/src/Carbon/Lang/en_AG.php        a#      .   vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ.php#      #  Q_L      .   vendor/nesbot/carbon/src/Carbon/Lang/cs_CZ.php        b      .   vendor/nesbot/carbon/src/Carbon/Lang/es_BO.php        	      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CI.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/sd.php	      	  4{      /   vendor/nesbot/carbon/src/Carbon/Lang/crh_UA.phpe      e  XN֤      0   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant.phpl      l  򶍄      .   vendor/nesbot/carbon/src/Carbon/Lang/ca_FR.php)      )  }      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SS.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_LU.php        .S      /   vendor/nesbot/carbon/src/Carbon/Lang/chr_US.php        @%9      .   vendor/nesbot/carbon/src/Carbon/Lang/so_SO.phpQ      Q  ڑ      ,   vendor/nesbot/carbon/src/Carbon/Lang/sat.phpO      O  }T      .   vendor/nesbot/carbon/src/Carbon/Lang/ru_MD.php        C=5      .   vendor/nesbot/carbon/src/Carbon/Lang/en_JE.php        ?Ej      /   vendor/nesbot/carbon/src/Carbon/Lang/zh_YUE.php        >1      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_EH.php)      )  Ϥ      +   vendor/nesbot/carbon/src/Carbon/Lang/st.phpN      N  	m      ,   vendor/nesbot/carbon/src/Carbon/Lang/kam.php        ^      .   vendor/nesbot/carbon/src/Carbon/Lang/xh_ZA.php        fW      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_KM.php)      )  Ϥ      +   vendor/nesbot/carbon/src/Carbon/Lang/am.phpN      N  O2a      /   vendor/nesbot/carbon/src/Carbon/Lang/dsb_DE.php8      8        +   vendor/nesbot/carbon/src/Carbon/Lang/bi.phpN      N        ,   vendor/nesbot/carbon/src/Carbon/Lang/kok.phpO      O  Kn      /   vendor/nesbot/carbon/src/Carbon/Lang/lrc_IQ.php        Ȍ[{      .   vendor/nesbot/carbon/src/Carbon/Lang/en_NU.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/gd_GB.php        sդ      .   vendor/nesbot/carbon/src/Carbon/Lang/ur_PK.php        X`      /   vendor/nesbot/carbon/src/Carbon/Lang/wae_CH.php        v      +   vendor/nesbot/carbon/src/Carbon/Lang/pt.php              .   vendor/nesbot/carbon/src/Carbon/Lang/ti_ER.php              /   vendor/nesbot/carbon/src/Carbon/Lang/ber_DZ.php        j      .   vendor/nesbot/carbon/src/Carbon/Lang/es_PE.php        d      ,   vendor/nesbot/carbon/src/Carbon/Lang/prg.php        ܒ      ,   vendor/nesbot/carbon/src/Carbon/Lang/fur.phpO      O        .   vendor/nesbot/carbon/src/Carbon/Lang/fr_VU.php
      
  wȤ      +   vendor/nesbot/carbon/src/Carbon/Lang/nl.php        +L4      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_SD.php        , ۤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_CM.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/ve_ZA.php        nP      /   vendor/nesbot/carbon/src/Carbon/Lang/gez_ER.php              +   vendor/nesbot/carbon/src/Carbon/Lang/km.php              /   vendor/nesbot/carbon/src/Carbon/Lang/es_419.php        d      .   vendor/nesbot/carbon/src/Carbon/Lang/en_CC.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/en_DE.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/ks.phpN      N        .   vendor/nesbot/carbon/src/Carbon/Lang/de_LI.php        7T       -   vendor/nesbot/carbon/src/Carbon/Lang/i18n.php        Nd      /   vendor/nesbot/carbon/src/Carbon/Lang/ast_ES.php        	+      .   vendor/nesbot/carbon/src/Carbon/Lang/en_NL.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/bo.php        >=      /   vendor/nesbot/carbon/src/Carbon/Lang/bem_ZM.php              .   vendor/nesbot/carbon/src/Carbon/Lang/en_FJ.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/hak.phpO      O  /{P      .   vendor/nesbot/carbon/src/Carbon/Lang/ne_NP.php        z      .   vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php
      
  .      +   vendor/nesbot/carbon/src/Carbon/Lang/bs.php}      }  Pj      ,   vendor/nesbot/carbon/src/Carbon/Lang/tcy.phpO      O  7      +   vendor/nesbot/carbon/src/Carbon/Lang/as.phpN      N  u      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_DJ.php(      (        3   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_MO.php        Ӿ6      +   vendor/nesbot/carbon/src/Carbon/Lang/vi.php
      
  <
      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GY.php        ?Ej      /   vendor/nesbot/carbon/src/Carbon/Lang/hne_IN.phpc      c  (      .   vendor/nesbot/carbon/src/Carbon/Lang/en_CK.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/dz_BT.phpz	      z	  `      +   vendor/nesbot/carbon/src/Carbon/Lang/ka.php3      3  ?      .   vendor/nesbot/carbon/src/Carbon/Lang/is_IS.php        hk      0   vendor/nesbot/carbon/src/Carbon/Lang/uz_Cyrl.php        cNz      .   vendor/nesbot/carbon/src/Carbon/Lang/es_CR.php        a      +   vendor/nesbot/carbon/src/Carbon/Lang/sh.php        ȗ      .   vendor/nesbot/carbon/src/Carbon/Lang/so_DJ.php        v      +   vendor/nesbot/carbon/src/Carbon/Lang/lb.phpv      v  Xt      .   vendor/nesbot/carbon/src/Carbon/Lang/ln_CF.php        ^٤      +   vendor/nesbot/carbon/src/Carbon/Lang/ts.phpN      N  x0      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_PF.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/ak_GH.php        ?`W      .   vendor/nesbot/carbon/src/Carbon/Lang/it_CH.php        4      +   vendor/nesbot/carbon/src/Carbon/Lang/ii.php        Ĭ      +   vendor/nesbot/carbon/src/Carbon/Lang/fi.php
      
  IV      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_DZ.php        =8      +   vendor/nesbot/carbon/src/Carbon/Lang/zh.php        pR      .   vendor/nesbot/carbon/src/Carbon/Lang/fa_AF.php        QiD      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MW.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/jgo.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/fr_SY.phpA      A  E      .   vendor/nesbot/carbon/src/Carbon/Lang/bg_BG.php        dIk      ,   vendor/nesbot/carbon/src/Carbon/Lang/tig.phpO      O  aؠդ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SI.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/pa_PK.php        v뷤      .   vendor/nesbot/carbon/src/Carbon/Lang/nn_NO.php        [      ,   vendor/nesbot/carbon/src/Carbon/Lang/gez.phpO      O  8      .   vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php              .   vendor/nesbot/carbon/src/Carbon/Lang/en_SG.phpL      L  ^-      +   vendor/nesbot/carbon/src/Carbon/Lang/en.php        \I      ,   vendor/nesbot/carbon/src/Carbon/Lang/khq.php<      <  ^      .   vendor/nesbot/carbon/src/Carbon/Lang/bn_IN.php        B      .   vendor/nesbot/carbon/src/Carbon/Lang/si_LK.php        dZ      .   vendor/nesbot/carbon/src/Carbon/Lang/ce_RU.php2      2  ov      ,   vendor/nesbot/carbon/src/Carbon/Lang/raj.phpO      O  5u      .   vendor/nesbot/carbon/src/Carbon/Lang/ig_NG.phpk      k  +      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CH.php        v      .   vendor/nesbot/carbon/src/Carbon/Lang/sv_AX.php        .a      +   vendor/nesbot/carbon/src/Carbon/Lang/ar.php        Պ.      +   vendor/nesbot/carbon/src/Carbon/Lang/jv.phpX
      X
  81      ,   vendor/nesbot/carbon/src/Carbon/Lang/mgh.php        2[       .   vendor/nesbot/carbon/src/Carbon/Lang/en_CA.php        '      .   vendor/nesbot/carbon/src/Carbon/Lang/es_CL.php        d      .   vendor/nesbot/carbon/src/Carbon/Lang/en_AI.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/it.php        b      .   vendor/nesbot/carbon/src/Carbon/Lang/oc_FR.php        ɠnd      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_SY.php>      >  -!b      .   vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php        v      .   vendor/nesbot/carbon/src/Carbon/Lang/en_BZ.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/ta_IN.phpt      t  )      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_TD.php
      
  wȤ      .   vendor/nesbot/carbon/src/Carbon/Lang/wo_SN.php"      "  c      ,   vendor/nesbot/carbon/src/Carbon/Lang/kde.php6      6  [)      /   vendor/nesbot/carbon/src/Carbon/Lang/mhr_RU.php|      |   7      ,   vendor/nesbot/carbon/src/Carbon/Lang/ast.php        Դ      ,   vendor/nesbot/carbon/src/Carbon/Lang/wae.phpO      O  /k      .   vendor/nesbot/carbon/src/Carbon/Lang/nl_NL.php        -^      /   vendor/nesbot/carbon/src/Carbon/Lang/doi_IN.phpt      t  K2Y      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GD.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/nd.php        1      /   vendor/nesbot/carbon/src/Carbon/Lang/niu_NU.php        D      /   vendor/nesbot/carbon/src/Carbon/Lang/fil_PH.phpN      N  i      .   vendor/nesbot/carbon/src/Carbon/Lang/ug_CN.phpA      A  l3      .   vendor/nesbot/carbon/src/Carbon/Lang/sl_SI.php               .   vendor/nesbot/carbon/src/Carbon/Lang/fr_TG.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_DJ.php)      )  Ϥ      /   vendor/nesbot/carbon/src/Carbon/Lang/ccp_IN.phpC      C  ]      .   vendor/nesbot/carbon/src/Carbon/Lang/tg_TJ.php        rΤ      /   vendor/nesbot/carbon/src/Carbon/Lang/teo_KE.phpH      H  <      .   vendor/nesbot/carbon/src/Carbon/Lang/en_LR.php        ?Ej      3   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_HK.php        ʷ      /   vendor/nesbot/carbon/src/Carbon/Lang/nan_TW.php              .   vendor/nesbot/carbon/src/Carbon/Lang/eu_ES.php        K      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_TL.php        [ia      .   vendor/nesbot/carbon/src/Carbon/Lang/he_IL.php        `Ƥ      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_IL.php)      )  Ϥ      .   vendor/nesbot/carbon/src/Carbon/Lang/ca_ES.php        T      +   vendor/nesbot/carbon/src/Carbon/Lang/lt.php        of2	      /   vendor/nesbot/carbon/src/Carbon/Lang/mjw_IN.php        Hl      /   vendor/nesbot/carbon/src/Carbon/Lang/lij_IT.php        n      .   vendor/nesbot/carbon/src/Carbon/Lang/en_AU.php        y      .   vendor/nesbot/carbon/src/Carbon/Lang/en_NR.php        ?Ej      /   vendor/nesbot/carbon/src/Carbon/Lang/raj_IN.php        CK      .   vendor/nesbot/carbon/src/Carbon/Lang/en_PK.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/en_ZW.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/fr_PM.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/es_VE.php        d      ,   vendor/nesbot/carbon/src/Carbon/Lang/unm.phpO      O   k      /   vendor/nesbot/carbon/src/Carbon/Lang/nds_NL.php          Tr٤      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CG.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/ru_KZ.php        C=5      .   vendor/nesbot/carbon/src/Carbon/Lang/as_IN.phpg	      g	  pL      ,   vendor/nesbot/carbon/src/Carbon/Lang/cgg.php        s      .   vendor/nesbot/carbon/src/Carbon/Lang/es_PA.php        d      ,   vendor/nesbot/carbon/src/Carbon/Lang/mer.php        2a9      .   vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php        {$      .   vendor/nesbot/carbon/src/Carbon/Lang/en_CY.phpo      o  &?      .   vendor/nesbot/carbon/src/Carbon/Lang/en_UG.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/en_VI.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/sw_CD.php~      ~  =Y      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_HT.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/hy.php        i )      .   vendor/nesbot/carbon/src/Carbon/Lang/en_TT.phpG      G        ,   vendor/nesbot/carbon/src/Carbon/Lang/smn.php              .   vendor/nesbot/carbon/src/Carbon/Lang/yo_BJ.phpN      N  :ɤ      ,   vendor/nesbot/carbon/src/Carbon/Lang/mgo.php        Y      +   vendor/nesbot/carbon/src/Carbon/Lang/cs.php        jm      ,   vendor/nesbot/carbon/src/Carbon/Lang/kab.phpO      O  ~      +   vendor/nesbot/carbon/src/Carbon/Lang/eu.php              .   vendor/nesbot/carbon/src/Carbon/Lang/nl_SX.php        &5      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_TN.php        C      .   vendor/nesbot/carbon/src/Carbon/Lang/yo_NG.php        }      .   vendor/nesbot/carbon/src/Carbon/Lang/an_ES.php        ǖ      ,   vendor/nesbot/carbon/src/Carbon/Lang/quz.phpO      O  }4      .   vendor/nesbot/carbon/src/Carbon/Lang/en_IM.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/mo.php        Nn      .   vendor/nesbot/carbon/src/Carbon/Lang/kn_IN.php        䇢      ,   vendor/nesbot/carbon/src/Carbon/Lang/tzl.php 	       	  UG       /   vendor/nesbot/carbon/src/Carbon/Lang/brx_IN.php0      0        .   vendor/nesbot/carbon/src/Carbon/Lang/kl_GL.php<
      <
  -UY      3   vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_XK.php        >      .   vendor/nesbot/carbon/src/Carbon/Lang/so_KE.phpQ      Q  ڑ      .   vendor/nesbot/carbon/src/Carbon/Lang/ks_IN.php              .   vendor/nesbot/carbon/src/Carbon/Lang/ar_IQ.php>      >  -!b      .   vendor/nesbot/carbon/src/Carbon/Lang/nl_BE.php        Ek      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_KW.php        |֤      ,   vendor/nesbot/carbon/src/Carbon/Lang/nmg.php        *T      ,   vendor/nesbot/carbon/src/Carbon/Lang/kln.php        {WYn      /   vendor/nesbot/carbon/src/Carbon/Lang/sah_RU.php        K:      .   vendor/nesbot/carbon/src/Carbon/Lang/br_FR.php        +v0%      ,   vendor/nesbot/carbon/src/Carbon/Lang/bas.php0      0  <      ,   vendor/nesbot/carbon/src/Carbon/Lang/bez.php        "      /   vendor/nesbot/carbon/src/Carbon/Lang/bhb_IN.php        u      1   vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php        }t      .   vendor/nesbot/carbon/src/Carbon/Lang/gu_IN.php        }:be      .   vendor/nesbot/carbon/src/Carbon/Lang/ms_MY.phpN      N  kz      .   vendor/nesbot/carbon/src/Carbon/Lang/tr_TR.php        M      .   vendor/nesbot/carbon/src/Carbon/Lang/af_NA.phpF      F  ]      .   vendor/nesbot/carbon/src/Carbon/Lang/en_BI.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/nr_ZA.php        N      +   vendor/nesbot/carbon/src/Carbon/Lang/ln.php          <      .   vendor/nesbot/carbon/src/Carbon/Lang/sv_FI.php        .      +   vendor/nesbot/carbon/src/Carbon/Lang/sr.phpU      U  z0]      .   vendor/nesbot/carbon/src/Carbon/Lang/qu_EC.phpG      G  \      ,   vendor/nesbot/carbon/src/Carbon/Lang/zgh.phpx      x  f/      /   vendor/nesbot/carbon/src/Carbon/Lang/ayc_PE.php              .   vendor/nesbot/carbon/src/Carbon/Lang/fo_DK.php        5
      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_SA.php        9>ۤ      .   vendor/nesbot/carbon/src/Carbon/Lang/gl_ES.php        }      ,   vendor/nesbot/carbon/src/Carbon/Lang/ckb.php;      ;  X5ͤ      6   vendor/nesbot/carbon/src/Carbon/Lang/tt_RU@iqtelif.php        V       ,   vendor/nesbot/carbon/src/Carbon/Lang/mua.php        )v      +   vendor/nesbot/carbon/src/Carbon/Lang/my.php        ?'(      .   vendor/nesbot/carbon/src/Carbon/Lang/ha_NE.php        }*B      /   vendor/nesbot/carbon/src/Carbon/Lang/miq_NI.php        Je      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SZ.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/dav.php        "kä      +   vendor/nesbot/carbon/src/Carbon/Lang/mi.php4	      4	  k_ؾ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MH.phpG      G        ,   vendor/nesbot/carbon/src/Carbon/Lang/haw.php        ]]      ,   vendor/nesbot/carbon/src/Carbon/Lang/nus.php        'Ht̤      +   vendor/nesbot/carbon/src/Carbon/Lang/az.php              0   vendor/nesbot/carbon/src/Carbon/Lang/uz_Arab.php              /   vendor/nesbot/carbon/src/Carbon/Lang/gsw_CH.php        \1l      ,   vendor/nesbot/carbon/src/Carbon/Lang/rwk.phpC      C  T.      ,   vendor/nesbot/carbon/src/Carbon/Lang/naq.php        lW      +   vendor/nesbot/carbon/src/Carbon/Lang/sw.php	      	  
      1   vendor/nesbot/carbon/src/Carbon/Lang/vai_Vaii.php        ZO      /   vendor/nesbot/carbon/src/Carbon/Lang/tcy_IN.php8      8  }      .   vendor/nesbot/carbon/src/Carbon/Lang/ss_ZA.php         !R      +   vendor/nesbot/carbon/src/Carbon/Lang/pl.php        @@      .   vendor/nesbot/carbon/src/Carbon/Lang/se_NO.php        +      .   vendor/nesbot/carbon/src/Carbon/Lang/ff_CM.php        -      .   vendor/nesbot/carbon/src/Carbon/Lang/en_IN.phpu      u  #r      .   vendor/nesbot/carbon/src/Carbon/Lang/ik_CA.php)      )  4©      +   vendor/nesbot/carbon/src/Carbon/Lang/sl.php        w\,      +   vendor/nesbot/carbon/src/Carbon/Lang/ko.phpm
      m
  7      .   vendor/nesbot/carbon/src/Carbon/Lang/ts_ZA.php        +tp      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GU.phpG      G        +   vendor/nesbot/carbon/src/Carbon/Lang/he.phpg      g  Būb      ,   vendor/nesbot/carbon/src/Carbon/Lang/lag.php        FƤ      0   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans.phpb      b  Z#      +   vendor/nesbot/carbon/src/Carbon/Lang/bn.php        <      ,   vendor/nesbot/carbon/src/Carbon/Lang/yuw.phpO      O  d      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_GQ.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/es_CU.phpG      G  (|@z      /   vendor/nesbot/carbon/src/Carbon/Lang/szl_PL.php        eѡ      1   vendor/nesbot/carbon/src/Carbon/Lang/vai_Latn.phps      s  1      .   vendor/nesbot/carbon/src/Carbon/Lang/en_NF.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/sq.phpV
      V
  ͤ      .   vendor/nesbot/carbon/src/Carbon/Lang/bi_VU.php}      }  {      .   vendor/nesbot/carbon/src/Carbon/Lang/sr_RS.phpc      c  &*B      +   vendor/nesbot/carbon/src/Carbon/Lang/ja.php        ?j      ,   vendor/nesbot/carbon/src/Carbon/Lang/sbp.phpc      c  EW      7   vendor/nesbot/carbon/src/Carbon/Lang/ca_ES_Valencia.phpQ      Q  c㇤      1   vendor/nesbot/carbon/src/Carbon/Lang/yue_Hans.php        Ӿ6      .   vendor/nesbot/carbon/src/Carbon/Lang/sa_IN.php	      	  <z      .   vendor/nesbot/carbon/src/Carbon/Lang/gv_GB.php        .ʤ      ,   vendor/nesbot/carbon/src/Carbon/Lang/lrc.php        *]      ,   vendor/nesbot/carbon/src/Carbon/Lang/szl.phpO      O  VB      .   vendor/nesbot/carbon/src/Carbon/Lang/fa_IR.php        芤      /   vendor/nesbot/carbon/src/Carbon/Lang/nhn_MX.php0      0  ֿ      +   vendor/nesbot/carbon/src/Carbon/Lang/ki.php        gw      .   vendor/nesbot/carbon/src/Carbon/Lang/se_FI.phpw      w  ߴ/      /   vendor/nesbot/carbon/src/Carbon/Lang/anp_IN.php        Ee'      3   vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_BA.php        #	'      ,   vendor/nesbot/carbon/src/Carbon/Lang/anp.phpO      O  "B      +   vendor/nesbot/carbon/src/Carbon/Lang/ig.phpN      N         +   vendor/nesbot/carbon/src/Carbon/Lang/mg.phpN      N  (      .   vendor/nesbot/carbon/src/Carbon/Lang/uk_UA.php        se      .   vendor/nesbot/carbon/src/Carbon/Lang/th_TH.php        3`      .   vendor/nesbot/carbon/src/Carbon/Lang/ne_IN.php              .   vendor/nesbot/carbon/src/Carbon/Lang/ro_RO.php        Nn      .   vendor/nesbot/carbon/src/Carbon/Lang/sk_SK.php        
      .   vendor/nesbot/carbon/src/Carbon/Lang/en_FM.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/yo.php	      	  {      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_BJ.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_KM.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/ja_JP.php        l      .   vendor/nesbot/carbon/src/Carbon/Lang/ha_NG.php        }*B      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_CD.php        ''x      /   vendor/nesbot/carbon/src/Carbon/Lang/kok_IN.php
      
  9+LQ      .   vendor/nesbot/carbon/src/Carbon/Lang/ln_CD.phpW      W  W      +   vendor/nesbot/carbon/src/Carbon/Lang/os.phpN      N  !      .   vendor/nesbot/carbon/src/Carbon/Lang/ff_SN.php^      ^  Y      ,   vendor/nesbot/carbon/src/Carbon/Lang/ccp.php	      	  $      +   vendor/nesbot/carbon/src/Carbon/Lang/lv.php        uƤ      +   vendor/nesbot/carbon/src/Carbon/Lang/wa.phpN      N  ."      .   vendor/nesbot/carbon/src/Carbon/Lang/sw_TZ.php        v      .   vendor/nesbot/carbon/src/Carbon/Lang/en_KE.phpG      G        ,   vendor/nesbot/carbon/src/Carbon/Lang/rof.php        %      +   vendor/nesbot/carbon/src/Carbon/Lang/iw.php              .   vendor/nesbot/carbon/src/Carbon/Lang/se_SE.php        +      ,   vendor/nesbot/carbon/src/Carbon/Lang/chr.phpO      O  8      .   vendor/nesbot/carbon/src/Carbon/Lang/ms_SG.php(      (  	8      +   vendor/nesbot/carbon/src/Carbon/Lang/ru.php        Ǥ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MU.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/om_KE.phpO      O  }z      ,   vendor/nesbot/carbon/src/Carbon/Lang/luy.phpB      B  U2{      /   vendor/nesbot/carbon/src/Carbon/Lang/mai_IN.php	      	  6      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_BF.php        ''x      3   vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_BA.php'      '  GoV      .   vendor/nesbot/carbon/src/Carbon/Lang/sm_WS.php        ]5      .   vendor/nesbot/carbon/src/Carbon/Lang/lb_LU.php        I      .   vendor/nesbot/carbon/src/Carbon/Lang/my_MM.php        㧤      +   vendor/nesbot/carbon/src/Carbon/Lang/tr.php        aɲ*      /   vendor/nesbot/carbon/src/Carbon/Lang/pap_CW.phpk      k  6Ĥ      .   vendor/nesbot/carbon/src/Carbon/Lang/el_CY.php        ̄A.      ,   vendor/nesbot/carbon/src/Carbon/Lang/doi.phpO      O  -'      .   vendor/nesbot/carbon/src/Carbon/Lang/lg_UG.php        grt      .   vendor/nesbot/carbon/src/Carbon/Lang/sq_AL.php        '      .   vendor/nesbot/carbon/src/Carbon/Lang/az_AZ.php        haK      .   vendor/nesbot/carbon/src/Carbon/Lang/tk_TM.phpX      X  "      +   vendor/nesbot/carbon/src/Carbon/Lang/et.php#      #   Ф      ,   vendor/nesbot/carbon/src/Carbon/Lang/csb.phpO      O        +   vendor/nesbot/carbon/src/Carbon/Lang/sm.phpN      N  "w      .   vendor/nesbot/carbon/src/Carbon/Lang/aa_ET.php        S      .   vendor/nesbot/carbon/src/Carbon/Lang/el_GR.php        vÕ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_RW.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/ku_TR.php        iV      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_LY.php@      @  Tʟ%      ,   vendor/nesbot/carbon/src/Carbon/Lang/agr.phpO      O  3I1ڤ      /   vendor/nesbot/carbon/src/Carbon/Lang/yue_HK.php          w}      .   vendor/nesbot/carbon/src/Carbon/Lang/en_TC.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/el.php'      '  g      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_CV.php        [ia      ,   vendor/nesbot/carbon/src/Carbon/Lang/agq.php)      )  I      ,   vendor/nesbot/carbon/src/Carbon/Lang/nan.phpO      O  դ      +   vendor/nesbot/carbon/src/Carbon/Lang/gu.php.      .        .   vendor/nesbot/carbon/src/Carbon/Lang/es_BZ.phpG      G  w7ܤ      +   vendor/nesbot/carbon/src/Carbon/Lang/pa.php        |oU      0   vendor/nesbot/carbon/src/Carbon/Lang/bs_Cyrl.php              .   vendor/nesbot/carbon/src/Carbon/Lang/wa_BE.php              .   vendor/nesbot/carbon/src/Carbon/Lang/sc_IT.php        NJ      /   vendor/nesbot/carbon/src/Carbon/Lang/nso_ZA.php        zv      .   vendor/nesbot/carbon/src/Carbon/Lang/zh_SG.php.      .  %ۤ      ,   vendor/nesbot/carbon/src/Carbon/Lang/ses.phpv      v  >      +   vendor/nesbot/carbon/src/Carbon/Lang/fr.php        GP٤      +   vendor/nesbot/carbon/src/Carbon/Lang/ik.phpN      N  7ș      +   vendor/nesbot/carbon/src/Carbon/Lang/is.php        G      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_FR.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/tn.phpN      N  M|U      +   vendor/nesbot/carbon/src/Carbon/Lang/sa.phpN      N        .   vendor/nesbot/carbon/src/Carbon/Lang/zh_HK.php        z      3   vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_XK.php        r(      /   vendor/nesbot/carbon/src/Carbon/Lang/shs_CA.php&      &  2      +   vendor/nesbot/carbon/src/Carbon/Lang/an.phpN      N  W]F      ,   vendor/nesbot/carbon/src/Carbon/Lang/crh.phpO      O  nR      .   vendor/nesbot/carbon/src/Carbon/Lang/hu_HU.php        ۺ      /   vendor/nesbot/carbon/src/Carbon/Lang/agr_PE.phpM      M  ODƤ      +   vendor/nesbot/carbon/src/Carbon/Lang/id.phpu      u  7      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_SO.php)      )  Ϥ      .   vendor/nesbot/carbon/src/Carbon/Lang/ht_HT.php?      ?  O      +   vendor/nesbot/carbon/src/Carbon/Lang/cy.php        fA      ,   vendor/nesbot/carbon/src/Carbon/Lang/niu.phpO      O  S%      .   vendor/nesbot/carbon/src/Carbon/Lang/so_ET.phpQ      Q  ڑ      /   vendor/nesbot/carbon/src/Carbon/Lang/unm_US.php               +   vendor/nesbot/carbon/src/Carbon/Lang/hr.php        M`      .   vendor/nesbot/carbon/src/Carbon/Lang/en_CH.php        ɦ/      .   vendor/nesbot/carbon/src/Carbon/Lang/mi_NZ.php        Xۤ      /   vendor/nesbot/carbon/src/Carbon/Lang/lzh_TW.php        >      .   vendor/nesbot/carbon/src/Carbon/Lang/sv_SE.php        .      /   vendor/nesbot/carbon/src/Carbon/Lang/mfe_MU.php1      1  (8      +   vendor/nesbot/carbon/src/Carbon/Lang/se.php
      
  h      ,   vendor/nesbot/carbon/src/Carbon/Lang/mai.phpO      O  h      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SL.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/xog.php\      \  O      +   vendor/nesbot/carbon/src/Carbon/Lang/li.phpN      N  `      .   vendor/nesbot/carbon/src/Carbon/Lang/cv_RU.php        l      0   vendor/nesbot/carbon/src/Carbon/Lang/uz_Latn.php	      	  oP      .   vendor/nesbot/carbon/src/Carbon/Lang/ru_BY.php        C=5      0   vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php        fk      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_RE.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/hi_IN.php        ϑ      .   vendor/nesbot/carbon/src/Carbon/Lang/mr_IN.php              .   vendor/nesbot/carbon/src/Carbon/Lang/fr_GA.php        ''x      /   vendor/nesbot/carbon/src/Carbon/Lang/the_NP.php        sʤ      .   vendor/nesbot/carbon/src/Carbon/Lang/ko_KR.php        -n      .   vendor/nesbot/carbon/src/Carbon/Lang/en_BB.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/yi.phpN      N        .   vendor/nesbot/carbon/src/Carbon/Lang/en_NG.php        (ظ?      .   vendor/nesbot/carbon/src/Carbon/Lang/ff_MR.php	      	  \      .   vendor/nesbot/carbon/src/Carbon/Lang/or_IN.php               +   vendor/nesbot/carbon/src/Carbon/Lang/ky.php        _0      /   vendor/nesbot/carbon/src/Carbon/Lang/kab_DZ.php        pW)Q      .   vendor/nesbot/carbon/src/Carbon/Lang/es_NI.php        -|K      7   vendor/nesbot/carbon/src/Carbon/Lang/uz_UZ@cyrillic.php        Ĳj      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_NE.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/hy_AM.php        az      .   vendor/nesbot/carbon/src/Carbon/Lang/en_PR.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/lt_LT.php        >+      1   vendor/nesbot/carbon/src/Carbon/Lang/gom_Latn.phpI	      I	  R;      +   vendor/nesbot/carbon/src/Carbon/Lang/mn.php!      !  s      .   vendor/nesbot/carbon/src/Carbon/Lang/ru_UA.php        !k      .   vendor/nesbot/carbon/src/Carbon/Lang/iu_CA.php        Dn      ,   vendor/nesbot/carbon/src/Carbon/Lang/tzm.php
      
  8      +   vendor/nesbot/carbon/src/Carbon/Lang/kw.phpN      N  KV--      .   vendor/nesbot/carbon/src/Carbon/Lang/ko_KP.phpG      G  x      +   vendor/nesbot/carbon/src/Carbon/Lang/fo.php	      	  "Ϥ      .   vendor/nesbot/carbon/src/Carbon/Lang/ga_IE.php              .   vendor/nesbot/carbon/src/Carbon/Lang/vi_VN.php        +H      .   vendor/nesbot/carbon/src/Carbon/Lang/es_EC.php        d      .   vendor/nesbot/carbon/src/Carbon/Lang/ru_KG.php        C=5      .   vendor/nesbot/carbon/src/Carbon/Lang/en_LC.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/gom.phpQ      Q  s	      3   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_HK.php        Ӿ6      +   vendor/nesbot/carbon/src/Carbon/Lang/rn.phpI      I  9      +   vendor/nesbot/carbon/src/Carbon/Lang/kl.phpN      N  p      +   vendor/nesbot/carbon/src/Carbon/Lang/tt.phpN      N  }jZ      ,   vendor/nesbot/carbon/src/Carbon/Lang/shn.phpO      O  L-xV      .   vendor/nesbot/carbon/src/Carbon/Lang/en_LS.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/en_TK.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/tk.phpN      N         +   vendor/nesbot/carbon/src/Carbon/Lang/dv.php
      
  Dg      .   vendor/nesbot/carbon/src/Carbon/Lang/bo_CN.php        R¤      .   vendor/nesbot/carbon/src/Carbon/Lang/id_ID.php        Zб      .   vendor/nesbot/carbon/src/Carbon/Lang/es_AR.php        d      .   vendor/nesbot/carbon/src/Carbon/Lang/te_IN.php        u      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GM.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/byn.phpO      O  r      4   vendor/nesbot/carbon/src/Carbon/Lang/sr_RS@latin.php               /   vendor/nesbot/carbon/src/Carbon/Lang/ber_MA.php        j      .   vendor/nesbot/carbon/src/Carbon/Lang/az_IR.php        aVS      .   vendor/nesbot/carbon/src/Carbon/Lang/mk_MK.php        }      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_DZ.phpA      A  E      ,   vendor/nesbot/carbon/src/Carbon/Lang/tet.php        m|      ,   vendor/nesbot/carbon/src/Carbon/Lang/lzh.phpO      O  J>       +   vendor/nesbot/carbon/src/Carbon/Lang/lg.phpN      N  =      .   vendor/nesbot/carbon/src/Carbon/Lang/en_TZ.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_CH.php        [ia      ,   vendor/nesbot/carbon/src/Carbon/Lang/dje.php        &      +   vendor/nesbot/carbon/src/Carbon/Lang/hi.php        3\      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MG.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/ksh.php\      \  Qo      .   vendor/nesbot/carbon/src/Carbon/Lang/fy_DE.php        D      /   vendor/nesbot/carbon/src/Carbon/Lang/sid_ET.php        <5      .   vendor/nesbot/carbon/src/Carbon/Lang/en_US.phpG      G        /   vendor/nesbot/carbon/src/Carbon/Lang/en_150.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/de_AT.php        :ɷ      .   vendor/nesbot/carbon/src/Carbon/Lang/yi_US.php          ŝؤ      0   vendor/nesbot/carbon/src/Carbon/Lang/az_Cyrl.php        6QI      .   vendor/nesbot/carbon/src/Carbon/Lang/tt_RU.php        r9Ť      .   vendor/nesbot/carbon/src/Carbon/Lang/to_TO.phpn      n  k      .   vendor/nesbot/carbon/src/Carbon/Lang/aa_DJ.php        JBm      +   vendor/nesbot/carbon/src/Carbon/Lang/or.phpN      N        .   vendor/nesbot/carbon/src/Carbon/Lang/de_BE.php        "       .   vendor/nesbot/carbon/src/Carbon/Lang/en_FK.php        ?Ej      /   vendor/nesbot/carbon/src/Carbon/Lang/gsw_LI.phpl      l  $ r      .   vendor/nesbot/carbon/src/Carbon/Lang/rw_RW.php        co      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_RW.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/tr_CY.php        ς      .   vendor/nesbot/carbon/src/Carbon/Lang/en_ZA.phpi      i  {1      .   vendor/nesbot/carbon/src/Carbon/Lang/en_BM.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/en_FI.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/wal.phpO      O  L(      +   vendor/nesbot/carbon/src/Carbon/Lang/fa.php        ^5&      .   vendor/nesbot/carbon/src/Carbon/Lang/en_CX.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/sw_UG.php~      ~  =Y      .   vendor/nesbot/carbon/src/Carbon/Lang/st_ZA.php        j"      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_NC.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/en_MS.php        ?Ej      3   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hant_MO.php        ʷ      /   vendor/nesbot/carbon/src/Carbon/Lang/hak_TW.php        ؤ      +   vendor/nesbot/carbon/src/Carbon/Lang/rw.phpN      N  Wn      .   vendor/nesbot/carbon/src/Carbon/Lang/en_DM.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/da_DK.php        i9      .   vendor/nesbot/carbon/src/Carbon/Lang/ml_IN.php        㚸      .   vendor/nesbot/carbon/src/Carbon/Lang/ka_GE.php        {      .   vendor/nesbot/carbon/src/Carbon/Lang/ff_GN.php        -      .   vendor/nesbot/carbon/src/Carbon/Lang/ta_SG.php        ޙ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_IL.php        O
Mg      4   vendor/nesbot/carbon/src/Carbon/Lang/aa_ER@saaho.php(      (  1H      ,   vendor/nesbot/carbon/src/Carbon/Lang/twq.phpX      X  jt      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_BL.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/xh.phpN      N        +   vendor/nesbot/carbon/src/Carbon/Lang/th.php        ke      /   vendor/nesbot/carbon/src/Carbon/Lang/cmn_TW.phpg      g  U      .   vendor/nesbot/carbon/src/Carbon/Lang/bo_IN.php	      	  Ť      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_TD.php)      )  Ϥ      .   vendor/nesbot/carbon/src/Carbon/Lang/es_MX.php        `      .   vendor/nesbot/carbon/src/Carbon/Lang/nl_CW.php        &5      ,   vendor/nesbot/carbon/src/Carbon/Lang/lkt.php        d      1   vendor/nesbot/carbon/src/Carbon/Lang/yue_Hant.php        ʷ      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_MO.php        1/      /   vendor/nesbot/carbon/src/Carbon/Lang/wal_ET.php        v4o      .   vendor/nesbot/carbon/src/Carbon/Lang/es_IC.phpG      G  (|@z      .   vendor/nesbot/carbon/src/Carbon/Lang/ta_LK.phpZ      Z  [դ      ,   vendor/nesbot/carbon/src/Carbon/Lang/sid.phpO      O  ^      +   vendor/nesbot/carbon/src/Carbon/Lang/mt.phpv
      v
  ^ӧ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_DG.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/mfe.phpO      O  }      /   vendor/nesbot/carbon/src/Carbon/Lang/tpi_PG.php]      ]  7̤      +   vendor/nesbot/carbon/src/Carbon/Lang/kk.phpx      x  }      /   vendor/nesbot/carbon/src/Carbon/Lang/sat_IN.php	      	  Ͱ9      .   vendor/nesbot/carbon/src/Carbon/Lang/om_ET.php        q      .   vendor/nesbot/carbon/src/Carbon/Lang/es_GQ.phpG      G  (|@z      ,   vendor/nesbot/carbon/src/Carbon/Lang/nds.phpO      O  K}      /   vendor/nesbot/carbon/src/Carbon/Lang/bho_IN.php        y䌤      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_AO.php        [ia      ,   vendor/nesbot/carbon/src/Carbon/Lang/hif.phpO      O  @      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_BE.phpD      D  $qʤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_IE.php        C      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MF.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/af_ZA.php        ?uL      .   vendor/nesbot/carbon/src/Carbon/Lang/sq_MK.php               /   vendor/nesbot/carbon/src/Carbon/Lang/sgs_LT.php        ._      +   vendor/nesbot/carbon/src/Carbon/Lang/ku.php        -      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_WF.php        ''x      ,   vendor/nesbot/carbon/src/Carbon/Lang/ebu.php        oq      .   vendor/nesbot/carbon/src/Carbon/Lang/pl_PL.php        ?7Τ      ,   vendor/nesbot/carbon/src/Carbon/Lang/bhb.phpO      O  ;      .   vendor/nesbot/carbon/src/Carbon/Lang/en_HK.php              +   vendor/nesbot/carbon/src/Carbon/Lang/ne.php        V      ,   vendor/nesbot/carbon/src/Carbon/Lang/ewo.php[      [  D      ,   vendor/nesbot/carbon/src/Carbon/Lang/bho.phpO      O  <-      .   vendor/nesbot/carbon/src/Carbon/Lang/ky_KG.php        &Ԥ      1   vendor/nesbot/carbon/src/Carbon/Lang/shi_Tfng.php              ,   vendor/nesbot/carbon/src/Carbon/Lang/fil.phpO      O  if)      ,   vendor/nesbot/carbon/src/Carbon/Lang/hsb.phpO      O  B`      +   vendor/nesbot/carbon/src/Carbon/Lang/nn.phpQ
      Q
   ذ      .   vendor/nesbot/carbon/src/Carbon/Lang/mg_MG.php        B      /   vendor/nesbot/carbon/src/Carbon/Lang/en_ISO.php&      &  ¬      .   vendor/nesbot/carbon/src/Carbon/Lang/zh_CN.php        Dɳ      ,   vendor/nesbot/carbon/src/Carbon/Lang/seh.php/      /  MCk      .   vendor/nesbot/carbon/src/Carbon/Lang/nl_AW.php        c      .   vendor/nesbot/carbon/src/Carbon/Lang/en_SB.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/ps.php	      	  a=      +   vendor/nesbot/carbon/src/Carbon/Lang/uk.php#      #  p      ,   vendor/nesbot/carbon/src/Carbon/Lang/nhn.phpO      O        .   vendor/nesbot/carbon/src/Carbon/Lang/en_ZM.php        ÿ      ,   vendor/nesbot/carbon/src/Carbon/Lang/mag.phpO      O  -      ,   vendor/nesbot/carbon/src/Carbon/Lang/ber.phpO      O  wߤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_WS.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/en_BE.php        ?Ej      +   vendor/nesbot/carbon/src/Carbon/Lang/tg.php        h      +   vendor/nesbot/carbon/src/Carbon/Lang/ta.phpm      m  2(      +   vendor/nesbot/carbon/src/Carbon/Lang/tl.php        y      0   vendor/nesbot/carbon/src/Carbon/Lang/bs_Latn.php)      )  C      .   vendor/nesbot/carbon/src/Carbon/Lang/es_GT.php        d      +   vendor/nesbot/carbon/src/Carbon/Lang/sc.phpN      N  > K      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_MG.php        ''x      .   vendor/nesbot/carbon/src/Carbon/Lang/fr_YT.php        ''x      +   vendor/nesbot/carbon/src/Carbon/Lang/ga.php
      
  #R      .   vendor/nesbot/carbon/src/Carbon/Lang/ha_GH.php        }*B      +   vendor/nesbot/carbon/src/Carbon/Lang/sv.php'      '  i      ,   vendor/nesbot/carbon/src/Carbon/Lang/bem.phpO      O  D      +   vendor/nesbot/carbon/src/Carbon/Lang/qu.php)      )  C2X      .   vendor/nesbot/carbon/src/Carbon/Lang/es_BR.phpG      G  w7ܤ      .   vendor/nesbot/carbon/src/Carbon/Lang/es_CO.php        d      .   vendor/nesbot/carbon/src/Carbon/Lang/en_AT.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/kkj.phpG      G        +   vendor/nesbot/carbon/src/Carbon/Lang/wo.phpN      N  Չ      .   vendor/nesbot/carbon/src/Carbon/Lang/kk_KZ.php        pg      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_PS.php        W?      /   vendor/nesbot/carbon/src/Carbon/Lang/tig_ER.php(	      (	  /;)      1   vendor/nesbot/carbon/src/Carbon/Lang/shi_Latn.php        ac      1   vendor/nesbot/carbon/src/Carbon/Lang/tzm_Latn.php	      	  3	      .   vendor/nesbot/carbon/src/Carbon/Lang/kw_GB.php        m0פ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_PN.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/ksb.php@      @  й      .   vendor/nesbot/carbon/src/Carbon/Lang/zu_ZA.phpR      R  ha      +   vendor/nesbot/carbon/src/Carbon/Lang/ak.phpN      N  6      +   vendor/nesbot/carbon/src/Carbon/Lang/sg.php              .   vendor/nesbot/carbon/src/Carbon/Lang/ar_IN.phpZ      Z  Xl      +   vendor/nesbot/carbon/src/Carbon/Lang/ve.phpN      N  e       .   vendor/nesbot/carbon/src/Carbon/Lang/fr_ML.php        ''x      ,   vendor/nesbot/carbon/src/Carbon/Lang/dyo.php        ۨr      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_MR.php)      )  Ϥ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_PW.php        ?Ej      0   vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn.php               +   vendor/nesbot/carbon/src/Carbon/Lang/br.php
      
  VuФ      .   vendor/nesbot/carbon/src/Carbon/Lang/it_VA.php        q
a      ,   vendor/nesbot/carbon/src/Carbon/Lang/saq.php              .   vendor/nesbot/carbon/src/Carbon/Lang/pa_IN.phpc      c  
P      ,   vendor/nesbot/carbon/src/Carbon/Lang/ayc.phpO      O  l`P      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_SS.php~      ~  Â      .   vendor/nesbot/carbon/src/Carbon/Lang/cy_GB.php        >~!o      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GG.php        ?Ej      .   vendor/nesbot/carbon/src/Carbon/Lang/sd_IN.php        nä      +   vendor/nesbot/carbon/src/Carbon/Lang/ss.php
      
  0      .   vendor/nesbot/carbon/src/Carbon/Lang/de_CH.php              .   vendor/nesbot/carbon/src/Carbon/Lang/zh_MO.php        ^dL      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_LB.php>      >  泺4      .   vendor/nesbot/carbon/src/Carbon/Lang/pt_PT.php        Eޤ      .   vendor/nesbot/carbon/src/Carbon/Lang/ar_OM.php        , ۤ      .   vendor/nesbot/carbon/src/Carbon/Lang/en_AS.phpG      G        .   vendor/nesbot/carbon/src/Carbon/Lang/ca_AD.php)      )  }      3   vendor/nesbot/carbon/src/Carbon/Lang/zh_Hans_SG.php        Ӿ6      .   vendor/nesbot/carbon/src/Carbon/Lang/ee_TG.php        x$      9   vendor/nesbot/carbon/src/Carbon/Lang/sd_IN@devanagari.php        $Z      +   vendor/nesbot/carbon/src/Carbon/Lang/be.php#      #  c      .   vendor/nesbot/carbon/src/Carbon/Lang/en_GI.php        ?Ej      ,   vendor/nesbot/carbon/src/Carbon/Lang/mzn.php        A      .   vendor/nesbot/carbon/src/Carbon/Lang/de_DE.php_      _  Z)      .   vendor/nesbot/carbon/src/Carbon/Lang/mn_MN.php        Ѥ      ,   vendor/nesbot/carbon/src/Carbon/Lang/dua.phpq      q  ,Ǥ      3   vendor/nesbot/carbon/src/Carbon/CarbonInterface.php&     & ~      N   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php              A   vendor/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php        s!m      E   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php        6      C   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php        η      C   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.phpk      k  lv      C   vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php        B%L      C   vendor/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php        K)      G   vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php8      8   נ      G   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php        }6%      I   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php        ):      E   vendor/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php_      _  OV4      C   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php        .      I   vendor/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php        +      8   vendor/nesbot/carbon/src/Carbon/Exceptions/Exception.php@      @  t      G   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php        [g2      G   vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.phpa      a  A|      E   vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php'      '  p%      F   vendor/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php              G   vendor/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php        )      B   vendor/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php        =      B   vendor/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php        +>      E   vendor/nesbot/carbon/src/Carbon/Exceptions/EndLessPeriodException.php        r      <   vendor/nesbot/carbon/src/Carbon/Exceptions/UnitException.php        ,      E   vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php5      5  »      B   vendor/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php        h5w6      E   vendor/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php7      7  e      G   vendor/nesbot/carbon/src/Carbon/Exceptions/UnsupportedUnitException.php:      :  nzK      ?   vendor/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.phpY      Y  0Ԥ      L   vendor/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.phpC      C  dy"      I   vendor/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php        g      A   vendor/nesbot/carbon/src/Carbon/PHPStan/MacroMethodReflection.php
      
  ۜ      :   vendor/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.phpM      M        9   vendor/nesbot/carbon/src/Carbon/CarbonPeriodImmutable.phpX      X  }      6   vendor/nesbot/carbon/src/Carbon/AbstractTranslator.phpJw      Jw  Lcy         vendor/nesbot/carbon/LICENSE        ^T      #   vendor/nesbot/carbon/extension.neon          zD      #   vendor/nesbot/carbon/bin/carbon.bat]       ]   {mu0         vendor/nesbot/carbon/bin/carbon        $ɤ      -   vendor/symfony/polyfill-intl-grapheme/LICENSE,      ,  H      2   vendor/symfony/polyfill-intl-grapheme/Grapheme.php1      1  j1      3   vendor/symfony/polyfill-intl-grapheme/bootstrap.php8      8  m      5   vendor/symfony/polyfill-intl-grapheme/bootstrap80.phpB      B  `-      ,   vendor/symfony/translation/StaticMessage.php        㞠      ;   vendor/symfony/translation/PseudoLocalizationTranslator.php2/      2/  I      0   vendor/symfony/translation/Dumper/FileDumper.php              2   vendor/symfony/translation/Dumper/MoFileDumper.php        Ð@      5   vendor/symfony/translation/Dumper/XliffFileDumper.php$      $  *'      3   vendor/symfony/translation/Dumper/IniFileDumper.php        U6K      4   vendor/symfony/translation/Dumper/YamlFileDumper.php        w$      4   vendor/symfony/translation/Dumper/JsonFileDumper.phpE      E  ti      3   vendor/symfony/translation/Dumper/CsvFileDumper.php^      ^  q      2   vendor/symfony/translation/Dumper/PoFileDumper.php)      )        5   vendor/symfony/translation/Dumper/DumperInterface.php        8      6   vendor/symfony/translation/Dumper/IcuResFileDumper.php]      ]        2   vendor/symfony/translation/Dumper/QtFileDumper.php\      \  en2      3   vendor/symfony/translation/Dumper/PhpFileDumper.php        ɤ      5   vendor/symfony/translation/Loader/LoaderInterface.php        6      4   vendor/symfony/translation/Loader/JsonFileLoader.php        ꗤ      3   vendor/symfony/translation/Loader/IniFileLoader.php        >      6   vendor/symfony/translation/Loader/IcuResFileLoader.php
      
        3   vendor/symfony/translation/Loader/CsvFileLoader.php        Dj-      2   vendor/symfony/translation/Loader/PoFileLoader.php        m5      0   vendor/symfony/translation/Loader/FileLoader.php        Cމ      2   vendor/symfony/translation/Loader/QtFileLoader.php
      
  N:o      3   vendor/symfony/translation/Loader/PhpFileLoader.php        S      5   vendor/symfony/translation/Loader/XliffFileLoader.php$      $  Fp@      4   vendor/symfony/translation/Loader/YamlFileLoader.phpD      D  ͹o      6   vendor/symfony/translation/Loader/IcuDatFileLoader.php'      '  &-      2   vendor/symfony/translation/Loader/MoFileLoader.php        {PV      1   vendor/symfony/translation/Loader/ArrayLoader.php              7   vendor/symfony/translation/Writer/TranslationWriter.phpS      S  x      @   vendor/symfony/translation/Writer/TranslationWriterInterface.php        X2      8   vendor/symfony/translation/MessageCatalogueInterface.php        
ʤ      9   vendor/symfony/translation/Formatter/MessageFormatter.php        Ф      B   vendor/symfony/translation/Formatter/MessageFormatterInterface.phpV      V  ]s      ?   vendor/symfony/translation/Formatter/IntlFormatterInterface.php        Ϥ      6   vendor/symfony/translation/Formatter/IntlFormatter.phpO      O  g      -   vendor/symfony/translation/LocaleSwitcher.php        x^      2   vendor/symfony/translation/Resources/functions.php3      3  ۦ~      4   vendor/symfony/translation/Resources/schemas/xml.xsd"      "  "@      ?   vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsdlA      lA  D      L   vendor/symfony/translation/Resources/schemas/xliff-core-1.2-transitional.xsd             ?   vendor/symfony/translation/Resources/bin/translation-status.php"      "  zv      6   vendor/symfony/translation/Resources/data/parents.json        cD      C   vendor/symfony/translation/Exception/ProviderExceptionInterface.php/      /  ܤ      C   vendor/symfony/translation/Exception/UnsupportedSchemeException.php        Í      A   vendor/symfony/translation/Exception/InvalidResourceException.php               G   vendor/symfony/translation/Exception/MissingRequiredOptionException.php        i       :   vendor/symfony/translation/Exception/ProviderException.php        y      ;   vendor/symfony/translation/Exception/ExceptionInterface.php        ?[      B   vendor/symfony/translation/Exception/NotFoundResourceException.php        GPؤ      A   vendor/symfony/translation/Exception/InvalidArgumentException.php	      	  >O      ?   vendor/symfony/translation/Exception/IncompleteDsnException.phpw      w  Hڤ      7   vendor/symfony/translation/Exception/LogicException.php        Ca      9   vendor/symfony/translation/Exception/RuntimeException.php        [N      )   vendor/symfony/translation/Translator.php;      ;  &Ze      "   vendor/symfony/translation/LICENSE,      ,  U      5   vendor/symfony/translation/TranslatorBagInterface.php        b      2   vendor/symfony/translation/TranslatableMessage.phpJ      J  .S      >   vendor/symfony/translation/CatalogueMetadataAwareInterface.php        ߵ_[      :   vendor/symfony/translation/Catalogue/AbstractOperation.php8      8  c      8   vendor/symfony/translation/Catalogue/TargetOperation.php}      }  ʉդ      7   vendor/symfony/translation/Catalogue/MergeOperation.phph
      h
  ,      ;   vendor/symfony/translation/Catalogue/OperationInterface.phpA      A  Ъ      @   vendor/symfony/translation/Reader/TranslationReaderInterface.php        0?
      7   vendor/symfony/translation/Reader/TranslationReader.php        `      /   vendor/symfony/translation/MessageCatalogue.php,'      ,'  +O      F   vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php        XI      H   vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php=      =  Z	      A   vendor/symfony/translation/DependencyInjection/TranslatorPass.php        ܤ`      K   vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.phpV      V  zΤ      H   vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php5	      5	        N   vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php        G      6   vendor/symfony/translation/DataCollectorTranslator.php              E   vendor/symfony/translation/DataCollector/TranslationDataCollector.php        3]      4   vendor/symfony/translation/Test/ProviderTestCase.php
      
  g      :   vendor/symfony/translation/Test/IncompleteDsnTestTrait.phpI      I  u0      ;   vendor/symfony/translation/Test/ProviderFactoryTestCase.php	      	  ZIM      C   vendor/symfony/translation/Test/AbstractProviderFactoryTestCase.php        |}      7   vendor/symfony/translation/Command/XliffLintCommand.phpD+      D+  Nb      7   vendor/symfony/translation/Command/TranslationTrait.phpU	      U	  G      =   vendor/symfony/translation/Command/TranslationLintCommand.phpE      E  9      =   vendor/symfony/translation/Command/TranslationPushCommand.php        5Y      =   vendor/symfony/translation/Command/TranslationPullCommand.php        汀      8   vendor/symfony/translation/Extractor/PhpAstExtractor.phpF      F  ;:E5      ;   vendor/symfony/translation/Extractor/ExtractorInterface.php        Ӎ      >   vendor/symfony/translation/Extractor/AbstractFileExtractor.php        s      7   vendor/symfony/translation/Extractor/ChainExtractor.php        DY      K   vendor/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.phpS      S  f      @   vendor/symfony/translation/Extractor/Visitor/AbstractVisitor.php        L      C   vendor/symfony/translation/Extractor/Visitor/TransMethodVisitor.php        aj/      B   vendor/symfony/translation/Extractor/Visitor/ConstraintVisitor.php?      ?  R*¤      0   vendor/symfony/translation/LoggingTranslator.phpG      G  a      1   vendor/symfony/translation/IdentityTranslator.php        [Q3      .   vendor/symfony/translation/Util/XliffUtils.php        DhJ      2   vendor/symfony/translation/Util/ArrayConverter.php        ik֤      ,   vendor/symfony/translation/TranslatorBag.php7      7  ?.      L   vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php7      7  \      E   vendor/symfony/translation/Provider/TranslationProviderCollection.phpy      y  ,6D      +   vendor/symfony/translation/Provider/Dsn.phpo      o  ]      ?   vendor/symfony/translation/Provider/AbstractProviderFactory.php        I<      9   vendor/symfony/translation/Provider/FilteringProvider.php          ?      @   vendor/symfony/translation/Provider/ProviderFactoryInterface.php              ;   vendor/symfony/translation/Provider/NullProviderFactory.phpK      K  =      9   vendor/symfony/translation/Provider/ProviderInterface.php        bV9      4   vendor/symfony/translation/Provider/NullProvider.php        .ha      5   vendor/symfony/translation/MetadataAwareInterface.php`      `  hH?      B   vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.phpa	      a	  |ⳤ      F   vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php9      9  >|zK      @   vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php_      _  d      @   vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.phpf      f  P      (   vendor/symfony/polyfill-mbstring/LICENSE,      ,  H      -   vendor/symfony/polyfill-mbstring/Mbstring.phpn      n  <      .   vendor/symfony/polyfill-mbstring/bootstrap.php          Nc)      0   vendor/symfony/polyfill-mbstring/bootstrap80.php'      '  	~
      '   vendor/symfony/polyfill-ctype/Ctype.php        8      %   vendor/symfony/polyfill-ctype/LICENSE,      ,        +   vendor/symfony/polyfill-ctype/bootstrap.php@      @  jQ9      -   vendor/symfony/polyfill-ctype/bootstrap80.phpr      r  F)      F   vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php        %      X   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.phpo     o c,      L   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.phpD5      D5        T   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php{      {  je      R   vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.phpD      D  'CԤ      /   vendor/symfony/polyfill-intl-normalizer/LICENSE,      ,  H      6   vendor/symfony/polyfill-intl-normalizer/Normalizer.phpd%      d%  u      5   vendor/symfony/polyfill-intl-normalizer/bootstrap.php        #p      7   vendor/symfony/polyfill-intl-normalizer/bootstrap80.php        ,      $   vendor/symfony/string/ByteString.php9      9  <UȤ      2   vendor/symfony/string/Slugger/SluggerInterface.php        ^      .   vendor/symfony/string/Slugger/AsciiSlugger.php        5      (   vendor/symfony/string/AbstractString.phpP      P        -   vendor/symfony/string/Resources/functions.phpT      T  0      <   vendor/symfony/string/Resources/data/wcswidth_table_zero.php]<      ]<  ?p      <   vendor/symfony/string/Resources/data/wcswidth_table_wide.php2      2  ?Y      &   vendor/symfony/string/TruncateMode.php        :      6   vendor/symfony/string/Exception/ExceptionInterface.phpQ      Q  $դ      <   vendor/symfony/string/Exception/InvalidArgumentException.php        e      4   vendor/symfony/string/Exception/RuntimeException.phpp      p  0ʤ         vendor/symfony/string/LICENSE,      ,  զ_Ϥ      '   vendor/symfony/string/UnicodeString.php<      <  Mu      )   vendor/symfony/string/CodePointString.php(      (  M      6   vendor/symfony/string/Inflector/InflectorInterface.phpC      C  Qcc      4   vendor/symfony/string/Inflector/SpanishInflector.php        ,      3   vendor/symfony/string/Inflector/FrenchInflector.phpK      K  n@      4   vendor/symfony/string/Inflector/EnglishInflector.phpF      F  Τ      $   vendor/symfony/string/LazyString.php[      [  @d      /   vendor/symfony/string/AbstractUnicodeString.phpq      q  =ڤ      >   vendor/symfony/translation-contracts/TranslatableInterface.php        j      ,   vendor/symfony/translation-contracts/LICENSE,      ,        =   vendor/symfony/translation-contracts/LocaleAwareInterface.phpl      l  h7F      <   vendor/symfony/translation-contracts/Test/TranslatorTest.php1A      1A  /QE      <   vendor/symfony/translation-contracts/TranslatorInterface.php
      
  \ܤ      8   vendor/symfony/translation-contracts/TranslatorTrait.php2      2  դ      !   vendor/symfony/console/Cursor.php        }k      /   vendor/symfony/console/Style/StyleInterface.php	      	  _a      -   vendor/symfony/console/Style/SymfonyStyle.php<      <        ,   vendor/symfony/console/Style/OutputStyle.php        L      @   vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php!      !  к*      -   vendor/symfony/console/Tester/TesterTrait.php        n      /   vendor/symfony/console/Tester/CommandTester.php	      	  a      9   vendor/symfony/console/Tester/CommandCompletionTester.php        q֤      3   vendor/symfony/console/Tester/ApplicationTester.phpw
      w
  gEGK      &   vendor/symfony/console/Application.php        %Kؤ      2   vendor/symfony/console/Interaction/Interaction.php        K      ?   vendor/symfony/console/CommandLoader/CommandLoaderInterface.php*      *  8      =   vendor/symfony/console/CommandLoader/FactoryCommandLoader.php        ]Bs      ?   vendor/symfony/console/CommandLoader/ContainerCommandLoader.phpZ      Z  |      B   vendor/symfony/console/Formatter/OutputFormatterStyleInterface.phpW      W  $}      >   vendor/symfony/console/Formatter/OutputFormatterStyleStack.php	      	  ߟ      8   vendor/symfony/console/Formatter/NullOutputFormatter.php        %      =   vendor/symfony/console/Formatter/NullOutputFormatterStyle.php        q.      F   vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php        0      9   vendor/symfony/console/Formatter/OutputFormatterStyle.php
      
        =   vendor/symfony/console/Formatter/OutputFormatterInterface.php        B5      4   vendor/symfony/console/Formatter/OutputFormatter.phpY$      Y$        /   vendor/symfony/console/Resources/completion.zsh              0   vendor/symfony/console/Resources/completion.fish        ܾ      4   vendor/symfony/console/Resources/bin/hiddeninput.exe $       $  v      0   vendor/symfony/console/Resources/completion.bash        zߤ          vendor/symfony/console/Color.php        .{j      ?   vendor/symfony/console/Exception/NamespaceNotFoundException.php        BLH      7   vendor/symfony/console/Exception/ExceptionInterface.php        l      ;   vendor/symfony/console/Exception/InvalidOptionException.php         !Ƥ      =   vendor/symfony/console/Exception/InvalidArgumentException.phpr      r  Uj      :   vendor/symfony/console/Exception/MissingInputException.php        Qg;      3   vendor/symfony/console/Exception/LogicException.php        SML      =   vendor/symfony/console/Exception/CommandNotFoundException.php        h      5   vendor/symfony/console/Exception/RuntimeException.php        *b      >   vendor/symfony/console/Exception/RunCommandFailedException.phps      s  ٤         vendor/symfony/console/LICENSE,      ,  U      /   vendor/symfony/console/Logger/ConsoleLogger.phpg      g        D   vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php              6   vendor/symfony/console/Messenger/RunCommandContext.php&      &  b7      =   vendor/symfony/console/Messenger/RunCommandMessageHandler.php6      6  h       6   vendor/symfony/console/Messenger/RunCommandMessage.php        mr      =   vendor/symfony/console/DataCollector/CommandDataCollector.php        1h      3   vendor/symfony/console/SignalRegistry/SignalMap.php        V      8   vendor/symfony/console/SignalRegistry/SignalRegistry.php'      '  n:      2   vendor/symfony/console/CI/GithubActionReporter.php)      )  &]      0   vendor/symfony/console/Completion/Suggestion.php<      <  <Mؖ      F   vendor/symfony/console/Completion/Output/CompletionOutputInterface.php        3O      @   vendor/symfony/console/Completion/Output/ZshCompletionOutput.php        yZ1      A   vendor/symfony/console/Completion/Output/FishCompletionOutput.php        w      A   vendor/symfony/console/Completion/Output/BashCompletionOutput.php        S      5   vendor/symfony/console/Completion/CompletionInput.php        5Ϥ      ;   vendor/symfony/console/Completion/CompletionSuggestions.phpF      F  $*      #   vendor/symfony/console/Terminal.phps      s  u      +   vendor/symfony/console/Attribute/Option.phph      h  R      -   vendor/symfony/console/Attribute/MapInput.php        ʤ      .   vendor/symfony/console/Attribute/AsCommand.php        5      -   vendor/symfony/console/Attribute/Argument.php        #e      B   vendor/symfony/console/Attribute/InteractiveAttributeInterface.php        \4      @   vendor/symfony/console/Attribute/Reflection/ReflectionMember.php
      
  HT      -   vendor/symfony/console/Attribute/Interact.php        ݔE֤      (   vendor/symfony/console/Attribute/Ask.php        FI      (   vendor/symfony/console/ConsoleEvents.php~      ~  ~6      +   vendor/symfony/console/Debug/CliRequest.phpP      P        0   vendor/symfony/console/Output/BufferedOutput.php(      (  CeM      .   vendor/symfony/console/Output/StreamOutput.phpl      l  J*ݤ      8   vendor/symfony/console/Output/ConsoleOutputInterface.php        /      6   vendor/symfony/console/Output/ConsoleSectionOutput.php$      $        ,   vendor/symfony/console/Output/NullOutput.php        mi      1   vendor/symfony/console/Output/OutputInterface.php
      
  9(      5   vendor/symfony/console/Output/TrimmedBufferOutput.php        0Oդ      (   vendor/symfony/console/Output/Output.php              /   vendor/symfony/console/Output/AnsiColorMode.php        f'      /   vendor/symfony/console/Output/ConsoleOutput.php        Ez      .   vendor/symfony/console/Command/HelpCommand.php
      
  #      0   vendor/symfony/console/Command/LockableTrait.php	      	  ն      .   vendor/symfony/console/Command/LazyCommand.php\      \  !+k      *   vendor/symfony/console/Command/Command.php]      ]  QJڤ      =   vendor/symfony/console/Command/SignalableCommandInterface.php        Z{      8   vendor/symfony/console/Command/DumpCompletionCommand.phpk      k  i      2   vendor/symfony/console/Command/CompleteCommand.php#      #  $g      3   vendor/symfony/console/Command/InvokableCommand.phpy!      y!  }g(      3   vendor/symfony/console/Command/TraceableCommand.php*      *  ބW      .   vendor/symfony/console/Command/ListCommand.php
      
  L      ,   vendor/symfony/console/Input/InputOption.php#!      #!  _3S      0   vendor/symfony/console/Input/InputDefinition.php.      .  O3t      +   vendor/symfony/console/Input/ArrayInput.php        ^      &   vendor/symfony/console/Input/Input.php        >q      .   vendor/symfony/console/Input/InputArgument.php        Yۤ      4   vendor/symfony/console/Input/InputAwareInterface.php@      @  n1      *   vendor/symfony/console/Input/ArgvInput.php4      4  M%      /   vendor/symfony/console/Input/InputInterface.php        Z|      9   vendor/symfony/console/Input/StreamableInputInterface.phpo      o  &      ,   vendor/symfony/console/Input/StringInput.php[
      [
  Ge6b      1   vendor/symfony/console/Helper/FormatterHelper.php        FN      (   vendor/symfony/console/Helper/Dumper.php        |      6   vendor/symfony/console/Helper/DebugFormatterHelper.php          3      +   vendor/symfony/console/Helper/TableCell.php        Pݤ      +   vendor/symfony/console/Helper/HelperSet.php-      -  gT      /   vendor/symfony/console/Helper/OutputWrapper.php        Ro      -   vendor/symfony/console/Helper/ProgressBar.phpQ      Q  膐Ȥ      *   vendor/symfony/console/Helper/TreeNode.php?	      ?	  gcפ      0   vendor/symfony/console/Helper/TableCellStyle.php        ä      7   vendor/symfony/console/Helper/SymfonyQuestionHelper.php        ]?Jڤ      5   vendor/symfony/console/Helper/TerminalInputHelper.phpt      t  S      1   vendor/symfony/console/Helper/HelperInterface.php        0t̤      0   vendor/symfony/console/Helper/QuestionHelper.phpQ      Q  4q      ,   vendor/symfony/console/Helper/TableStyle.php3      3  vV      0   vendor/symfony/console/Helper/TableSeparator.php        &      (   vendor/symfony/console/Helper/Helper.phpG      G  ~T      ,   vendor/symfony/console/Helper/TreeHelper.php^      ^        +   vendor/symfony/console/Helper/TreeStyle.php
	      
	  >8Z      3   vendor/symfony/console/Helper/ProgressIndicator.php        #      +   vendor/symfony/console/Helper/TableRows.php        p      2   vendor/symfony/console/Helper/DescriptorHelper.php9
      9
        '   vendor/symfony/console/Helper/Table.php        s	mǤ      /   vendor/symfony/console/Helper/ProcessHelper.php        ߤ      2   vendor/symfony/console/Helper/InputAwareHelper.php              3   vendor/symfony/console/SingleCommandApplication.php        JRmP      6   vendor/symfony/console/Event/ConsoleTerminateEvent.php        99      4   vendor/symfony/console/Event/ConsoleCommandEvent.php.      .        -   vendor/symfony/console/Event/ConsoleEvent.php        #      2   vendor/symfony/console/Event/ConsoleAlarmEvent.php~      ~  `      3   vendor/symfony/console/Event/ConsoleSignalEvent.php>      >  WX      2   vendor/symfony/console/Event/ConsoleErrorEvent.php        ǂ̤      6   vendor/symfony/console/EventListener/ErrorListener.phpq
      q
  h      8   vendor/symfony/console/Question/ConfirmationQuestion.php        -      ,   vendor/symfony/console/Question/Question.php        %K      2   vendor/symfony/console/Question/ChoiceQuestion.phpA      A        @   vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php)      )  <;      0   vendor/symfony/console/Descriptor/Descriptor.php`
      `
  %|      3   vendor/symfony/console/Descriptor/XmlDescriptor.php%      %  b1      9   vendor/symfony/console/Descriptor/DescriptorInterface.php3      3  :w      <   vendor/symfony/console/Descriptor/ApplicationDescription.phpj      j  9U      8   vendor/symfony/console/Descriptor/MarkdownDescriptor.php        :ؤ      4   vendor/symfony/console/Descriptor/JsonDescriptor.phpq      q  x꽤      4   vendor/symfony/console/Descriptor/TextDescriptor.php0      0  4<      '   vendor/symfony/polyfill-php86/Php86.php        	      ?   vendor/symfony/polyfill-php86/Resources/stubs/SortDirection.php        )	      %   vendor/symfony/polyfill-php86/LICENSE,      ,  9      +   vendor/symfony/polyfill-php86/bootstrap.php        r       -   vendor/symfony/polyfill-php86/bootstrap80.php~      ~  C,      ;   vendor/symfony/polyfill-php85/Resources/stubs/NoDiscard.php        z      I   vendor/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php        Þb      N   vendor/symfony/polyfill-php85/Resources/stubs/Filter/FilterFailedException.phpf      f  a:      H   vendor/symfony/polyfill-php85/Resources/stubs/Filter/FilterException.php[      [  ʤ      %   vendor/symfony/polyfill-php85/LICENSE,      ,  9      '   vendor/symfony/polyfill-php85/Php85.phpg      g  %֤      +   vendor/symfony/polyfill-php85/bootstrap.php        U0      -   vendor/symfony/polyfill-php85/bootstrap80.php        e      N   vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.phpX      X  Wߤ      A   vendor/symfony/polyfill-php83/Resources/stubs/DateObjectError.phpG      G  
.I      T   vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php^      ^  K      O   vendor/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.phpY      Y  Mߤ      @   vendor/symfony/polyfill-php83/Resources/stubs/DateRangeError.phpF      F  L;      ?   vendor/symfony/polyfill-php83/Resources/stubs/DateException.phpE      E        N   vendor/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.phpX      X  g      V   vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php`      `  6      B   vendor/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.phpH      H  <ܐ      :   vendor/symfony/polyfill-php83/Resources/stubs/Override.php        NsE      ;   vendor/symfony/polyfill-php83/Resources/stubs/DateError.php=      =  ˤ      '   vendor/symfony/polyfill-php83/Php83.php        m%̤      %   vendor/symfony/polyfill-php83/LICENSE,      ,  t=      -   vendor/symfony/polyfill-php83/bootstrap81.php        p$      +   vendor/symfony/polyfill-php83/bootstrap.php        Xg      -   vendor/symfony/polyfill-php83/bootstrap80.php        [gɤ      &   vendor/symfony/clock/Resources/now.php        9>9$      $   vendor/symfony/clock/NativeClock.php	      	  	6         vendor/symfony/clock/LICENSE,      ,  t=      '   vendor/symfony/clock/ClockInterface.php/      /   W      1   vendor/symfony/clock/Test/ClockSensitiveTrait.php        Ċ         vendor/symfony/clock/Clock.phpA	      A	   #      '   vendor/symfony/clock/MonotonicClock.phpt
      t
  o      "   vendor/symfony/clock/DatePoint.php        @Ф      (   vendor/symfony/clock/ClockAwareTrait.phpI      I  f/_      "   vendor/symfony/clock/MockClock.php        &          vendor/symfony/finder/Finder.php^      ^  
w         vendor/symfony/finder/Glob.php        m+G      9   vendor/symfony/finder/Exception/AccessDeniedException.php        cWޤ      >   vendor/symfony/finder/Exception/DirectoryNotFoundException.php        RI         vendor/symfony/finder/LICENSE,      ,  U      #   vendor/symfony/finder/Gitignore.php        k'      %   vendor/symfony/finder/SplFileInfo.phpW      W  ,q~      3   vendor/symfony/finder/Comparator/DateComparator.php        Y      5   vendor/symfony/finder/Comparator/NumberComparator.php
      
  f1      /   vendor/symfony/finder/Comparator/Comparator.php        'ͤ      A   vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php6      6  uD      /   vendor/symfony/finder/Iterator/LazyIterator.php        -9      =   vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php(      (   襤      =   vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.phpJ      J  p      :   vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpy      y        9   vendor/symfony/finder/Iterator/FileTypeFilterIterator.phpT      T  %H      5   vendor/symfony/finder/Iterator/PathFilterIterator.php        dސ{      3   vendor/symfony/finder/Iterator/SortableIterator.php        澺      ;   vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.phpn      n  كt      :   vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpP      P  gɤ      9   vendor/symfony/finder/Iterator/FilenameFilterIterator.phpQ      Q        ;   vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpb      b  ,      <   vendor/symfony/finder/Iterator/FilecontentFilterIterator.php        ~       7   vendor/symfony/finder/Iterator/CustomFilterIterator.php        #      .   vendor/symfony/process/PhpExecutableFinder.php	      	        &   vendor/symfony/process/InputStream.phpQ	      Q	  9O_      =   vendor/symfony/process/Exception/ProcessSignaledException.php        iʒ      7   vendor/symfony/process/Exception/ExceptionInterface.php        +      @   vendor/symfony/process/Exception/ProcessStartFailedException.php|      |  Y      =   vendor/symfony/process/Exception/InvalidArgumentException.php        ˅      >   vendor/symfony/process/Exception/RunProcessFailedException.php        U-.      =   vendor/symfony/process/Exception/ProcessTimedOutException.php        h      3   vendor/symfony/process/Exception/LogicException.php        W      ;   vendor/symfony/process/Exception/ProcessFailedException.php        3-      5   vendor/symfony/process/Exception/RuntimeException.php        >H         vendor/symfony/process/LICENSE,      ,  U      +   vendor/symfony/process/ExecutableFinder.php        M{      6   vendor/symfony/process/Messenger/RunProcessMessage.php        `      6   vendor/symfony/process/Messenger/RunProcessContext.php        AB      =   vendor/symfony/process/Messenger/RunProcessMessageHandler.php        xq      %   vendor/symfony/process/PhpProcess.php	      	  
      .   vendor/symfony/process/Pipes/AbstractPipes.php              /   vendor/symfony/process/Pipes/PipesInterface.php        \	      -   vendor/symfony/process/Pipes/WindowsPipes.php              *   vendor/symfony/process/Pipes/UnixPipes.php        Vℤ      (   vendor/symfony/process/PhpSubprocess.php        *kJ      '   vendor/symfony/process/ProcessUtils.php        0      "   vendor/symfony/process/Process.php        NC      ,   vendor/symfony/deprecation-contracts/LICENSE,      ,  K      1   vendor/symfony/deprecation-contracts/function.php        Oݤ      3   vendor/symfony/service-contracts/ResetInterface.php        񁒳      B   vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.phpM      M  jĤ      <   vendor/symfony/service-contracts/ContainerAwareInterface.php        ?>ۤ      (   vendor/symfony/service-contracts/LICENSE,      ,        =   vendor/symfony/service-contracts/ServiceProviderInterface.phpf      f  Τ      @   vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php        p>      <   vendor/symfony/service-contracts/Test/ServiceLocatorTest.php~      ~  Âs      ;   vendor/symfony/service-contracts/ServiceSubscriberTrait.php        r      @   vendor/symfony/service-contracts/Attribute/SubscribedService.php        Xѓ      7   vendor/symfony/service-contracts/Attribute/Required.php        e;Z      ?   vendor/symfony/service-contracts/ServiceCollectionInterface.phpr      r  K0      ?   vendor/symfony/service-contracts/ServiceSubscriberInterface.php
      
  Ŵ      8   vendor/symfony/service-contracts/ServiceLocatorTrait.php        v|      -   vendor/symfony/polyfill-php84/bootstrap82.php        Y a      '   vendor/symfony/polyfill-php84/Php84.phpv=      v=  [CT      D   vendor/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php        Է      <   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php
      
  @&      >   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.phpR      R  ?f      ;   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php        l8      :   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php        }      ;   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php        Q=/      ;   vendor/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.phpO      O  tj      >   vendor/symfony/polyfill-php84/Resources/stubs/RoundingMode.php\      \  <H      <   vendor/symfony/polyfill-php84/Resources/stubs/Deprecated.phpD      D  Ž      8   vendor/symfony/polyfill-php84/Resources/RoundingMode.php              6   vendor/symfony/polyfill-php84/Resources/Deprecated.php        ^6      %   vendor/symfony/polyfill-php84/LICENSE,      ,         +   vendor/symfony/polyfill-php84/bootstrap.php        \      -   vendor/symfony/polyfill-php84/bootstrap80.php        -      4   vendor/voku/portable-ascii/src/voku/helper/ASCII.php        Er>      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c8.php        t͟
      8   vendor/voku/portable-ascii/src/voku/helper/data/x025.php*      *  |      8   vendor/voku/portable-ascii/src/voku/helper/data/x06b.php        R@      8   vendor/voku/portable-ascii/src/voku/helper/data/x010.php              8   vendor/voku/portable-ascii/src/voku/helper/data/x023.php        CJy      8   vendor/voku/portable-ascii/src/voku/helper/data/x068.phpF      F  hKf      8   vendor/voku/portable-ascii/src/voku/helper/data/x04d.php        2m[6      8   vendor/voku/portable-ascii/src/voku/helper/data/x05d.phpB      B        8   vendor/voku/portable-ascii/src/voku/helper/data/x00f.php        _c^H      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c9.phpv      v  2xl      F   vendor/voku/portable-ascii/src/voku/helper/data/ascii_by_languages.phpi     i 7zO      8   vendor/voku/portable-ascii/src/voku/helper/data/x02a.php        ä      8   vendor/voku/portable-ascii/src/voku/helper/data/x01f.phpP      P  c      8   vendor/voku/portable-ascii/src/voku/helper/data/x021.php        HrBt      8   vendor/voku/portable-ascii/src/voku/helper/data/x053.php        ]p      8   vendor/voku/portable-ascii/src/voku/helper/data/x1d6.php        :l_      8   vendor/voku/portable-ascii/src/voku/helper/data/x0bf.php	      	  rI      8   vendor/voku/portable-ascii/src/voku/helper/data/x01d.php        ?      8   vendor/voku/portable-ascii/src/voku/helper/data/x078.php,      ,  0      8   vendor/voku/portable-ascii/src/voku/helper/data/x031.php+      +  `Ф      8   vendor/voku/portable-ascii/src/voku/helper/data/x005.php        q䈋      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c3.phps	      s	  K'      8   vendor/voku/portable-ascii/src/voku/helper/data/x07d.phpJ      J  zDP      8   vendor/voku/portable-ascii/src/voku/helper/data/x063.php4      4  c      8   vendor/voku/portable-ascii/src/voku/helper/data/x09c.php7      7  E      8   vendor/voku/portable-ascii/src/voku/helper/data/x050.phpN      N        8   vendor/voku/portable-ascii/src/voku/helper/data/x0a4.phpc      c  |      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b9.phpd      d  ؤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x02c.php        H      8   vendor/voku/portable-ascii/src/voku/helper/data/x00a.php'      '  _,      8   vendor/voku/portable-ascii/src/voku/helper/data/x0ca.php	      	  +8      8   vendor/voku/portable-ascii/src/voku/helper/data/x00c.php        +L      8   vendor/voku/portable-ascii/src/voku/helper/data/x086.php
      
  F2Q      8   vendor/voku/portable-ascii/src/voku/helper/data/x013.php        tL      8   vendor/voku/portable-ascii/src/voku/helper/data/x003.php1      1  jyȤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x00e.php
      
  Աz      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c0.php        ~      8   vendor/voku/portable-ascii/src/voku/helper/data/x05a.php          0      8   vendor/voku/portable-ascii/src/voku/helper/data/x0be.php        GH      8   vendor/voku/portable-ascii/src/voku/helper/data/x0fd.phpU      U  m ۤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x020.php        y      8   vendor/voku/portable-ascii/src/voku/helper/data/x077.phpG      G        8   vendor/voku/portable-ascii/src/voku/helper/data/x0a3.php        ǗΤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x06c.php'      '  D      8   vendor/voku/portable-ascii/src/voku/helper/data/x072.php7      7  ž,      8   vendor/voku/portable-ascii/src/voku/helper/data/x1d4.phpf      f  e      8   vendor/voku/portable-ascii/src/voku/helper/data/x051.phpQ      Q  w$ͤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x0cd.php        3$z]      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b1.php        AR¤      8   vendor/voku/portable-ascii/src/voku/helper/data/x061.php:      :        8   vendor/voku/portable-ascii/src/voku/helper/data/x08c.php        ˛      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d5.phpL      L  E@      8   vendor/voku/portable-ascii/src/voku/helper/data/x064.php3      3  73      8   vendor/voku/portable-ascii/src/voku/helper/data/x0fb.php        bΞ      8   vendor/voku/portable-ascii/src/voku/helper/data/x000.phps      s  :`,      8   vendor/voku/portable-ascii/src/voku/helper/data/x09d.php        
'ݤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x060.php&      &         8   vendor/voku/portable-ascii/src/voku/helper/data/x0b0.php        Jص      8   vendor/voku/portable-ascii/src/voku/helper/data/x1d5.php        D      8   vendor/voku/portable-ascii/src/voku/helper/data/x05f.php8      8  ab      8   vendor/voku/portable-ascii/src/voku/helper/data/x018.php        b`i      J   vendor/voku/portable-ascii/src/voku/helper/data/ascii_language_max_key.php9      9  8      8   vendor/voku/portable-ascii/src/voku/helper/data/x030.phpM      M   E<      8   vendor/voku/portable-ascii/src/voku/helper/data/x002.php?      ?  4      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b2.phpL      L        8   vendor/voku/portable-ascii/src/voku/helper/data/x0fa.phpD      D  E      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d2.phpx      x  4ۤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x073.php*      *  Y      8   vendor/voku/portable-ascii/src/voku/helper/data/x0ff.php        7{M      8   vendor/voku/portable-ascii/src/voku/helper/data/x071.phpB      B  Y      8   vendor/voku/portable-ascii/src/voku/helper/data/x088.php)      )  s+      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d4.php        r;*      8   vendor/voku/portable-ascii/src/voku/helper/data/x0ae.php	      	  ޕ"       8   vendor/voku/portable-ascii/src/voku/helper/data/x057.php        .,      8   vendor/voku/portable-ascii/src/voku/helper/data/x094.php9      9  JHܤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x017.phpl      l  >+Ť      8   vendor/voku/portable-ascii/src/voku/helper/data/x08e.php7      7  DG      8   vendor/voku/portable-ascii/src/voku/helper/data/x09b.php3      3  Q      8   vendor/voku/portable-ascii/src/voku/helper/data/x028.php	      	  )'@      8   vendor/voku/portable-ascii/src/voku/helper/data/x06e.php$      $  'Ҥ      8   vendor/voku/portable-ascii/src/voku/helper/data/x096.php              8   vendor/voku/portable-ascii/src/voku/helper/data/x0cf.phpm      m  \q@      8   vendor/voku/portable-ascii/src/voku/helper/data/x0bd.php        __/      8   vendor/voku/portable-ascii/src/voku/helper/data/x033.php        m%\      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b7.php        i/      8   vendor/voku/portable-ascii/src/voku/helper/data/x091.php3      3  gŤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d0.phpf      f  wTF      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d3.phpe      e  oKnڤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x054.php        Ф      8   vendor/voku/portable-ascii/src/voku/helper/data/x085.php          Q      8   vendor/voku/portable-ascii/src/voku/helper/data/x059.php(      (  zv      8   vendor/voku/portable-ascii/src/voku/helper/data/x0ac.phpi      i  [       8   vendor/voku/portable-ascii/src/voku/helper/data/x075.phpG      G  7Τ      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c2.phpj      j  9      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b4.php              8   vendor/voku/portable-ascii/src/voku/helper/data/x07e.phpN      N  B
      8   vendor/voku/portable-ascii/src/voku/helper/data/x093.php>      >   h      8   vendor/voku/portable-ascii/src/voku/helper/data/x069.phpE      E  @Z      8   vendor/voku/portable-ascii/src/voku/helper/data/x087.php-      -        8   vendor/voku/portable-ascii/src/voku/helper/data/x0ce.phph      h  MUq      8   vendor/voku/portable-ascii/src/voku/helper/data/x055.php        Ub'      8   vendor/voku/portable-ascii/src/voku/helper/data/x016.php:      :  ~      8   vendor/voku/portable-ascii/src/voku/helper/data/x0fe.php        G      8   vendor/voku/portable-ascii/src/voku/helper/data/x099.php               8   vendor/voku/portable-ascii/src/voku/helper/data/x0b6.php	      	  *      8   vendor/voku/portable-ascii/src/voku/helper/data/x026.php         =1      8   vendor/voku/portable-ascii/src/voku/helper/data/x056.php        EC      8   vendor/voku/portable-ascii/src/voku/helper/data/x024.php        oa      8   vendor/voku/portable-ascii/src/voku/helper/data/x007.php(      (  89      8   vendor/voku/portable-ascii/src/voku/helper/data/x027.php        H      8   vendor/voku/portable-ascii/src/voku/helper/data/x080.php/      /  Ug      8   vendor/voku/portable-ascii/src/voku/helper/data/x022.php        (O3      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c1.php        R]      8   vendor/voku/portable-ascii/src/voku/helper/data/x029.php        I      8   vendor/voku/portable-ascii/src/voku/helper/data/x05e.php@      @  P      8   vendor/voku/portable-ascii/src/voku/helper/data/x083.php'      '  l      8   vendor/voku/portable-ascii/src/voku/helper/data/x098.php)      )  w      8   vendor/voku/portable-ascii/src/voku/helper/data/x079.php        |_7      8   vendor/voku/portable-ascii/src/voku/helper/data/x089.php        k      8   vendor/voku/portable-ascii/src/voku/helper/data/x076.php#      #  x	      8   vendor/voku/portable-ascii/src/voku/helper/data/x06d.php/      /        8   vendor/voku/portable-ascii/src/voku/helper/data/x082.php-      -  B`l      8   vendor/voku/portable-ascii/src/voku/helper/data/x1d7.phpA      A   B      8   vendor/voku/portable-ascii/src/voku/helper/data/x0a2.php        )٤      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d1.php        EQ~      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c5.php        vKq1      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b8.phpn      n  ]z      8   vendor/voku/portable-ascii/src/voku/helper/data/x00b.php2      2  p)      8   vendor/voku/portable-ascii/src/voku/helper/data/x08b.php'      '  *'3      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b5.php;	      ;	  1      8   vendor/voku/portable-ascii/src/voku/helper/data/x04e.php*      *  Rq      8   vendor/voku/portable-ascii/src/voku/helper/data/x052.php2      2  v      8   vendor/voku/portable-ascii/src/voku/helper/data/x065.php"      "  )D6      8   vendor/voku/portable-ascii/src/voku/helper/data/x05c.php        [~      8   vendor/voku/portable-ascii/src/voku/helper/data/x095.phpC      C  }XǤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x081.phpE      E  Z      8   vendor/voku/portable-ascii/src/voku/helper/data/x0fc.php        }~      8   vendor/voku/portable-ascii/src/voku/helper/data/x04f.php        n      8   vendor/voku/portable-ascii/src/voku/helper/data/x009.php              8   vendor/voku/portable-ascii/src/voku/helper/data/x02f.php        &      8   vendor/voku/portable-ascii/src/voku/helper/data/x06a.phpF      F  MGP      8   vendor/voku/portable-ascii/src/voku/helper/data/x00d.php'      '  O      8   vendor/voku/portable-ascii/src/voku/helper/data/x0bc.phpg      g  X      8   vendor/voku/portable-ascii/src/voku/helper/data/x015.php        kFi      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c4.php	      	        8   vendor/voku/portable-ascii/src/voku/helper/data/x0af.php	      	  6w      8   vendor/voku/portable-ascii/src/voku/helper/data/x004.php        U9      8   vendor/voku/portable-ascii/src/voku/helper/data/x032.php        A*Sܤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x0b3.php        @M      8   vendor/voku/portable-ascii/src/voku/helper/data/x09e.php        G      8   vendor/voku/portable-ascii/src/voku/helper/data/x0bb.php~      ~  ä      8   vendor/voku/portable-ascii/src/voku/helper/data/x092.php,      ,  ^W      8   vendor/voku/portable-ascii/src/voku/helper/data/x067.php        NG      8   vendor/voku/portable-ascii/src/voku/helper/data/x0ad.php              8   vendor/voku/portable-ascii/src/voku/helper/data/x07f.php<      <        8   vendor/voku/portable-ascii/src/voku/helper/data/x07c.php;      ;  kˤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x08a.php+      +  OUӤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x014.php        -	      8   vendor/voku/portable-ascii/src/voku/helper/data/x05b.php@      @  3      8   vendor/voku/portable-ascii/src/voku/helper/data/x1f1.phpM      M  ޑ7      8   vendor/voku/portable-ascii/src/voku/helper/data/x058.phpJ      J  z>      8   vendor/voku/portable-ascii/src/voku/helper/data/x070.phpY      Y  80      8   vendor/voku/portable-ascii/src/voku/helper/data/x011.php5      5  9      8   vendor/voku/portable-ascii/src/voku/helper/data/x09a.php        Uk      8   vendor/voku/portable-ascii/src/voku/helper/data/x0a0.phpP      P  5SC      8   vendor/voku/portable-ascii/src/voku/helper/data/x062.php        ͤ      8   vendor/voku/portable-ascii/src/voku/helper/data/x0ba.php        #      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c6.php        `      8   vendor/voku/portable-ascii/src/voku/helper/data/x06f.php.      .  4      8   vendor/voku/portable-ascii/src/voku/helper/data/x02e.php=      =  K      8   vendor/voku/portable-ascii/src/voku/helper/data/x0c7.php        @      8   vendor/voku/portable-ascii/src/voku/helper/data/x0cb.php	      	  Id      8   vendor/voku/portable-ascii/src/voku/helper/data/x0f9.php        
~fI      8   vendor/voku/portable-ascii/src/voku/helper/data/x07b.phpA      A  O      8   vendor/voku/portable-ascii/src/voku/helper/data/x08f.php/      /        8   vendor/voku/portable-ascii/src/voku/helper/data/x01e.php              8   vendor/voku/portable-ascii/src/voku/helper/data/x074.php\      \  aA      8   vendor/voku/portable-ascii/src/voku/helper/data/x066.phpI      I  ?S      8   vendor/voku/portable-ascii/src/voku/helper/data/x090.php        !       8   vendor/voku/portable-ascii/src/voku/helper/data/x09f.php        -(*      8   vendor/voku/portable-ascii/src/voku/helper/data/x084.php*      *  I      8   vendor/voku/portable-ascii/src/voku/helper/data/x08d.php          9      =   vendor/voku/portable-ascii/src/voku/helper/data/ascii_ord.php        F_      8   vendor/voku/portable-ascii/src/voku/helper/data/x012.php        K      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d7.php        ң      8   vendor/voku/portable-ascii/src/voku/helper/data/x001.php7      7  >{8      8   vendor/voku/portable-ascii/src/voku/helper/data/x0a1.phpy      y  t      8   vendor/voku/portable-ascii/src/voku/helper/data/x0cc.php        !>      8   vendor/voku/portable-ascii/src/voku/helper/data/x097.php'      '  +      8   vendor/voku/portable-ascii/src/voku/helper/data/x07a.phpA      A  _&0      M   vendor/voku/portable-ascii/src/voku/helper/data/ascii_extras_by_languages.phprG      rG  31      8   vendor/voku/portable-ascii/src/voku/helper/data/x006.php        :~=L      8   vendor/voku/portable-ascii/src/voku/helper/data/x0d6.php        8;      &   vendor/voku/portable-ascii/LICENSE.txt"      "  -D      5   vendor/doctrine/inflector/src/CachedWordInflector.php        [_i      2   vendor/doctrine/inflector/src/InflectorFactory.php        ;:3      @   vendor/doctrine/inflector/src/Rules/Turkish/InflectorFactory.php        
      ;   vendor/doctrine/inflector/src/Rules/Turkish/Uninflected.phpg      g  >Yε      ;   vendor/doctrine/inflector/src/Rules/Turkish/Inflectible.php        JȤ      5   vendor/doctrine/inflector/src/Rules/Turkish/Rules.phpj      j  ڃ      H   vendor/doctrine/inflector/src/Rules/NorwegianBokmal/InflectorFactory.php        ;0      C   vendor/doctrine/inflector/src/Rules/NorwegianBokmal/Uninflected.phpd      d  ٮd      C   vendor/doctrine/inflector/src/Rules/NorwegianBokmal/Inflectible.php        {<      =   vendor/doctrine/inflector/src/Rules/NorwegianBokmal/Rules.phpr      r  T      /   vendor/doctrine/inflector/src/Rules/Ruleset.php	      	  fP      B   vendor/doctrine/inflector/src/Rules/Esperanto/InflectorFactory.php        q#      =   vendor/doctrine/inflector/src/Rules/Esperanto/Uninflected.php        iz      =   vendor/doctrine/inflector/src/Rules/Esperanto/Inflectible.php        :[F      7   vendor/doctrine/inflector/src/Rules/Esperanto/Rules.phpl      l  ņ8A      0   vendor/doctrine/inflector/src/Rules/Patterns.phpZ      Z  $4#      ,   vendor/doctrine/inflector/src/Rules/Word.php&      &  KHW      5   vendor/doctrine/inflector/src/Rules/Substitutions.php\      \  m      6   vendor/doctrine/inflector/src/Rules/Transformation.php        '      @   vendor/doctrine/inflector/src/Rules/Spanish/InflectorFactory.php        [      ;   vendor/doctrine/inflector/src/Rules/Spanish/Uninflected.phpg      g  @O      ;   vendor/doctrine/inflector/src/Rules/Spanish/Inflectible.php9      9  ͕      5   vendor/doctrine/inflector/src/Rules/Spanish/Rules.phpj      j  j?      @   vendor/doctrine/inflector/src/Rules/Italian/InflectorFactory.php        ɷ#      ;   vendor/doctrine/inflector/src/Rules/Italian/Uninflected.php        eҤ      ;   vendor/doctrine/inflector/src/Rules/Italian/Inflectible.php
!      
!  $+      5   vendor/doctrine/inflector/src/Rules/Italian/Rules.phpj      j  ^      C   vendor/doctrine/inflector/src/Rules/Portuguese/InflectorFactory.php        3      >   vendor/doctrine/inflector/src/Rules/Portuguese/Uninflected.php        n*      >   vendor/doctrine/inflector/src/Rules/Portuguese/Inflectible.php        @Yo      8   vendor/doctrine/inflector/src/Rules/Portuguese/Rules.phpm      m  !<ۘ      ?   vendor/doctrine/inflector/src/Rules/French/InflectorFactory.php        ~2      :   vendor/doctrine/inflector/src/Rules/French/Uninflected.phpW      W  #      :   vendor/doctrine/inflector/src/Rules/French/Inflectible.phpZ      Z  ,zR      4   vendor/doctrine/inflector/src/Rules/French/Rules.phpi      i  ld      7   vendor/doctrine/inflector/src/Rules/Transformations.php        h%AS      4   vendor/doctrine/inflector/src/Rules/Substitution.php        Τ      /   vendor/doctrine/inflector/src/Rules/Pattern.php        a_      @   vendor/doctrine/inflector/src/Rules/English/InflectorFactory.php        Y?      ;   vendor/doctrine/inflector/src/Rules/English/Uninflected.php        &'      ;   vendor/doctrine/inflector/src/Rules/English/Inflectible.php.      .  ԟ      5   vendor/doctrine/inflector/src/Rules/English/Rules.phpj      j  D      :   vendor/doctrine/inflector/src/LanguageInflectorFactory.php%      %  x뷤      +   vendor/doctrine/inflector/src/Inflector.php02      02        /   vendor/doctrine/inflector/src/WordInflector.php          ##l      *   vendor/doctrine/inflector/src/Language.php        w3      3   vendor/doctrine/inflector/src/NoopWordInflector.php          Iˤ      2   vendor/doctrine/inflector/src/RulesetInflector.phpK      K  ed      A   vendor/doctrine/inflector/src/GenericLanguageInflectorFactory.php        ;      !   vendor/doctrine/inflector/LICENSE)      )  9ޤ      8   vendor/illuminate/conditionable/HigherOrderWhenProxy.php        $      8   vendor/illuminate/conditionable/Traits/Conditionable.php              ,   vendor/illuminate/contracts/Mail/Factory.php        _+      -   vendor/illuminate/contracts/Mail/Mailable.php        Ϥ      +   vendor/illuminate/contracts/Mail/Mailer.php              /   vendor/illuminate/contracts/Mail/Attachable.php          @</      .   vendor/illuminate/contracts/Mail/MailQueue.php        !`4      -   vendor/illuminate/contracts/Cache/Factory.php        cU      0   vendor/illuminate/contracts/Cache/Repository.php        ͓]      2   vendor/illuminate/contracts/Cache/LockProvider.php5      5  o@      *   vendor/illuminate/contracts/Cache/Lock.phpz      z  ܤ      +   vendor/illuminate/contracts/Cache/Store.php#      #  @      3   vendor/illuminate/contracts/Cache/CanFlushLocks.phpm      m  ۤ      :   vendor/illuminate/contracts/Cache/LockTimeoutException.phpv       v   
      D   vendor/illuminate/contracts/Container/BindingResolutionException.php          k      6   vendor/illuminate/contracts/Container/SelfBuilding.php}       }   &0      =   vendor/illuminate/contracts/Container/ContextualAttribute.php[       [   q}      3   vendor/illuminate/contracts/Container/Container.php        @X      E   vendor/illuminate/contracts/Container/CircularDependencyException.php          .      B   vendor/illuminate/contracts/Container/ContextualBindingBuilder.php}      }        >   vendor/illuminate/contracts/Foundation/CachesConfiguration.php        .      6   vendor/illuminate/contracts/Foundation/Application.php        R&      7   vendor/illuminate/contracts/Foundation/CachesRoutes.php^      ^        :   vendor/illuminate/contracts/Foundation/MaintenanceMode.php        b)      <   vendor/illuminate/contracts/Foundation/ExceptionRenderer.php          Eސ      7   vendor/illuminate/contracts/Log/ContextLogProcessor.php                H   vendor/illuminate/contracts/Session/Middleware/AuthenticatesSessions.phpf       f   鲤      /   vendor/illuminate/contracts/Session/Session.php        9)      2   vendor/illuminate/contracts/Concurrency/Driver.php        K      .   vendor/illuminate/contracts/Hashing/Hasher.php        <K      6   vendor/illuminate/contracts/Bus/QueueingDispatcher.php        *&      .   vendor/illuminate/contracts/Bus/Dispatcher.php        Pkxݤ      2   vendor/illuminate/contracts/Filesystem/Factory.php        ZV      0   vendor/illuminate/contracts/Filesystem/Cloud.php           f      ?   vendor/illuminate/contracts/Filesystem/LockTimeoutException.php{       {   q      5   vendor/illuminate/contracts/Filesystem/Filesystem.php        ZX      @   vendor/illuminate/contracts/Filesystem/FileNotFoundException.php|       |   1įd      .   vendor/illuminate/contracts/Cookie/Factory.php        ~      6   vendor/illuminate/contracts/Cookie/QueueingFactory.phpk      k  Fz      1   vendor/illuminate/contracts/Config/Repository.php        jBä      ,   vendor/illuminate/contracts/View/Factory.php        !ʤ      +   vendor/illuminate/contracts/View/Engine.php	      	  _4      =   vendor/illuminate/contracts/View/ViewCompilationException.phpy       y   xt+פ      )   vendor/illuminate/contracts/View/View.php        Q      ,   vendor/illuminate/contracts/Auth/Factory.php        ;Ť      0   vendor/illuminate/contracts/Auth/Access/Gate.php        H      8   vendor/illuminate/contracts/Auth/Access/Authorizable.php0      0  :      2   vendor/illuminate/contracts/Auth/StatefulGuard.php        V_      E   vendor/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.phpc       c   4v      1   vendor/illuminate/contracts/Auth/UserProvider.php$      $  O)      :   vendor/illuminate/contracts/Auth/PasswordBrokerFactory.php        mM      4   vendor/illuminate/contracts/Auth/Authenticatable.phpI      I  }D      4   vendor/illuminate/contracts/Auth/MustVerifyEmail.php%      %  'U      5   vendor/illuminate/contracts/Auth/CanResetPassword.php        y<(      *   vendor/illuminate/contracts/Auth/Guard.phpL      L  !b'      3   vendor/illuminate/contracts/Auth/PasswordBroker.php	      	  +r      6   vendor/illuminate/contracts/Auth/SupportsBasicAuth.php{      {  ycf      4   vendor/illuminate/contracts/Pagination/Paginator.php
      
  [      ?   vendor/illuminate/contracts/Pagination/LengthAwarePaginator.php              :   vendor/illuminate/contracts/Pagination/CursorPaginator.php6      6  D%      8   vendor/illuminate/contracts/Routing/BindingRegistrar.php        A6      3   vendor/illuminate/contracts/Routing/UrlRoutable.phpq      q  'ݤ      1   vendor/illuminate/contracts/Routing/Registrar.php
      
        4   vendor/illuminate/contracts/Routing/UrlGenerator.php        ;      7   vendor/illuminate/contracts/Routing/ResponseFactory.php        vI      +   vendor/illuminate/contracts/Http/Kernel.phpp      p  $      2   vendor/illuminate/contracts/Validation/Factory.php        9{      4   vendor/illuminate/contracts/Validation/Validator.phpm      m  D}ۤ      @   vendor/illuminate/contracts/Validation/UncompromisedVerifier.php        GL      :   vendor/illuminate/contracts/Validation/CompilableRules.phpx      x        =   vendor/illuminate/contracts/Validation/ValidatorAwareRule.php<      <  ΅      /   vendor/illuminate/contracts/Validation/Rule.php        7:      7   vendor/illuminate/contracts/Validation/ImplicitRule.php                9   vendor/illuminate/contracts/Validation/ValidationRule.php        c      8   vendor/illuminate/contracts/Validation/DataAwareRule.php          qܤ      8   vendor/illuminate/contracts/Validation/InvokableRule.php        R#      @   vendor/illuminate/contracts/Validation/ValidatesWhenResolved.php          >OG      ;   vendor/illuminate/contracts/Encryption/EncryptException.php          jJ      :   vendor/illuminate/contracts/Encryption/StringEncrypter.phpQ      Q  ד;      4   vendor/illuminate/contracts/Encryption/Encrypter.php$      $  {)      ;   vendor/illuminate/contracts/Encryption/DecryptException.php           2v      :   vendor/illuminate/contracts/Support/DeferrableProvider.php          Tܤ      1   vendor/illuminate/contracts/Support/Arrayable.php        PT      A   vendor/illuminate/contracts/Support/DeferringDisplayableValue.php               2   vendor/illuminate/contracts/Support/MessageBag.php        g      0   vendor/illuminate/contracts/Support/Htmlable.php          뤏#      D   vendor/illuminate/contracts/Support/CanBeEscapedWhenCastToString.phpI      I  ŝ_0      5   vendor/illuminate/contracts/Support/ValidatedData.php                2   vendor/illuminate/contracts/Support/Renderable.php          _ޤ      3   vendor/illuminate/contracts/Support/Responsable.php2      2  e      0   vendor/illuminate/contracts/Support/Jsonable.php          RQؤ      7   vendor/illuminate/contracts/Support/MessageProvider.php          A       3   vendor/illuminate/contracts/Support/HasOnceHash.php        2F      8   vendor/illuminate/contracts/Database/ModelIdentifier.php	      	  >-&      ?   vendor/illuminate/contracts/Database/LostConnectionDetector.php8      8  Aݤ      A   vendor/illuminate/contracts/Database/ConcurrencyErrorDetector.phpj      j  Ԥ      B   vendor/illuminate/contracts/Database/Query/ConditionExpression.phpl       l   +bc      6   vendor/illuminate/contracts/Database/Query/Builder.php          )(Z      9   vendor/illuminate/contracts/Database/Query/Expression.php7      7  y)      >   vendor/illuminate/contracts/Database/Events/MigrationEvent.php\       \   ;ä      L   vendor/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php        s      A   vendor/illuminate/contracts/Database/Eloquent/CastsAttributes.php        >H      :   vendor/illuminate/contracts/Database/Eloquent/Castable.php              N   vendor/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php          L-¤      J   vendor/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php        4]      L   vendor/illuminate/contracts/Database/Eloquent/ComparesCastableAttributes.php        GE?      9   vendor/illuminate/contracts/Database/Eloquent/Builder.php.      .  _      H   vendor/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php        S      6   vendor/illuminate/contracts/Process/InvokedProcess.php        ܤ      5   vendor/illuminate/contracts/Process/ProcessResult.phpv      v  Kz      1   vendor/illuminate/contracts/Events/Dispatcher.php          y      D   vendor/illuminate/contracts/Events/ShouldHandleEventsAfterCommit.phpb       b   `x      @   vendor/illuminate/contracts/Events/ShouldDispatchAfterCommit.php^       ^   1A      6   vendor/illuminate/contracts/Debug/ExceptionHandler.php        D      4   vendor/illuminate/contracts/Debug/ShouldntReport.phpR       R   ֤      1   vendor/illuminate/contracts/Pipeline/Pipeline.php        Twf      ,   vendor/illuminate/contracts/Pipeline/Hub.php&      &  jB      -   vendor/illuminate/contracts/Redis/Factory.php        l}      =   vendor/illuminate/contracts/Redis/LimiterTimeoutException.phpy       y   c{      0   vendor/illuminate/contracts/Redis/Connection.php              /   vendor/illuminate/contracts/Redis/Connector.php|      |        =   vendor/illuminate/contracts/Queue/EntityNotFoundException.php        ArI      -   vendor/illuminate/contracts/Queue/Factory.php        8L      4   vendor/illuminate/contracts/Queue/ShouldBeUnique.phpR       R   ql      9   vendor/illuminate/contracts/Queue/PreparesForDispatch.php          NB      -   vendor/illuminate/contracts/Queue/Monitor.php`      `  ss      4   vendor/illuminate/contracts/Queue/ClearableQueue.php          	      +   vendor/illuminate/contracts/Queue/Queue.php        {      <   vendor/illuminate/contracts/Queue/ShouldQueueAfterCommit.phpn       n         5   vendor/illuminate/contracts/Queue/QueueableEntity.php        Y      C   vendor/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.phpx       x   0Q      3   vendor/illuminate/contracts/Queue/Interruptible.php          g      1   vendor/illuminate/contracts/Queue/ShouldQueue.phpO       O   at      4   vendor/illuminate/contracts/Queue/EntityResolver.php        Zɤ      )   vendor/illuminate/contracts/Queue/Job.php        d      9   vendor/illuminate/contracts/Queue/QueueableCollection.php        U7{      7   vendor/illuminate/contracts/Queue/ShouldBeEncrypted.phpU       U   +      5   vendor/illuminate/contracts/Notifications/Factory.php        `3      8   vendor/illuminate/contracts/Notifications/Dispatcher.php              4   vendor/illuminate/contracts/Broadcasting/Factory.php!      !  zΫ      9   vendor/illuminate/contracts/Broadcasting/ShouldRescue.phpW       W   :I3      ;   vendor/illuminate/contracts/Broadcasting/ShouldBeUnique.phpY       Y   ~      @   vendor/illuminate/contracts/Broadcasting/HasBroadcastChannel.php        vc7R      8   vendor/illuminate/contracts/Broadcasting/Broadcaster.php;      ;  m$!      <   vendor/illuminate/contracts/Broadcasting/ShouldBroadcast.php'      '  6      ?   vendor/illuminate/contracts/Broadcasting/ShouldBroadcastNow.phpu       u   G      2   vendor/illuminate/contracts/Translation/Loader.php@      @  -      6   vendor/illuminate/contracts/Translation/Translator.php        px      ?   vendor/illuminate/contracts/Translation/HasLocalePreference.php          p      5   vendor/illuminate/contracts/JsonSchema/JsonSchema.php              3   vendor/illuminate/contracts/Console/Application.php        \.K      >   vendor/illuminate/contracts/Console/PromptsForMissingInput.php\       \   S      .   vendor/illuminate/contracts/Console/Kernel.php        t      2   vendor/illuminate/contracts/Console/Isolatable.phpP       P   kdO      ,   vendor/illuminate/support/ValidatedInput.php|      |        #   vendor/illuminate/support/Sleep.php0      0  SjϤ      (   vendor/illuminate/support/Pluralizer.php\      \  y      &   vendor/illuminate/support/Optional.php
      
  K      /   vendor/illuminate/support/Facades/Validator.php(      (  ҪX      ,   vendor/illuminate/support/Facades/Facade.phpr$      r$  ~#      +   vendor/illuminate/support/Facades/Event.phpJ      J        -   vendor/illuminate/support/Facades/Request.phpE/      E/  X&      -   vendor/illuminate/support/Facades/Context.php        m>      ,   vendor/illuminate/support/Facades/Schema.php        =      *   vendor/illuminate/support/Facades/Vite.php
      
        .   vendor/illuminate/support/Facades/Response.php        [Z      .   vendor/illuminate/support/Facades/Schedule.php        O      .   vendor/illuminate/support/Facades/Pipeline.php{      {  tsT      *   vendor/illuminate/support/Facades/Mail.php          3      +   vendor/illuminate/support/Facades/Cache.php        ѣm      -   vendor/illuminate/support/Facades/Artisan.php        ugJ      0   vendor/illuminate/support/Facades/Exceptions.phpF      F  	      +   vendor/illuminate/support/Facades/Route.php!      !  ]      (   vendor/illuminate/support/Facades/DB.php!      !  `G      *   vendor/illuminate/support/Facades/Auth.phpF      F  Gs\      +   vendor/illuminate/support/Facades/Queue.phpc      c  Ԥ      5   vendor/illuminate/support/Facades/MaintenanceMode.php        ;      )   vendor/illuminate/support/Facades/App.php;&      ;&  {[̤      *   vendor/illuminate/support/Facades/Date.php          2̤      *   vendor/illuminate/support/Facades/Lang.php|      |  R~      2   vendor/illuminate/support/Facades/Notification.php*      *        -   vendor/illuminate/support/Facades/Storage.phpj$      j$  5      ,   vendor/illuminate/support/Facades/Config.phpx      x        *   vendor/illuminate/support/Facades/Gate.php        zi      )   vendor/illuminate/support/Facades/Bus.php        
      .   vendor/illuminate/support/Facades/Password.php	      	        *   vendor/illuminate/support/Facades/View.php        ){      ,   vendor/illuminate/support/Facades/Cookie.php	      	  Ym      +   vendor/illuminate/support/Facades/Blade.php?      ?  q2`Ϥ      )   vendor/illuminate/support/Facades/URL.php        Pc      .   vendor/illuminate/support/Facades/Redirect.phpV	      V	  $      *   vendor/illuminate/support/Facades/File.php        1      1   vendor/illuminate/support/Facades/RateLimiter.php        5'Q      *   vendor/illuminate/support/Facades/Hash.phpr      r  
7      /   vendor/illuminate/support/Facades/Broadcast.php
      
  ıZ      *   vendor/illuminate/support/Facades/Http.php*      *  J3      -   vendor/illuminate/support/Facades/Process.php        a,֤      +   vendor/illuminate/support/Facades/Redis.php^      ^  (B      +   vendor/illuminate/support/Facades/Crypt.php        BĤ      )   vendor/illuminate/support/Facades/Log.php]      ]  (y>f      -   vendor/illuminate/support/Facades/Session.php        4      1   vendor/illuminate/support/Facades/Concurrency.php        Pݤ      5   vendor/illuminate/support/Facades/ParallelTesting.php        X\      6   vendor/illuminate/support/AggregateServiceProvider.phpR      R  wUҤ      '   vendor/illuminate/support/functions.php        s      .   vendor/illuminate/support/DefaultProviders.php        T̔      !   vendor/illuminate/support/Uri.php<.      <.        4   vendor/illuminate/support/RebindsCallbacksToSelf.php\      \  :f:      %   vendor/illuminate/support/Timebox.php        ME      (   vendor/illuminate/support/MessageBag.php2*      2*  ׾      $   vendor/illuminate/support/Fluent.php        YR      -   vendor/illuminate/support/ServiceProvider.phpC      C  p      %   vendor/illuminate/support/Manager.php*      *  8      /   vendor/illuminate/support/InteractsWithTime.php        N      &   vendor/illuminate/support/Onceable.php	      	  z:)      )   vendor/illuminate/support/BinaryCodec.php               !   vendor/illuminate/support/Env.php_!      _!  j      )   vendor/illuminate/support/DateFactory.php)      )  q      4   vendor/illuminate/support/NamespacedItemResolver.phpT      T  I*      9   vendor/illuminate/support/Traits/ReadsClassAttributes.php        K?      6   vendor/illuminate/support/Traits/InteractsWithData.phpz+      z+  4B      2   vendor/illuminate/support/Traits/ForwardsCalls.phpR      R  >￤      0   vendor/illuminate/support/Traits/Localizable.phpu      u  ]J      -   vendor/illuminate/support/Traits/Dumpable.php        f&:      -   vendor/illuminate/support/Traits/Tappable.php        ,      8   vendor/illuminate/support/Traits/CapsuleManagerTrait.php        	      5   vendor/illuminate/support/MultipleInstanceManager.php        Mpפ      ,   vendor/illuminate/support/UriQueryString.php        yB      /   vendor/illuminate/support/EncodedHtmlString.php
      
  ρ      '   vendor/illuminate/support/Benchmark.php6      6  1)      3   vendor/illuminate/support/Testing/Fakes/BusFake.phpj      j  Н       <   vendor/illuminate/support/Testing/Fakes/PendingChainFake.php        *Ӥ      <   vendor/illuminate/support/Testing/Fakes/PendingBatchFake.php        v      ?   vendor/illuminate/support/Testing/Fakes/BatchRepositoryFake.phpQ      Q  <T      ;   vendor/illuminate/support/Testing/Fakes/PendingMailFake.php              5   vendor/illuminate/support/Testing/Fakes/EventFake.php.      .  s)y      0   vendor/illuminate/support/Testing/Fakes/Fake.phpN       N   }±      5   vendor/illuminate/support/Testing/Fakes/QueueFake.php2T      2T         <   vendor/illuminate/support/Testing/Fakes/NotificationFake.php^/      ^/  Fx      4   vendor/illuminate/support/Testing/Fakes/MailFake.php@      @  yc      A   vendor/illuminate/support/Testing/Fakes/ChainedBatchTruthTest.php        t      @   vendor/illuminate/support/Testing/Fakes/ExceptionHandlerFake.php        %w      5   vendor/illuminate/support/Testing/Fakes/BatchFake.php                $   vendor/illuminate/support/Carbon.phpr      r  \!      &   vendor/illuminate/support/Composer.php]      ]  Ni=      *   vendor/illuminate/support/ViewErrorBag.php
      
  EU      @   vendor/illuminate/support/Queue/Concerns/ResolvesQueueRoutes.php5      5   !          vendor/illuminate/support/Js.phpl      l  QH      %   vendor/illuminate/support/helpers.phpf5      f5  y ^      $   vendor/illuminate/support/Number.php2      2  ԟ      4   vendor/illuminate/support/ConfigurationUrlParser.php        ˇ!      1   vendor/illuminate/support/HigherOrderTapProxy.php        IQe      "   vendor/illuminate/support/Once.phpq      q  $      (   vendor/illuminate/support/HtmlString.php7      7  ˭@      *   vendor/illuminate/support/ProcessUtils.php              >   vendor/illuminate/support/Defer/DeferredCallbackCollection.php        _/*      4   vendor/illuminate/support/Defer/DeferredCallback.phpR      R   d      6   vendor/illuminate/support/Exceptions/MathException.php          \K      !   vendor/illuminate/support/Str.php!      !  "      (   vendor/illuminate/support/Stringable.php        I[      %   vendor/illuminate/support/Lottery.php3      3  e      0   vendor/illuminate/macroable/Traits/Macroable.php        EQ      *   vendor/illuminate/reflection/Reflector.php        U鄤      8   vendor/illuminate/reflection/Traits/ReflectsClosures.php        )k      (   vendor/illuminate/reflection/helpers.php5      5  A      ,   vendor/illuminate/filesystem/ReceiveFile.php        *B      *   vendor/illuminate/filesystem/functions.phph      h  I8      2   vendor/illuminate/filesystem/FilesystemManager.php3      3  
      2   vendor/illuminate/filesystem/FilesystemAdapter.phps      s  /      :   vendor/illuminate/filesystem/FilesystemServiceProvider.php_      _  	Y      *   vendor/illuminate/filesystem/ServeFile.php        h      -   vendor/illuminate/filesystem/LockableFile.php        'j      /   vendor/illuminate/filesystem/AwsS3V3Adapter.php              7   vendor/illuminate/filesystem/LocalFilesystemAdapter.phpY      Y  ]#      +   vendor/illuminate/filesystem/Filesystem.phpwO      wO  <      ,   vendor/illuminate/collections/Collection.phpx      x  8      <   vendor/illuminate/collections/HigherOrderCollectionProxy.phpB      B  ..      +   vendor/illuminate/collections/functions.php        Nڤ      =   vendor/illuminate/collections/MultipleItemsFoundException.php        D`      ,   vendor/illuminate/collections/Enumerable.php`      `  b      7   vendor/illuminate/collections/ItemNotFoundException.phpv       v   }       9   vendor/illuminate/collections/Traits/EnumeratesValues.phpS      S  "r      G   vendor/illuminate/collections/Traits/TransformsToResourceCollection.php        .      )   vendor/illuminate/collections/helpers.php(       (   zL      0   vendor/illuminate/collections/LazyCollection.php        _b      %   vendor/illuminate/collections/Arr.php              <?php

namespace Laravel\Installer\Console;

use BeyondCode\HerdConfiguration\HerdConfiguration;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Composer;
use Illuminate\Support\ProcessUtils;
use Illuminate\Support\Str;
use Laravel\Installer\Console\Enums\NodePackageManager;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\Support\Logger;
use Override;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RuntimeException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
use Throwable;

use function Illuminate\Filesystem\join_paths;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\info;
use function Laravel\Prompts\select;
use function Laravel\Prompts\task;
use function Laravel\Prompts\text;

class NewCommand extends Command
{
    use Concerns\ConfiguresPrompts;
    use Concerns\InteractsWithHerdOrValet;

    const DATABASE_DRIVERS = ['mysql', 'mariadb', 'pgsql', 'sqlite', 'sqlsrv'];

    /**
     * The Composer instance.
     *
     * @var Composer
     */
    protected $composer;

    protected ?HerdConfiguration $herdConfig = null;

    public function __construct()
    {
        parent::__construct();

        $this->loadHerdConfig();
    }

    /**
     * The agent context, encapsulating detection and JSON output behavior.
     */
    protected Agent $agent;

    /**
     * Detect agents, suppress interactive output, and emit a JSON result.
     */
    #[Override]
    public function run(InputInterface $input, OutputInterface $output): int
    {
        $this->agent = new Agent;

        if (! $this->agent->isActive()) {
            return parent::run($input, $output);
        }

        $input->setInteractive(false);

        $logOutput = $this->agent->openLog();

        Prompt::setOutput($logOutput);

        try {
            $exitCode = parent::run($input, $logOutput);
        } catch (Throwable $e) {
            $this->agent->emitFailure(['error' => $e->getMessage()]);

            return self::FAILURE;
        }

        if ($exitCode === self::SUCCESS) {
            $this->agent->emitSuccess();
        } else {
            $this->agent->emitFailure();
        }

        return $exitCode;
    }

    /**
     * Configure the command options.
     */
    #[Override]
    protected function configure(): void
    {
        $this
            ->setName('new')
            ->setDescription('Create a new Laravel application')
            ->addArgument('name', InputArgument::REQUIRED)
            ->addOption('dev', null, InputOption::VALUE_NONE, 'Install the latest "development" release')
            ->addOption('git', null, InputOption::VALUE_NONE, 'Initialize a Git repository')
            ->addOption('branch', null, InputOption::VALUE_REQUIRED, 'The branch that should be created for a new repository', $this->defaultBranch())
            ->addOption('github', null, InputOption::VALUE_OPTIONAL, 'Create a new repository on GitHub', false)
            ->addOption('organization', null, InputOption::VALUE_REQUIRED, 'The GitHub organization to create the new repository for')
            ->addOption('database', null, InputOption::VALUE_REQUIRED, 'The database driver your application will use. Possible values are: '.implode(', ', self::DATABASE_DRIVERS))
            ->addOption('react', null, InputOption::VALUE_NONE, 'Install the React Starter Kit')
            ->addOption('svelte', null, InputOption::VALUE_NONE, 'Install the Svelte Starter Kit')
            ->addOption('vue', null, InputOption::VALUE_NONE, 'Install the Vue Starter Kit')
            ->addOption('livewire', null, InputOption::VALUE_NONE, 'Install the Livewire Starter Kit')
            ->addOption('livewire-class-components', null, InputOption::VALUE_NONE, 'Generate stand-alone Livewire class components')
            ->addOption('workos', null, InputOption::VALUE_NONE, 'Use WorkOS for authentication')
            ->addOption('npm', null, InputOption::VALUE_NONE, 'Automatically run NPM scripts')
            ->addOption('teams', null, InputOption::VALUE_NONE, 'Install team support')
            ->addOption('no-authentication', null, InputOption::VALUE_NONE, 'Do not generate authentication scaffolding')
            ->addOption('pest', null, InputOption::VALUE_NONE, 'Install the Pest testing framework')
            ->addOption('phpunit', null, InputOption::VALUE_NONE, 'Install the PHPUnit testing framework')
            ->addOption('npm', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies')
            ->addOption('pnpm', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies via PNPM')
            ->addOption('bun', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies via Bun')
            ->addOption('yarn', null, InputOption::VALUE_NONE, 'Install and build NPM dependencies via Yarn')
            ->addOption('boost', null, InputOption::VALUE_NONE, 'Install Laravel Boost to improve AI assisted coding')
            ->addOption('no-boost', null, InputOption::VALUE_NONE, 'Skip Laravel Boost installation')
            ->addOption('using', null, InputOption::VALUE_OPTIONAL, 'Install a custom starter kit from a community maintained package')
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces install even if the directory already exists');
    }

    /**
     * Interact with the user before validating the input.
     */
    #[Override]
    protected function interact(InputInterface $input, OutputInterface $output): void
    {
        parent::interact($input, $output);

        $this->configurePrompts($input, $output);

        $this->displayHeader($output);

        $this->ensureExtensionsAreAvailable($input, $output);

        $this->checkForUpdate($input, $output);

        if (! $input->getArgument('name')) {
            $input->setArgument('name', text(
                label: 'What is the name of your project?',
                placeholder: 'E.g. example-app',
                required: 'The project name is required.',
                validate: function ($value) use ($input) {
                    if (preg_match('/[^\pL\pN\-_.]/', $value) !== 0) {
                        return 'The name may only contain letters, numbers, dashes, underscores, and periods.';
                    }

                    if ($input->getOption('force') !== true) {
                        try {
                            $this->verifyApplicationDoesntExist($this->getInstallationDirectory($value));
                        } catch (RuntimeException $e) {
                            return 'Application already exists.';
                        }
                    }
                },
            ));
        }

        if ($input->getOption('force') !== true) {
            $this->verifyApplicationDoesntExist(
                $this->getInstallationDirectory($input->getArgument('name'))
            );
        }

        if (! $this->usingStarterKit($input)) {
            match (select(
                label: 'Which starter kit would you like to install?',
                options: [
                    'none' => 'None',
                    'react' => 'React',
                    'svelte' => 'Svelte',
                    'vue' => 'Vue',
                    'livewire' => 'Livewire',
                ],
                default: 'none',
            )) {
                'react' => $input->setOption('react', true),
                'svelte' => $input->setOption('svelte', true),
                'vue' => $input->setOption('vue', true),
                'livewire' => $input->setOption('livewire', true),
                default => null,
            };

            if ($this->usingLaravelStarterKit($input)) {
                match (select(
                    label: 'Which authentication provider do you prefer?',
                    options: [
                        'laravel' => "Laravel's built-in authentication",
                        'workos' => 'WorkOS (Requires WorkOS account)',
                        'none' => 'No authentication scaffolding',
                    ],
                    default: 'laravel',
                )) {
                    'laravel' => $input->setOption('workos', false),
                    'workos' => $input->setOption('workos', true),
                    'none' => $input->setOption('no-authentication', true),
                    default => null,
                };
            }

            if (
                $input->getOption('livewire') &&
                ! $input->getOption('workos') &&
                ! $input->getOption('no-authentication')
            ) {
                $input->setOption('livewire-class-components', ! confirm(
                    label: 'Would you like to use single-file Livewire components?',
                    default: true,
                ));
            }

            if (
                $this->usingLaravelStarterKit($input) &&
                ! $input->getOption('no-authentication') &&
                ! $input->getOption('livewire-class-components') &&
                ! $input->getOption('teams')
            ) {
                $input->setOption('teams', confirm(
                    label: 'Would you like to add teams support to your application?',
                    default: false,
                ));
            }
        }

        if (! $input->getOption('phpunit') && ! $input->getOption('pest')) {
            $input->setOption('pest', select(
                label: 'Which testing framework do you prefer?',
                options: ['Pest', 'PHPUnit'],
                default: 'Pest',
            ) === 'Pest');
        }

        if (! $input->getOption('boost') && ! $input->getOption('no-boost')) {
            $input->setOption('boost', confirm(
                label: 'Do you want to install Laravel Boost to improve AI assisted coding?',
            ));
        }
    }

    /**
     * Display the Laravel header with gradient colors.
     */
    protected function displayHeader(OutputInterface $output): void
    {
        $output->writeln('');

        $lines = [
            ' ██╗       █████╗  ██████╗   █████╗  ██╗   ██╗ ███████╗ ██╗',
            ' ██║      ██╔══██╗ ██╔══██╗ ██╔══██╗ ██║   ██║ ██╔════╝ ██║',
            ' ██║      ███████║ ██████╔╝ ███████║ ██║   ██║ █████╗   ██║',
            ' ██║      ██╔══██║ ██╔══██╗ ██╔══██║ ╚██╗ ██╔╝ ██╔══╝   ██║',
            ' ███████╗ ██║  ██║ ██║  ██║ ██║  ██║  ╚████╔╝  ███████╗ ███████╗',
            ' ╚══════╝ ╚═╝  ╚═╝ ╚═╝  ╚═╝ ╚═╝  ╚═╝   ╚═══╝   ╚══════╝ ╚══════╝',
        ];

        $gradients = [
            'Red' => [196, 160, 124, 88, 52, 88],
            'Gray' => [250, 248, 245, 243, 240, 238],
            'Ocean' => [81, 75, 69, 63, 57, 21],
            'Vaporwave' => [213, 177, 141, 105, 69, 39],
            'Sunset' => [214, 208, 202, 196, 160, 124],
            'Aurora' => [51, 50, 49, 48, 47, 41],
            'Ember' => [227, 221, 215, 209, 203, 197],
            'Cyberpunk' => [201, 165, 129, 93, 57, 21],
        ];

        $themeName = array_rand($gradients);
        $gradient = $gradients[$themeName];

        foreach ($lines as $index => $line) {
            $color = $gradient[$index];
            $output->writeln("\e[38;5;{$color}m{$line}\e[0m");
        }
    }

    /**
     * Ensure that the required PHP extensions are installed.
     *
     *
     * @throws RuntimeException
     */
    protected function ensureExtensionsAreAvailable(InputInterface $input, OutputInterface $output): void
    {
        $availableExtensions = get_loaded_extensions();

        $missingExtensions = collect([
            'ctype',
            'filter',
            'hash',
            'mbstring',
            'openssl',
            'session',
            'tokenizer',
        ])->reject(fn ($extension) => in_array($extension, $availableExtensions));

        if ($missingExtensions->isEmpty()) {
            return;
        }

        throw new RuntimeException(
            sprintf('The following PHP extensions are required but are not installed: %s', $missingExtensions->join(', ', ', and '))
        );
    }

    /**
     * Check for newer version of the installer package.
     *
     * @return void
     */
    protected function checkForUpdate(InputInterface $input, OutputInterface $output)
    {
        if ($this->agent->isActive()) {
            return;
        }

        $package = 'laravel/installer';
        $version = $this->getApplication()->getVersion();
        $versionData = $this->getLatestVersionData($package);

        if ($versionData === false) {
            return;
        }

        $data = json_decode($versionData, true);
        $latestVersion = ltrim($data['packages'][$package][0]['version'], 'v');

        if (version_compare($version, $latestVersion) !== -1) {
            return;
        }

        $output->writeln('');
        $output->writeln("  <bg=yellow;fg=black> WARN </> A new version of the Laravel installer is available. You have version {$version} installed, the latest version is {$latestVersion}.");

        $laravelInstallerPath = (new ExecutableFinder)->find('laravel') ?? '';
        $isHerd = str_contains($laravelInstallerPath, DIRECTORY_SEPARATOR.'Herd'.DIRECTORY_SEPARATOR);
        // Intalled via php.new
        $isHerdLite = str_contains($laravelInstallerPath, DIRECTORY_SEPARATOR.'herd-lite'.DIRECTORY_SEPARATOR);

        if ($isHerd) {
            $this->confirmUpdateAndContinue(
                'To update, open <options=bold>Herd</> > <options=bold>Settings</> > <options=bold>PHP</> > <options=bold>Laravel Installer</> '
                    .'and click the <options=bold>"Update"</> button.',
                $input,
                $output
            );

            return;
        }

        if ($isHerdLite) {
            $message = match (PHP_OS_FAMILY) {
                'Windows' => 'Set-ExecutionPolicy Bypass -Scope Process -Force; '
                    .'[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; '
                    ."iex ((New-Object System.Net.WebClient).DownloadString('https://php.new/install/windows'))",
                'Darwin' => '/bin/bash -c "$(curl -fsSL https://php.new/install/mac)"',
                default => '/bin/bash -c "$(curl -fsSL https://php.new/install/linux)"',
            };

            $output->writeln('');
            $output->writeln('  To update, run the following command in your terminal:');

            $this->confirmUpdateAndContinue($message, $input, $output);

            return;
        }

        if (confirm(label: 'Would you like to update now?')) {
            $this->runCommands(
                [
                    'Installer updated' => 'composer global update laravel/installer --with-all-dependencies',
                ],
                $input,
                $output,
                taskLabel: 'Updating Laravel installer',
            );
            $this->proxyLaravelNew($input, $output);
        }
    }

    /**
     * Allow the user to update the Laravel Installer and continue.
     */
    protected function confirmUpdateAndContinue(string $message, InputInterface $input, OutputInterface $output): void
    {
        $output->writeln('');
        $output->writeln("  {$message}");

        $updated = confirm(
            label: 'Would you like to update now?',
            yes: 'I have updated',
            no: 'Not now',
        );

        if (! $updated) {
            return;
        }

        $this->proxyLaravelNew($input, $output);
    }

    /**
     * Proxy the command to the globally installed Laravel Installer.
     */
    protected function proxyLaravelNew(InputInterface $input, OutputInterface $output): void
    {
        $output->writeln('');
        $this->runCommands(['laravel '.$input], $input, $output, workingPath: getcwd());
        exit;
    }

    /**
     * Get the latest version of the installer package from Packagist.
     */
    protected function getLatestVersionData(string $package): string|false
    {
        $packagePrefix = str_replace('/', '-', $package);
        $cachedPath = join_paths(sys_get_temp_dir(), $packagePrefix.'-version-check.json');
        $lastModifiedPath = join_paths(sys_get_temp_dir(), $packagePrefix.'-last-modified');

        $cacheExists = file_exists($cachedPath);
        $lastModifiedExists = file_exists($lastModifiedPath);

        $cacheLastWrittenAt = $cacheExists ? filemtime($cachedPath) : 0;
        $lastModifiedResponse = $lastModifiedExists ? file_get_contents($lastModifiedPath) : null;

        if ($cacheLastWrittenAt > time() - 86400) {
            // Cache is less than 24 hours old, use it
            return file_get_contents($cachedPath);
        }

        $curl = curl_init();

        $headers = ['User-Agent: Laravel Installer'];

        if ($lastModifiedResponse) {
            $headers[] = "If-Modified-Since: {$lastModifiedResponse}";
        }

        curl_setopt_array($curl, [
            CURLOPT_URL => "https://repo.packagist.org/p2/{$package}.json",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => true,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_TIMEOUT => 3,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_SSL_VERIFYPEER => true,
        ]);

        try {
            $response = curl_exec($curl);
            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
            $error = curl_error($curl);

            unset($curl);
        } catch (Throwable $e) {
            return false;
        }

        if ($error) {
            return false;
        }

        $responseHeaders = substr($response, 0, $headerSize);
        $result = substr($response, $headerSize);

        $lastModifiedFromResponse = null;

        if (preg_match('/^Last-Modified:\s*(.+)$/mi', $responseHeaders, $matches)) {
            $lastModifiedFromResponse = trim($matches[1]);
        }

        file_put_contents($lastModifiedPath, $lastModifiedFromResponse);

        if ($httpCode === 304 && $cacheExists) {
            touch($cachedPath);

            return file_get_contents($cachedPath);
        }

        if ($httpCode === 200 && $result !== false) {
            file_put_contents($cachedPath, $result);

            return $result;
        }

        return ($cacheExists) ? file_get_contents($cachedPath) : false;
    }

    /**
     * Execute the command.
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->pingNewInstallUrl();

        $this->validateDatabaseOption($input);

        $name = rtrim($input->getArgument('name'), '/\\');

        $directory = $this->getInstallationDirectory($name);

        $this->agent->rememberInstallation($directory);

        $this->composer = new Composer(new Filesystem, $directory);

        $version = $this->getVersion($input);

        if (! $input->getOption('force')) {
            $this->verifyApplicationDoesntExist($directory);
        }

        if ($input->getOption('force') && $directory === '.') {
            throw new RuntimeException('Cannot use --force option when using current directory for installation!');
        }

        $composer = $this->findComposer();
        $phpBinary = $this->phpBinary();

        $createProjectCommand = $composer." create-project laravel/laravel \"$directory\" $version --remove-vcs --prefer-dist --no-scripts";

        $starterKit = $this->getStarterKit($input);

        if ($starterKit) {
            $createProjectCommand = $composer." create-project {$starterKit} \"{$directory}\" --stability=dev";

            if ($this->usingLaravelStarterKit($input) && $input->getOption('livewire-class-components')) {
                $createProjectCommand = str_replace(" {$starterKit} ", " {$starterKit}:dev-components ", $createProjectCommand);
            }

            if ($this->usingLaravelStarterKit($input)) {
                $branch = match (true) {
                    $input->getOption('workos') && $input->getOption('teams') => 'dev-workos-teams',
                    $input->getOption('workos') => 'dev-workos',
                    $input->getOption('teams') => 'dev-teams',
                    default => null,
                };

                if ($branch) {
                    $createProjectCommand = str_replace(" {$starterKit} ", " {$starterKit}:{$branch} ", $createProjectCommand);
                }
            }

            if (! $this->usingLaravelStarterKit($input) && str_contains($starterKit, '://')) {
                $createProjectCommand = 'npx tiged@latest '.$starterKit.' "'.$directory.'" && cd "'.$directory.'" && composer install';
            }
        }

        $commands = [];

        if ($directory != '.' && $input->getOption('force')) {
            $forceLabel = "Removed existing directory [{$name}]";

            if (PHP_OS_FAMILY == 'Windows') {
                $commands[$forceLabel] = "(if exist \"$directory\" rd /s /q \"$directory\")";
            } else {
                $commands[$forceLabel] = "rm -rf \"$directory\"";
            }
        }

        $commands['Application installed'] = $createProjectCommand;

        $appInitializedLabel = 'Application initialized';

        $commands[$appInitializedLabel] = [
            $composer." run post-root-package-install -d \"$directory\"",
            $phpBinary." \"$directory/artisan\" key:generate --ansi",
        ];

        if (PHP_OS_FAMILY != 'Windows') {
            $commands[$appInitializedLabel][] = "chmod 755 \"$directory/artisan\"";
        }

        if (($process = $this->runCommands(
            $commands,
            $input,
            $output,
            // Starter kits need to defer execution of hooks until after create-project completes...
            env: ['LARAVEL_INSTALLER_DEFER_HOOKS' => '1'],
            taskLabel: 'Creating Laravel application',
        ))->isSuccessful()) {
            $hooksProcess = $this->runInstallerHooks($directory, $input, $output);

            if ($hooksProcess && ! $hooksProcess->isSuccessful()) {
                return $hooksProcess->getExitCode();
            }

            if ($name !== '.') {
                $this->pregReplaceInFile(
                    '/^APP_URL=http:\/\/localhost$/m',
                    'APP_URL='.$this->generateAppUrl($name, $directory),
                    $directory.'/.env'
                );

                [$database, $migrate] = $this->promptForDatabaseOptions($directory, $input);

                $this->configureDefaultDatabaseConnection($directory, $database, $name);

                if ($migrate) {
                    if ($database === 'sqlite') {
                        touch($directory.'/database/database.sqlite');
                    }

                    $commands = [
                        'Database migrated' => trim(sprintf(
                            $this->phpBinary().' artisan migrate %s',
                            ! $input->isInteractive() ? '--no-interaction' : '',
                        )),
                    ];

                    $this->runCommands(
                        $commands,
                        $input,
                        $output,
                        workingPath: $directory,
                        taskLabel: 'Running database migrations',
                    );
                }
            }

            if($this->herdConfig && $this->herdConfig->isPro()) {
                $this->replaceInFile(
                    'MAIL_HOST=log',
                    'MAIL_HOST=127.0.0.1',
                    $directory.'/.env'
                );


                $this->replaceInFile(
                    'MAIL_MAILER=log',
                    'MAIL_MAILER=smtp',
                    $directory.'/.env'
                );

                $this->replaceInFile(
                    'MAIL_PORT=2525',
                    'MAIL_PORT='. $this->herdConfig->smtpPort(),
                    $directory.'/.env'
                );

                if ($name !== '.') {
                    $mailboxName = $this->generateMailboxName($name);
                }
                else {
                    $mailboxName = '${APP_NAME}';
                }

                $this->replaceInFile(
                    'MAIL_USERNAME=null',
                    'MAIL_USERNAME="' . $mailboxName . '"',
                    $directory.'/.env'
                );
            }


            if ($input->getOption('git') || $input->getOption('github') !== false) {
                $this->createRepository($directory, $input, $output);
            }

            if ($input->getOption('pest')) {
                $this->installPest($directory, $input, $output);
            }

            if ($input->getOption('github') !== false) {
                $this->pushToGitHub($name, $directory, $input, $output);
                $output->writeln('');
            }

            [$packageManager, $runPackageManager] = $this->determinePackageManager($directory, $input);

            $this->configureComposerScripts($packageManager);

            if ($input->getOption('pest') && ! $this->useConciseOutput($output)) {
                $output->writeln('');
            }

            if (! $runPackageManager && $input->isInteractive()) {
                $runPackageManager = confirm(
                    label: 'Would you like to run <options=bold>'.$packageManager->installCommand().'</> and <options=bold>'.$packageManager->buildCommand().'</>?'
                );
            }

            foreach (NodePackageManager::allLockFiles() as $lockFile) {
                if (! in_array($lockFile, $packageManager->lockFiles()) && file_exists($directory.'/'.$lockFile)) {
                    (new Filesystem)->delete($directory.'/'.$lockFile);
                }
            }

            if ($runPackageManager) {
                $this->runCommands(
                    [
                        'Packages installed' => $packageManager->installCommand(),
                        'Assets built' => $packageManager->buildCommand(),
                    ],
                    $input,
                    $output,
                    workingPath: $directory,
                    taskLabel: 'Setting up frontend dependencies with '.$packageManager->value,
                );
            }

            if ($input->getOption('boost') && ! $input->getOption('no-boost')) {
                $this->installBoost($directory, $input, $output);
            }

            if ($input->getOption('boost') && ! $input->getOption('no-boost')) {
                $this->configureBoostComposerScript();
                $this->commitChanges('Configure Boost post-update script', $directory, $input, $output);
            }

            info("Application ready in <options=bold>[{$name}]</>. You can start your local development using:");

            $output->writeln($this->finalStep("cd {$name}"));

            if (! $runPackageManager) {
                $output->writeln($this->finalStep($packageManager->installCommand().' && '.$packageManager->buildCommand()));
            }

            if ($this->isParkedOnHerdOrValet($directory)) {
                $url = $this->generateAppUrl($name, $directory);
                $output->writeln($this->finalStep('Open: <options=bold;href='.$url.'>'.$url));
            } else {
                $output->writeln($this->finalStep('composer run dev'));
            }

            $output->writeln('');
            $output->writeln(' <fg=cyan;options=bold>New to Laravel?</> Check out our <href=https://laravel.com/docs/installation#next-steps;options=underscore>documentation</>. <options=bold>Build something amazing!</>');
            $output->writeln('');

            $output->writeln('');
            if($this->herdConfig && $this->herdConfig->isPro()) {
                $output->writeln('  <bg=green;fg=black> DONE </> Herd Pro set up your mailbox at <options=bold>'.$mailboxName.'</>. Your application is ready to send mails now!');
                $output->writeln('');
            }
            $output->writeln('');
        }

        return $process->getExitCode();
    }

    /**
     * Format the final step command with an arrow and styling.
     */
    protected function finalStep(string $command): string
    {
        return ' <fg=gray>➜</> '.(str_contains($command, '<') ? $command : "<options=bold>{$command}</>");
    }

    /**
     * Ping the new install URL.
     */
    protected function pingNewInstallUrl(): void
    {
        $curl = curl_init();

        $headers = ['User-Agent: Laravel Installer'];

        if ($this->agent->isActive() && $this->agent->name() !== null) {
            $headers[] = 'X-Agent: '.match ($this->agent->name()) {
                'Claude' => 'Claude Code', // For legacy purposes
                default => $this->agent->name(),
            };
        }

        curl_setopt_array($curl, [
            CURLOPT_URL => 'https://laravel.com/new-install',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_TIMEOUT => 3,
        ]);

        try {
            curl_exec($curl);
        } catch (Throwable $e) {
            //
        }
    }

    /**
     * Determine the Node package manager to use.
     *
     * @return array{NodePackageManager, bool}
     */
    protected function determinePackageManager(string $directory, InputInterface $input): array
    {
        // If they passed a specific flag, respect the user's choice...
        if ($input->getOption('pnpm')) {
            return [NodePackageManager::PNPM, true];
        }

        if ($input->getOption('bun')) {
            return [NodePackageManager::BUN, true];
        }

        if ($input->getOption('yarn')) {
            return [NodePackageManager::YARN, true];
        }

        if ($input->getOption('npm')) {
            return [NodePackageManager::NPM, true];
        }

        // Check for an existing lock file to determine the package manager...
        foreach (NodePackageManager::cases() as $packageManager) {
            if ($packageManager === NodePackageManager::NPM) {
                continue;
            }

            foreach ($packageManager->lockFiles() as $lockFile) {
                if (file_exists($directory.'/'.$lockFile)) {
                    return [$packageManager, false];
                }
            }
        }

        return [NodePackageManager::NPM, false];
    }

    /**
     * Return the local machine's default Git branch if set or default to `main`.
     *
     * @return string
     */
    protected function defaultBranch()
    {
        $process = new Process(['git', 'config', '--global', 'init.defaultBranch']);

        $process->run();

        $output = trim($process->getOutput());

        return $process->isSuccessful() && $output ? $output : 'main';
    }

    /**
     * Configure the default database connection.
     *
     * @return void
     */
    protected function configureDefaultDatabaseConnection(string $directory, string $database, string $name)
    {
        $this->pregReplaceInFile(
            '/DB_CONNECTION=.*/',
            'DB_CONNECTION='.$database,
            $directory.'/.env'
        );

        $this->pregReplaceInFile(
            '/DB_CONNECTION=.*/',
            'DB_CONNECTION='.$database,
            $directory.'/.env.example'
        );

        if ($database === 'sqlite') {
            $environment = file_get_contents($directory.'/.env');

            // If database options aren't commented, comment them for SQLite...
            if (! str_contains($environment, '# DB_HOST=127.0.0.1')) {
                $this->commentDatabaseConfigurationForSqlite($directory);

                return;
            }

            return;
        }

        // Any commented database configuration options should be uncommented when not on SQLite...
        $this->uncommentDatabaseConfiguration($directory);

        $defaultPorts = [
            'pgsql' => '5432',
            'sqlsrv' => '1433',
        ];

        if (isset($defaultPorts[$database])) {
            $this->replaceInFile(
                'DB_PORT=3306',
                'DB_PORT='.$defaultPorts[$database],
                $directory.'/.env'
            );

            $this->replaceInFile(
                'DB_PORT=3306',
                'DB_PORT='.$defaultPorts[$database],
                $directory.'/.env.example'
            );
        }

        $this->replaceInFile(
            'DB_DATABASE=laravel',
            'DB_DATABASE='.str_replace('-', '_', strtolower($name)),
            $directory.'/.env'
        );

        $this->replaceInFile(
            'DB_DATABASE=laravel',
            'DB_DATABASE='.str_replace('-', '_', strtolower($name)),
            $directory.'/.env.example'
        );
    }

    /**
     * Determine if the application is using Laravel 11 or newer.
     */
    public function usingLaravelVersionOrNewer(int $usingVersion, string $directory): bool
    {
        $version = json_decode(file_get_contents($directory.'/composer.json'), true)['require']['laravel/framework'];
        $version = str_replace('^', '', $version);
        $version = explode('.', $version)[0];

        return $version >= $usingVersion;
    }

    /**
     * Comment the irrelevant database configuration entries for SQLite applications.
     */
    protected function commentDatabaseConfigurationForSqlite(string $directory): void
    {
        $defaults = [
            'DB_HOST=127.0.0.1',
            'DB_PORT=3306',
            'DB_DATABASE=laravel',
            'DB_USERNAME=root',
            'DB_PASSWORD=',
        ];

        $this->replaceInFile(
            $defaults,
            collect($defaults)->map(fn ($default) => "# {$default}")->all(),
            $directory.'/.env'
        );

        $this->replaceInFile(
            $defaults,
            collect($defaults)->map(fn ($default) => "# {$default}")->all(),
            $directory.'/.env.example'
        );
    }

    /**
     * Uncomment the relevant database configuration entries for non SQLite applications.
     *
     * @return void
     */
    protected function uncommentDatabaseConfiguration(string $directory)
    {
        $defaults = [
            '# DB_HOST=127.0.0.1',
            '# DB_PORT=3306',
            '# DB_DATABASE=laravel',
            '# DB_USERNAME=root',
            '# DB_PASSWORD=',
        ];

        $this->replaceInFile(
            $defaults,
            collect($defaults)->map(fn ($default) => substr($default, 2))->all(),
            $directory.'/.env'
        );

        $this->replaceInFile(
            $defaults,
            collect($defaults)->map(fn ($default) => substr($default, 2))->all(),
            $directory.'/.env.example'
        );
    }

    /**
     * Determine the default database connection.
     *
     * @return array
     */
    protected function promptForDatabaseOptions(string $directory, InputInterface $input)
    {
        $defaultDatabase = collect(
            $databaseOptions = $this->databaseOptions()
        )->keys()->first();

        if (! $input->getOption('database') && $this->usingStarterKit($input)) {
            // Starter kits will already be migrated in post composer create-project command...
            $migrate = false;

            $input->setOption('database', 'sqlite');
        }

        if (! $input->getOption('database') && $input->isInteractive()) {
            $input->setOption('database', select(
                label: 'Which database will your application use?',
                options: $databaseOptions,
                default: $defaultDatabase,
            ));

            if ($input->getOption('database') !== 'sqlite') {
                $migrate = confirm(
                    label: 'Default database updated. Would you like to run the default database migrations?'
                );
            } else {
                $migrate = true;
            }
        }

        return [$input->getOption('database') ?? $defaultDatabase, $migrate ?? $input->hasOption('database')];
    }

    /**
     * Get the available database options.
     */
    protected function databaseOptions(): array
    {
        return collect([
            'sqlite' => ['SQLite', extension_loaded('pdo_sqlite')],
            'mysql' => ['MySQL', extension_loaded('pdo_mysql')],
            'mariadb' => ['MariaDB', extension_loaded('pdo_mysql')],
            'pgsql' => ['PostgreSQL', extension_loaded('pdo_pgsql')],
            'sqlsrv' => ['SQL Server', extension_loaded('pdo_sqlsrv')],
        ])
            ->sortBy(fn ($database) => $database[1] ? 0 : 1)
            ->map(fn ($database) => $database[0].($database[1] ? '' : ' (Missing PDO extension)'))
            ->all();
    }

    /**
     * Validate the database driver input.
     */
    protected function validateDatabaseOption(InputInterface $input)
    {
        if ($input->getOption('database') && ! in_array($input->getOption('database'), self::DATABASE_DRIVERS)) {
            throw new \InvalidArgumentException("Invalid database driver [{$input->getOption('database')}]. Possible values are: ".implode(', ', self::DATABASE_DRIVERS).'.');
        }
    }

    /**
     * Install Pest into the application.
     *
     * @return void
     */
    protected function installPest(string $directory, InputInterface $input, OutputInterface $output)
    {
        $composerBinary = $this->findComposer();

        $commands = [
            'Pest installed' => [
                $composerBinary.' remove phpunit/phpunit --dev --no-update',
                $composerBinary.' require pestphp/pest pestphp/pest-plugin-laravel --no-update --dev',
                $composerBinary.' update',
            ],
            'Pest initialized' => [
                $this->phpBinary().' ./vendor/bin/pest --init',
                $composerBinary.' require pestphp/pest-plugin-drift --dev',
                $this->phpBinary().' ./vendor/bin/pest --drift',
                $composerBinary.' remove pestphp/pest-plugin-drift --dev',
            ],
        ];

        $this->runCommands(
            $commands,
            $input,
            $output,
            workingPath: $directory,
            env: ['PEST_NO_SUPPORT' => 'true'],
            taskLabel: 'Setting up Pest',
        );

        if ($this->usingStarterKit($input)) {
            $this->replaceInFile(
                './vendor/bin/phpunit',
                './vendor/bin/pest',
                $directory.'/.github/workflows/tests.yml',
            );

            $contents = file_get_contents("$directory/tests/Pest.php");

            $contents = str_replace(
                ' // ->use(RefreshDatabase::class)',
                '    ->use(RefreshDatabase::class)',
                $contents,
            );

            file_put_contents("$directory/tests/Pest.php", $contents);

            $directoryIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("$directory/tests"));

            foreach ($directoryIterator as $testFile) {
                if ($testFile->isDir()) {
                    continue;
                }

                $contents = file_get_contents($testFile);

                file_put_contents(
                    $testFile,
                    str_replace("\n\nuses(\Illuminate\Foundation\Testing\RefreshDatabase::class);", '', $contents),
                );
            }
        }

        $this->commitChanges('Install Pest', $directory, $input, $output);
    }

    /**
     * Install Laravel Boost into the application.
     */
    protected function installBoost(string $directory, InputInterface $input, OutputInterface $output): void
    {
        $composerBinary = $this->findComposer();

        $commands = [
            'Boost installed' => $composerBinary.' require "laravel/boost:^2.2" --dev -W',
            'Boost initialized' => trim(sprintf(
                $this->phpBinary().' artisan boost:install %s',
                ! $input->isInteractive() ? '--no-interaction' : '',
            )),
        ];

        $this->runCommands(
            $commands,
            $input,
            $output,
            workingPath: $directory,
            taskLabel: 'Setting up Laravel Boost',
        );

        $this->commitChanges('Install Laravel Boost', $directory, $input, $output);
    }

    /**
     * Create a Git repository and commit the base Laravel skeleton.
     *
     * @return void
     */
    protected function createRepository(string $directory, InputInterface $input, OutputInterface $output)
    {
        $branch = $input->getOption('branch') ?: $this->defaultBranch();

        $commands = [
            'Repository initialized' => [
                'git init -q',
                'git add .',
                'git commit -q -m "Set up a fresh Laravel app"',
                "git branch -M {$branch}",
            ],
        ];

        $this->runCommands(
            $commands,
            $input,
            $output,
            workingPath: $directory,
            taskLabel: 'Initializing Git repository',
        );
    }

    /**
     * Commit any changes in the current working directory.
     *
     * @return void
     */
    protected function commitChanges(string $message, string $directory, InputInterface $input, OutputInterface $output)
    {
        if (! $input->getOption('git') && $input->getOption('github') === false) {
            return;
        }

        $commands = [
            'Changes committed' => [
                'git add .',
                "git commit -q -m \"$message\"",
            ],
        ];

        $this->runCommands(
            $commands,
            $input,
            $output,
            workingPath: $directory,
            taskLabel: 'Committing changes',
        );
    }

    /**
     * Create a GitHub repository and push the git log to it.
     *
     * @return void
     */
    protected function pushToGitHub(string $name, string $directory, InputInterface $input, OutputInterface $output)
    {
        $process = new Process(['gh', 'auth', 'status']);
        $process->run();

        if (! $process->isSuccessful()) {
            $output->writeln('  <bg=yellow;fg=black> WARN </> Make sure the "gh" CLI tool is installed and that you\'re authenticated to GitHub. Skipping...'.PHP_EOL);

            return;
        }

        $name = $input->getOption('organization') ? $input->getOption('organization')."/$name" : $name;
        $flags = $input->getOption('github') ?: '--private';

        $commands = [
            'Repository pushed' => "gh repo create {$name} --source=. --push {$flags}",
        ];

        $this->runCommands(
            $commands,
            $input,
            $output,
            workingPath: $directory,
            env: ['GIT_TERMINAL_PROMPT' => 0],
            taskLabel: "Pushing to GitHub [{$name}]",
        );
    }

    /**
     * Configure the Composer scripts for the selected package manager.
     */
    protected function configureComposerScripts(NodePackageManager $packageManager): void
    {
        $this->composer->modify(function (array $content) use ($packageManager) {
            if (windows_os()) {
                $content['scripts']['dev'] = [
                    'Composer\\Config::disableProcessTimeout',
                    "npx concurrently -c \"#93c5fd,#c4b5fd,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"npm run dev\" --names='server,queue,vite'",
                ];
            }

            foreach (['dev', 'dev:ssr', 'setup'] as $scriptKey) {
                if (array_key_exists($scriptKey, $content['scripts'])) {
                    $content['scripts'][$scriptKey] = str_replace(
                        ['npm', 'npx', 'ppnpm'],
                        [$packageManager->value, $packageManager->runLocalOrRemoteCommand(), 'pnpm'],
                        $content['scripts'][$scriptKey],
                    );
                }
            }

            return $content;
        });
    }

    /**
     * Add boost:update command to the post-update-cmd Composer script.
     */
    protected function configureBoostComposerScript(): void
    {
        $this->composer->modify(function (array $content) {
            $content['scripts']['post-update-cmd'][] = '@php artisan boost:update --ansi';

            return $content;
        });
    }

    /**
     * Run any Laravel installer hooks defined by the installed application.
     */
    protected function runInstallerHooks(string $directory, InputInterface $input, OutputInterface $output): ?Process
    {
        $commands = $this->installerHooks($directory, 'post-create-project');

        if ($commands === []) {
            return null;
        }

        return $this->runCommands(
            $commands,
            $input,
            $output,
            workingPath: $directory,
            taskLabel: 'Running starter kit hooks',
        );
    }

    /**
     * Get the commands for the given Laravel installer hook.
     */
    protected function installerHooks(string $directory, string $hook): array
    {
        $composerJson = $directory.'/composer.json';

        if (! file_exists($composerJson)) {
            return [];
        }

        $composer = json_decode(file_get_contents($composerJson), true) ?: [];

        return collect($composer['extra']['laravel']['installer'][$hook] ?? [])
            ->filter(fn ($command) => is_string($command) && $command !== '')
            ->map(fn ($command) => $this->normalizeInstallerHookCommand($command))
            ->values()
            ->all();
    }

    /**
     * Normalize Composer-style script commands for direct execution by the installer.
     */
    protected function normalizeInstallerHookCommand(string $command): string
    {
        $replace = [
            'php' => fn () => $this->phpBinary(),
            'composer' => fn () => $this->findComposer(),
        ];

        foreach ($replace as $find => $binary) {
            $marker = "@{$find}";

            if (str_starts_with($command, "{$marker} ")) {
                return $binary().' '.substr($command, strlen("{$marker} "));
            }

            if ($command === $marker) {
                return $binary();
            }
        }

        return $command;
    }

    /**
     * Verify that the application does not already exist.
     *
     * @param  string  $directory
     * @return void
     */
    protected function verifyApplicationDoesntExist($directory)
    {
        if ((is_dir($directory) || is_file($directory)) && $directory != getcwd()) {
            throw new RuntimeException('Application already exists!');
        }
    }

    /**
     * Generate a valid APP_URL for the given application name.
     *
     * @param  string  $name
     * @param  string  $directory
     * @return string
     */
    protected function generateAppUrl($name, $directory)
    {
        if (! $this->isParkedOnHerdOrValet($directory)) {
            return 'http://localhost:8000';
        }

        $hostname = mb_strtolower($name).'.'.$this->getTld();

        return $this->canResolveHostname($hostname) ? 'http://'.$hostname : 'http://localhost';
    }

     /**
     * Generate a mailbox name for the given application name.
     *
     * @param  string  $name
     * @return string
     */
    protected function generateMailboxName($name)
    {
        return ucwords(str_replace('-', ' ', $name));
    }

    /**
     * Get the starter kit repository, if any.
     */
    protected function getStarterKit(InputInterface $input): ?string
    {
        if ($input->getOption('no-authentication')) {
            return match (true) {
                $input->getOption('react') => 'laravel/blank-react-starter-kit',
                $input->getOption('svelte') => 'laravel/blank-svelte-starter-kit',
                $input->getOption('vue') => 'laravel/blank-vue-starter-kit',
                $input->getOption('livewire') => 'laravel/blank-livewire-starter-kit',
                default => $input->getOption('using'),
            };
        }

        return match (true) {
            $input->getOption('react') => 'laravel/react-starter-kit',
            $input->getOption('svelte') => 'laravel/svelte-starter-kit',
            $input->getOption('vue') => 'laravel/vue-starter-kit',
            $input->getOption('livewire') => 'laravel/livewire-starter-kit',
            default => $input->getOption('using'),
        };
    }

    /**
     * Determine if a Laravel first-party starter kit has been chosen.
     */
    protected function usingLaravelStarterKit(InputInterface $input): bool
    {
        return $this->usingStarterKit($input) &&
            str_starts_with($this->getStarterKit($input), 'laravel/');
    }

    /**
     * Determine if a starter kit is being used.
     *
     * @return bool
     */
    protected function usingStarterKit(InputInterface $input)
    {
        return $input->getOption('react') || $input->getOption('svelte') || $input->getOption('vue') || $input->getOption('livewire') || $input->getOption('using');
    }

    /**
     * Get the TLD for the application.
     *
     * @return string
     */
    protected function getTld()
    {
        return $this->runOnValetOrHerd('tld') ?: 'test';
    }

    /**
     * Determine whether the given hostname is resolvable.
     *
     * @param  string  $hostname
     * @return bool
     */
    protected function canResolveHostname($hostname)
    {
        return gethostbyname($hostname.'.') !== $hostname.'.';
    }

    /**
     * Get the installation directory.
     *
     * @return string
     */
    protected function getInstallationDirectory(string $name)
    {
        if ($name === '.') {
            return '.';
        }

        return str_starts_with($name, DIRECTORY_SEPARATOR) ? $name : getcwd().'/'.$name;
    }

    /**
     * Get the version that should be downloaded.
     *
     * @return string
     */
    protected function getVersion(InputInterface $input)
    {
        if ($input->getOption('dev')) {
            return 'dev-master';
        }

        return '';
    }

    /**
     * Get the composer command for the environment.
     *
     * @return string
     */
    protected function findComposer()
    {
        return implode(' ', $this->composer->findComposer());
    }

    /**
     * Get the path to the appropriate PHP binary.
     *
     * @return string
     */
    protected function phpBinary()
    {
        $phpBinary = function_exists('Illuminate\Support\php_binary')
            ? \Illuminate\Support\php_binary()
            : (new PhpExecutableFinder)->find(false);

        return $phpBinary !== false
            ? ProcessUtils::escapeArgument($phpBinary)
            : 'php';
    }

    /**
     * Run the given commands.
     *
     * @param  array  $commands
     * @return Process
     */
    protected function runCommands(
        $commands,
        InputInterface $input,
        OutputInterface $output,
        ?string $workingPath = null,
        array $env = [],
        ?string $taskLabel = null,
    ) {
        $commands = array_map(fn ($value) => (is_array($value)) ? $value : [$value], $commands);

        if (! $output->isDecorated()) {
            $commands = array_map(
                fn ($values) => array_map(function ($value) {
                    if (Str::startsWith($value, ['chmod', 'rm', 'git', $this->phpBinary().' ./vendor/bin/pest'])) {
                        return $value;
                    }

                    return $value.' --no-ansi';
                }, $values),
                $commands,
            );
        }

        if ($input->getOption('quiet')) {
            $commands = array_map(
                fn ($values) => array_map(function ($value) {
                    if (Str::startsWith($value, ['chmod', 'rm', 'git', $this->phpBinary().' ./vendor/bin/pest'])) {
                        return $value;
                    }

                    return $value.' --quiet';
                }, $values),
                $commands,
            );
        }

        if ($this->shouldRunAsTask($output, $commands)) {
            return $this->runCommandsAsTask($commands, $workingPath, $env, $taskLabel);
        }

        $commandline = implode(' && ', array_map(fn ($values) => implode(' && ', $values), $commands));

        if ('\\' === DIRECTORY_SEPARATOR && $input->isInteractive() && ! Process::isTtySupported()) {
            return $this->runCommandsInteractivelyOnWindows($commandline, $workingPath, $env);
        }

        $process = Process::fromShellCommandline($commandline, $workingPath, $env, null, null);

        if (Process::isTtySupported() && ! $this->agent->isActive()) {
            try {
                $process->setTty(true);
            } catch (RuntimeException $e) {
                $output->writeln('  <bg=yellow;fg=black> WARN </> '.$e->getMessage().PHP_EOL);
            }
        }

        $process->run(function ($type, $line) use ($output) {
            $output->write('    '.$line);
        });

        return $process;
    }

    /**
     * Determine if the commands should be run as tasks.
     */
    protected function shouldRunAsTask(OutputInterface $output, array $commands): bool
    {
        return function_exists('Laravel\Prompts\task')
            && function_exists('pcntl_fork')
            && ! array_is_list($commands)
            && ! $this->agent->isActive() && $this->useConciseOutput($output);
    }

    /**
     * Run the given shell commands within a Laravel Prompts task.
     *
     * @param  non-empty-array<string, non-empty-array<int, string>>  $commands
     */
    protected function runCommandsAsTask(
        array $commands,
        ?string $workingPath,
        array $env,
        ?string $taskLabel = null,
    ): Process {
        return task(
            label: $taskLabel ? str($taskLabel)->finish('...') : '',
            keepSummary: true,
            callback: function (Logger $logger) use ($commands, $workingPath, $env, $taskLabel) {
                foreach ($commands as $label => $subCommands) {
                    foreach ($subCommands as $command) {
                        $logger->subLabel($command);

                        $process = Process::fromShellCommandline($command, $workingPath, $env, null, null);
                        $process->run(function ($type, $line) use ($logger) {
                            $logger->line($line);
                        });

                        if (! $process->isSuccessful()) {
                            $logger->error($label);
                            $logger->error('Command failed: '.$command);
                            $logger->error('Error output: '.trim($process->getErrorOutput()));

                            return $process;
                        }
                    }

                    $logger->success($label);
                }

                if ($taskLabel) {
                    $logger->label($taskLabel);
                }

                return $process;
            },
        );
    }

    /**
     * Run the given command on Windows with inherited stdio for interactive support.
     */
    protected function runCommandsInteractivelyOnWindows(string $commandline, ?string $workingPath, array $env): Process
    {
        $descriptors = [
            0 => STDIN,
            1 => STDOUT,
            2 => STDERR,
        ];

        $envPairs = $env !== [] ? array_filter(array_merge($_SERVER, $_ENV, $env), fn ($v) => ! is_array($v)) : null;

        $proc = proc_open($commandline, $descriptors, $pipes, $workingPath, $envPairs);

        if (is_resource($proc)) {
            $exitCode = proc_close($proc);
        } else {
            $exitCode = 1;
        }

        // Return a completed Process instance that reflects the actual exit code...
        $sentinel = Process::fromShellCommandline('exit '.$exitCode, $workingPath);

        $sentinel->run();

        return $sentinel;
    }

    /**
     * Replace the given file.
     *
     * @return void
     */
    protected function replaceFile(string $replace, string $file)
    {
        $stubs = dirname(__DIR__).'/stubs';

        file_put_contents(
            $file,
            file_get_contents("$stubs/$replace"),
        );
    }

    /**
     * Replace the given string in the given file.
     *
     * @return void
     */
    protected function replaceInFile(string|array $search, string|array $replace, string $file)
    {
        file_put_contents(
            $file,
            str_replace($search, $replace, file_get_contents($file))
        );
    }

    /**
     * Replace the given string in the given file using regular expressions.
     *
     * @param  string|array  $search
     * @param  string|array  $replace
     * @return void
     */
    protected function pregReplaceInFile(string $pattern, string $replace, string $file)
    {
        file_put_contents(
            $file,
            preg_replace($pattern, $replace, file_get_contents($file))
        );
    }

    protected function loadHerdConfig() {
        try {
            $this->herdConfig = HerdConfiguration::load();
        } catch (\Throwable $e) {
            //
        }
    }

    /**
     * Delete the given file.
     *
     * @return void
     */
    protected function deleteFile(string $file)
    {
        unlink($file);
    }

    /**
     * Determine if concise output should be used.
     */
    protected function useConciseOutput(OutputInterface $output): bool
    {
        return $output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL || $output->isQuiet();
    }
}
<?php

namespace Laravel\Installer\Console\Concerns;

use Symfony\Component\Process\Exception\ProcessStartFailedException;
use Symfony\Component\Process\Process;

trait InteractsWithHerdOrValet
{
    /**
     * Determine if the given directory is parked using Herd or Valet.
     *
     * @return bool
     */
    public function isParkedOnHerdOrValet(string $directory)
    {
        $output = $this->runOnValetOrHerd('paths');

        $decodedOutput = json_decode($output);

        return is_array($decodedOutput) &&
            (in_array(dirname($directory), $decodedOutput) ||
             in_array(dirname($directory).DIRECTORY_SEPARATOR, $decodedOutput));
    }

    /**
     * Runs the given command on the "herd" or "valet" CLI.
     *
     * @return string|false
     */
    protected function runOnValetOrHerd(string $command)
    {
        foreach (['herd', 'valet'] as $tool) {
            $process = new Process([$tool, $command, '-v']);

            try {
                $process->run();

                if ($process->isSuccessful()) {
                    return trim($process->getOutput());
                }
            } catch (ProcessStartFailedException) {
            }
        }

        return false;
    }
}
<?php

namespace Laravel\Installer\Console\Concerns;

use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\MultiSelectPrompt;
use Laravel\Prompts\PasswordPrompt;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\SelectPrompt;
use Laravel\Prompts\SuggestPrompt;
use Laravel\Prompts\TextPrompt;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;

trait ConfiguresPrompts
{
    /**
     * Configure the prompt fallbacks.
     *
     * @return void
     */
    protected function configurePrompts(InputInterface $input, OutputInterface $output)
    {
        Prompt::fallbackWhen(! $input->isInteractive() || PHP_OS_FAMILY === 'Windows');

        TextPrompt::fallbackUsing(fn (TextPrompt $prompt) => $this->promptUntilValid(
            fn () => (new SymfonyStyle($input, $output))->ask($prompt->label, $prompt->default ?: null) ?? '',
            $prompt->required,
            $prompt->validate,
            $output
        ));

        PasswordPrompt::fallbackUsing(fn (PasswordPrompt $prompt) => $this->promptUntilValid(
            fn () => (new SymfonyStyle($input, $output))->askHidden($prompt->label) ?? '',
            $prompt->required,
            $prompt->validate,
            $output
        ));

        ConfirmPrompt::fallbackUsing(fn (ConfirmPrompt $prompt) => $this->promptUntilValid(
            fn () => (new SymfonyStyle($input, $output))->confirm($prompt->label, $prompt->default),
            $prompt->required,
            $prompt->validate,
            $output
        ));

        SelectPrompt::fallbackUsing(fn (SelectPrompt $prompt) => $this->promptUntilValid(
            fn () => (new SymfonyStyle($input, $output))->choice($prompt->label, $prompt->options, $prompt->default),
            false,
            $prompt->validate,
            $output
        ));

        MultiSelectPrompt::fallbackUsing(function (MultiSelectPrompt $prompt) use ($input, $output) {
            if ($prompt->default !== []) {
                return $this->promptUntilValid(
                    fn () => (new SymfonyStyle($input, $output))->choice($prompt->label, $prompt->options, implode(',', $prompt->default), true),
                    $prompt->required,
                    $prompt->validate,
                    $output
                );
            }

            return $this->promptUntilValid(
                fn () => collect((new SymfonyStyle($input, $output))->choice(
                    $prompt->label,
                    array_is_list($prompt->options)
                        ? ['None', ...$prompt->options]
                        : ['none' => 'None', ...$prompt->options],
                    'None',
                    true)
                )->reject(array_is_list($prompt->options) ? 'None' : 'none')->all(),
                $prompt->required,
                $prompt->validate,
                $output
            );
        });

        SuggestPrompt::fallbackUsing(fn (SuggestPrompt $prompt) => $this->promptUntilValid(
            function () use ($prompt, $input, $output) {
                $question = new Question($prompt->label, $prompt->default);

                is_callable($prompt->options)
                    ? $question->setAutocompleterCallback($prompt->options)
                    : $question->setAutocompleterValues($prompt->options);

                return (new SymfonyStyle($input, $output))->askQuestion($question);
            },
            $prompt->required,
            $prompt->validate,
            $output
        ));
    }

    /**
     * Prompt the user until the given validation callback passes.
     *
     * @param  \Closure  $prompt
     * @param  bool|string  $required
     * @param  \Closure|null  $validate
     * @param  OutputInterface  $output
     * @return mixed
     */
    protected function promptUntilValid($prompt, $required, $validate, $output)
    {
        while (true) {
            $result = $prompt();

            if ($required && ($result === '' || $result === [] || $result === false)) {
                $output->writeln('<error>'.(is_string($required) ? $required : 'Required.').'</error>');

                continue;
            }

            if ($validate) {
                $error = $validate($result);

                if (is_string($error) && strlen($error) > 0) {
                    $output->writeln("<error>{$error}</error>");

                    continue;
                }
            }

            return $result;
        }
    }
}
<?php

namespace Laravel\Installer\Console\Enums;

enum NodePackageManager: string
{
    case NPM = 'npm';
    case YARN = 'yarn';
    case PNPM = 'pnpm';
    case BUN = 'bun';

    public function installCommand(): string
    {
        return match ($this) {
            self::NPM => 'npm install --ignore-scripts',
            self::YARN => 'yarn install --ignore-scripts',
            self::PNPM => 'pnpm install --ignore-scripts',
            self::BUN => 'bun install --ignore-scripts',
        };
    }

    public function runCommand(): string
    {
        return match ($this) {
            self::NPM => 'npm run',
            self::YARN => 'yarn',
            self::PNPM => 'pnpm',
            self::BUN => 'bun run',
        };
    }

    public function buildCommand(): string
    {
        return $this->runCommand().' build';
    }

    public function runLocalOrRemoteCommand(): string
    {
        return match ($this) {
            self::NPM => 'npx',
            self::YARN => 'npx',
            self::PNPM => 'pnpm dlx',
            self::BUN => 'bunx',
        };
    }

    public static function allLockFiles(): array
    {
        return ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lock', 'bun.lockb'];
    }

    public function lockFiles(): array
    {
        return match ($this) {
            self::NPM => ['package-lock.json'],
            self::YARN => ['yarn.lock'],
            self::PNPM => ['pnpm-lock.yaml'],
            self::BUN => ['bun.lock', 'bun.lockb'],
        };
    }
}
<?php

namespace Laravel\Installer\Console;

use Laravel\AgentDetector\AgentDetector;
use Laravel\AgentDetector\AgentResult;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;

class Agent
{
    protected ?AgentResult $result;

    /**
     * The resolved installation name, captured for the JSON output.
     */
    protected ?string $name = null;

    /**
     * The resolved installation directory, captured for the JSON output.
     */
    protected ?string $directory = null;

    /**
     * Path to the subprocess log file, when one is open.
     */
    protected ?string $logPath = null;

    /**
     * Open file handle for the subprocess log, when one is open.
     *
     * @var resource|null
     */
    protected $logHandle = null;

    /**
     * Whether or not the command succeeded.
     */
    protected bool $succeeded = false;

    public function __construct()
    {
        $this->result = AgentDetector::detect();
    }

    /**
     * Determine whether the command is running under a detected agent.
     */
    public function isActive(): bool
    {
        return $this->result?->isAgent ?? false;
    }

    /**
     * The detected agent name, if any.
     */
    public function name(): ?string
    {
        return $this->result?->knownAgent()?->label();
    }

    /**
     * Capture the resolved installation details for the JSON output.
     */
    public function rememberInstallation(string $directory): void
    {
        $this->directory = $directory;
        $this->name = basename($directory === '.' ? (string) getcwd() : $directory);
    }

    /**
     * Open a log destination to capture subprocess output during agent runs.
     */
    public function openLog(): StreamOutput
    {
        [$path, $handle] = $this->resolveLogPathAndHandle();

        $this->logPath = $path;
        $this->logHandle = $handle;

        return new StreamOutput($handle, OutputInterface::VERBOSITY_NORMAL, false);
    }

    /**
     * Emit a successful agent result with optional extra payload.
     */
    public function emitSuccess(array $extra = []): void
    {
        $this->discardLog();
        $this->emit(true, $extra);
    }

    /**
     * Emit a failed agent result with optional extra payload, merged with log details.
     */
    public function emitFailure(array $extra = []): void
    {
        $this->emit(false, $extra + $this->failureDetails());
    }

    /**
     * Read the last N lines of the agent log, with ANSI escapes stripped.
     */
    public function readLogTail(string $path, int $lines = 50): string
    {
        $content = @file_get_contents($path);

        if ($content === false) {
            return '';
        }

        return $this->formatTail($content, $lines);
    }

    /**
     * Close and remove the agent log file (used on the success path).
     */
    protected function discardLog(): void
    {
        if (is_resource($this->logHandle)) {
            @fclose($this->logHandle);
            $this->logHandle = null;
        }

        if ($this->logPath !== null) {
            @unlink($this->logPath);
            $this->logPath = null;
        }
    }

    /**
     * Build the log + tail fields for the agent failure payload.
     */
    protected function failureDetails(): array
    {
        if (! is_resource($this->logHandle)) {
            return [];
        }

        @fflush($this->logHandle);

        $details = [];

        if ($this->logPath !== null && file_exists($this->logPath)) {
            $details['log'] = $this->logPath;
            $details['tail'] = $this->readLogTail($this->logPath);
        } else {
            @rewind($this->logHandle);
            $content = stream_get_contents($this->logHandle);
            $details['tail'] = $this->formatTail($content === false ? '' : $content);
        }

        @fclose($this->logHandle);
        $this->logHandle = null;

        return $details;
    }

    /**
     * Write the minimal JSON result for agent invocations.
     */
    protected function emit(bool $success, array $extra = []): void
    {
        $payload = ['success' => $success];

        if ($this->name !== null) {
            $payload['name'] = $this->name;
        }

        if ($this->directory !== null) {
            $payload['directory'] = $this->directory;
        }

        foreach ($extra as $key => $value) {
            $payload[$key] = $value;
        }

        fwrite(STDOUT, json_encode($payload, JSON_UNESCAPED_SLASHES).PHP_EOL);
    }

    /**
     * Attempt to open a temporary file for logging, falling back to an in-memory stream on failure.
     *
     * @return array{string|null, resource}
     */
    protected function resolveLogPathAndHandle(): array
    {
        $path = tempnam(sys_get_temp_dir(), 'laravel-installer-');
        $handle = $path !== false ? @fopen($path, 'w+') : false;

        if ($handle !== false) {
            return [$path, $handle];
        }

        if ($path !== false) {
            @unlink($path);
        }

        $handle = fopen('php://temp', 'w+');

        return [$path, $handle];
    }

    /**
     * Strip ANSI escapes and return the last N lines of the given content.
     */
    protected function formatTail(string $content, int $lines = 50): string
    {
        if ($content === '') {
            return '';
        }

        $stripped = preg_replace('/\x1b\[[0-9;?]*[a-zA-Z]/', '', $content);
        $allLines = preg_split("/\r\n|\n|\r/", rtrim($stripped ?? $content));

        return implode("\n", array_slice($allLines, -$lines));
    }
}
<?php

if (file_exists(__DIR__.'/../../../autoload.php')) {
    require __DIR__.'/../../../autoload.php';
} else {
    require __DIR__.'/../vendor/autoload.php';
}

$app = new Symfony\Component\Console\Application('Laravel Installer', '5.28.1');

if (method_exists($app, 'addCommand')) {
    $app->addCommand(new Laravel\Installer\Console\NewCommand);
} else {
    $app->add(new Laravel\Installer\Console\NewCommand);
}

$app->run();
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

use Carbon\CarbonImmutable;
use DateTimeImmutable;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\VarDateTimeImmutableType;

class DateTimeImmutableType extends VarDateTimeImmutableType implements CarbonDoctrineType
{
    /** @use CarbonTypeConverter<CarbonImmutable> */
    use CarbonTypeConverter;

    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?CarbonImmutable
    {
        return $this->doConvertToPHPValue($value);
    }

    /**
     * @return class-string<CarbonImmutable>
     */
    protected function getCarbonClassName(): string
    {
        return CarbonImmutable::class;
    }
}
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

use Carbon\Carbon;
use Carbon\CarbonInterface;
use DateTimeInterface;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\DB2Platform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\DBAL\Types\Exception\InvalidType;
use Doctrine\DBAL\Types\Exception\ValueNotConvertible;
use Exception;

/**
 * @template T of CarbonInterface
 */
trait CarbonTypeConverter
{
    /**
     * This property differentiates types installed by carbonphp/carbon-doctrine-types
     * from the ones embedded previously in nesbot/carbon source directly.
     *
     * @readonly
     */
    public bool $external = true;

    /**
     * @return class-string<T>
     */
    protected function getCarbonClassName(): string
    {
        return Carbon::class;
    }

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        $precision = min(
            $fieldDeclaration['precision'] ?? DateTimeDefaultPrecision::get(),
            $this->getMaximumPrecision($platform),
        );

        $type = parent::getSQLDeclaration($fieldDeclaration, $platform);

        if (!$precision) {
            return $type;
        }

        if (str_contains($type, '(')) {
            return preg_replace('/\(\d+\)/', "($precision)", $type);
        }

        [$before, $after] = explode(' ', "$type ");

        return trim("$before($precision) $after");
    }

    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
    {
        if ($value === null) {
            return $value;
        }

        if ($value instanceof DateTimeInterface) {
            return $value->format('Y-m-d H:i:s.u');
        }

        throw InvalidType::new(
            $value,
            static::class,
            ['null', 'DateTime', 'Carbon']
        );
    }

    private function doConvertToPHPValue(mixed $value)
    {
        $class = $this->getCarbonClassName();

        if ($value === null || is_a($value, $class)) {
            return $value;
        }

        if ($value instanceof DateTimeInterface) {
            return $class::instance($value);
        }

        $date = null;
        $error = null;

        try {
            $date = $class::parse($value);
        } catch (Exception $exception) {
            $error = $exception;
        }

        if (!$date) {
            throw ValueNotConvertible::new(
                $value,
                static::class,
                'Y-m-d H:i:s.u or any format supported by '.$class.'::parse()',
                $error
            );
        }

        return $date;
    }

    private function getMaximumPrecision(AbstractPlatform $platform): int
    {
        if ($platform instanceof DB2Platform) {
            return 12;
        }

        if ($platform instanceof OraclePlatform) {
            return 9;
        }

        if ($platform instanceof SQLServerPlatform || $platform instanceof SQLitePlatform) {
            return 3;
        }

        return 6;
    }
}
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

use Doctrine\DBAL\Platforms\AbstractPlatform;

interface CarbonDoctrineType
{
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform);

    public function convertToPHPValue(mixed $value, AbstractPlatform $platform);

    public function convertToDatabaseValue($value, AbstractPlatform $platform);
}
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

class DateTimeDefaultPrecision
{
    private static $precision = 6;

    /**
     * Change the default Doctrine datetime and datetime_immutable precision.
     *
     * @param int $precision
     */
    public static function set(int $precision): void
    {
        self::$precision = $precision;
    }

    /**
     * Get the default Doctrine datetime and datetime_immutable precision.
     *
     * @return int
     */
    public static function get(): int
    {
        return self::$precision;
    }
}
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

class CarbonType extends DateTimeType implements CarbonDoctrineType
{
}
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

use Carbon\Carbon;
use DateTime;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\VarDateTimeType;

class DateTimeType extends VarDateTimeType implements CarbonDoctrineType
{
    /** @use CarbonTypeConverter<Carbon> */
    use CarbonTypeConverter;

    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Carbon
    {
        return $this->doConvertToPHPValue($value);
    }
}
<?php

declare(strict_types=1);

namespace Carbon\Doctrine;

class CarbonImmutableType extends DateTimeImmutableType implements CarbonDoctrineType
{
}
MIT License

Copyright (c) 2023 Carbon

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<?php

namespace BeyondCode\HerdConfiguration;

class HerdConfiguration
{
    protected string $operatingSystem = '';

    /**
     * @var bool
     * Whether or not the interception is globally enabled by the user.
     */
    protected bool $interceptionEnabled = false;

    /**
     * @var bool
     * Whether or not the mail service is enabled.
     * As soon as the license is pro, this is always true.
     */
    protected bool $mailsEnabled = false;

    /**
     * @var int
     * The port on which the SMTP server for
     * the mail service is running.
     */
    protected int $smtpPort = 2525;

    /**
     * @var int
     * The port for the API server which serves as a bridge for the CLI on Windows.
     *
     * Windows only.
     */
    protected int $apiPort = 2304;

    protected bool $watchViaCLI = false;
    protected bool $watchDumps = true;
    protected bool $watchEvents = false;
    protected bool $watchLogs = true;
    protected bool $watchQueries = true;
    protected bool $watchHttpClient = true;
    protected bool $watchViews = true;
    protected bool $watchCache = true;

    public static function load(): self
    {
        if(array_key_exists('HERD_CONFIG_TEST', $_SERVER) && array_key_exists('HERD_CONFIG_JSON', $_SERVER) && $_SERVER['HERD_CONFIG_TEST'] === true) {
            return self::fromJson($_SERVER['HERD_CONFIG_JSON']);
        }

        $config = new self();
        $config->detectOperatingSystem();

        $file = $config->loadConfigFile();

        $config->fill($file);

        return $config;
    }

    public function isWindows(): bool
    {
        return $this->operatingSystem === 'windows';
    }

    public function isMac(): bool
    {
        return $this->operatingSystem === 'mac';
    }

    public function isLinux(): bool
    {
        return $this->operatingSystem === 'linux';
    }

    public function isPro(): bool
    {
        // so far, we can detect a pro license by checking if the mails are active
        return $this->mailsEnabled();
    }

    public function interceptionEnabled(): bool
    {
        return $this->interceptionEnabled;
    }

    public function dumpsEnabled(): bool
    {
        return $this->interceptionEnabled;
    }

    public function mailsEnabled(): bool
    {
        return $this->mailsEnabled;
    }

    public function watchViaCLI(): bool
    {
        return $this->watchViaCLI;
    }

    public function watchLogs(): bool
    {
        return $this->watchLogs;
    }

    public function watchEvents(): bool
    {
        return $this->watchEvents;
    }

    public function watchQueries(): bool
    {
        return $this->watchQueries;
    }

    public function watchHttpClient(): bool
    {
        return $this->watchHttpClient;
    }

    public function watchViews(): bool
    {
        return $this->watchViews;
    }

    public function watchCache(): bool
    {
        return $this->watchCache;
    }

    public function watchDumps(): bool
    {
        return $this->watchDumps;
    }

    public function watchDumpsInCurrentEnvironment(): bool
    {
        $sapi = php_sapi_name();

        if ($sapi !== 'cli') {
            return $this->watchDumps;
        }

        return $this->watchDumps && $this->watchViaCLI;
    }

    public function smtpPort(): int
    {
        return $this->smtpPort;
    }

    public function apiPort(): int
    {
        return $this->apiPort;
    }

    protected function fill(string $json): self
    {
        $config = json_decode($json, true);
        
        if (!is_array($config)) {
            $config = [];
        }

        $this->interceptionEnabled = array_key_exists('dumps', $config) && $config['dumps'] === true;
        $this->mailsEnabled = array_key_exists('mails', $config) && $config['mails'] === true;

        $this->smtpPort = (array_key_exists('smtpPort', $config) && $config['smtpPort']) ? $config['smtpPort'] : 2525;
        $this->apiPort = (array_key_exists('apiPort', $config) && $config['apiPort']) ? $config['apiPort'] : 2304;

        $this->watchViaCLI = array_key_exists('watchViaCLI', $config) && $config['watchViaCLI'] === true;

        $this->watchLogs = array_key_exists('watchLogs', $config) && $config['watchLogs'] === true;
        $this->watchEvents = array_key_exists('watchEvents', $config) && $config['watchEvents'] === true;
        $this->watchQueries = array_key_exists('watchQueries', $config) && $config['watchQueries'] === true;
        $this->watchHttpClient = array_key_exists('watchHttpClient', $config) && $config['watchHttpClient'] === true;
        $this->watchViews = array_key_exists('watchViews', $config) && $config['watchViews'] === true;
        $this->watchCache = array_key_exists('watchCache', $config) && $config['watchCache'] === true;
        $this->watchDumps = array_key_exists('watchDumps', $config) && $config['watchDumps'] === true;

        return $this;
    }

    protected function detectOperatingSystem() {
        $uname = php_uname('s');

        if (strpos($uname, 'Windows') !== false) {
            $this->operatingSystem = 'windows';
        } elseif (strpos($uname, 'Linux') !== false) {
            $this->operatingSystem = 'linux';
        } else {
            $this->operatingSystem = 'mac';
        }
    }



    public static function fromJson(string $json): self
    {
        $config = new self();

        $config->detectOperatingSystem();

        $config->fill($json);

        return $config;
    }


    protected function loadConfigFile(?string $path = null)
    {
        if ($path === null) {
            $path = $this->getConfigPath();
        }

        if (!file_exists($path)) {
            throw new \Exception("Herd configuration file not found at {$path}");
        }

        $herdConfig = file_get_contents($path);

        return $herdConfig;
    }

    protected function getConfigPath()
    {
        if($this->operatingSystem === null) return;

        $configPath = '';

        if (array_key_exists('HOME', $_SERVER)) {
            if ($this->isWindows()) {
                $configPath = $_SERVER['HOME'] . '\.config\herd\config\config.json';
            } elseif ($this->isLinux()) {
                $configPath = $_SERVER['HOME'] . '/.config/herd/config/herd.json';
            } else {
                $configPath = $_SERVER['HOME'] . '/Library/Application Support/Herd/config/herd.json';
            }
        } else if (array_key_exists('HOMEPATH', $_SERVER) && array_key_exists('HOMEDRIVE', $_SERVER)) {
            $configPath = $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH'] . '\.config\herd\config\config.json';
        }

        return $configPath;
    }

    public static function getIniValues()
    {
        $uname = php_uname('s');

        if (strpos($uname, 'Windows') !== false) {
            $operatingSystem = 'windows';
        } elseif (strpos($uname, 'Linux') !== false) {
            $operatingSystem = 'linux';
        } else {
            $operatingSystem = 'mac';
        }

        $configPath = '';
        if (array_key_exists('HOME', $_SERVER)) {
            if ($operatingSystem === 'windows') {
                $configPath = $_SERVER['HOME'] . '\.config\herd\bin\\';
            } elseif ($operatingSystem === 'linux') {
                $configPath = $_SERVER['HOME'] . '/.config/herd/config/php/';
            } else {
                $configPath = $_SERVER['HOME'] . '/Library/Application Support/Herd/config/php/';
            }
        } else if (array_key_exists('HOMEPATH', $_SERVER) && array_key_exists('HOMEDRIVE', $_SERVER)) {
            $configPath = $_SERVER['HOMEDRIVE'] . $_SERVER['HOMEPATH'] . '\.config\herd\bin\\';
        }

        if ($operatingSystem === 'mac' || $operatingSystem === 'linux') {
            $filename = $configPath . PHP_MAJOR_VERSION . PHP_MINOR_VERSION . '/php.ini';
        } else {
            $filename = $configPath . "php" . PHP_MAJOR_VERSION . PHP_MINOR_VERSION . '\php.ini';
        }

        if (!file_exists($filename)) {
            return [];
        }

        return parse_ini_file($filename) ?: [];
    }
}
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    /** @var \Closure(string):void */
    private static $includeFile;

    /** @var string|null */
    private $vendorDir;

    // PSR-4
    /**
     * @var array<string, array<string, int>>
     */
    private $prefixLengthsPsr4 = array();
    /**
     * @var array<string, list<string>>
     */
    private $prefixDirsPsr4 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr4 = array();

    // PSR-0
    /**
     * List of PSR-0 prefixes
     *
     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     *
     * @var array<string, array<string, list<string>>>
     */
    private $prefixesPsr0 = array();
    /**
     * @var list<string>
     */
    private $fallbackDirsPsr0 = array();

    /** @var bool */
    private $useIncludePath = false;

    /**
     * @var array<string, string>
     */
    private $classMap = array();

    /** @var bool */
    private $classMapAuthoritative = false;

    /**
     * @var array<string, bool>
     */
    private $missingClasses = array();

    /** @var string|null */
    private $apcuPrefix;

    /**
     * @var array<string, self>
     */
    private static $registeredLoaders = array();

    /**
     * @param string|null $vendorDir
     */
    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
        self::initializeIncludeClosure();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }

        return array();
    }

    /**
     * @return array<string, list<string>>
     */
    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    /**
     * @return list<string>
     */
    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    /**
     * @return array<string, string> Array of classname => path
     */
    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array<string, string> $classMap Class to filename map
     *
     * @return void
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string              $prefix  The prefix
     * @param list<string>|string $paths   The PSR-0 root directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @return void
     */
    public function add($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths   The PSR-4 base directories
     * @param bool                $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        $paths = (array) $paths;
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string              $prefix The prefix
     * @param list<string>|string $paths  The PSR-0 base directories
     *
     * @return void
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string              $prefix The prefix/namespace, with trailing '\\'
     * @param list<string>|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     *
     * @return void
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     *
     * @return void
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     *
     * @return void
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     *
     * @return void
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);

        if (null === $this->vendorDir) {
            return;
        }

        if ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     *
     * @return void
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));

        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return true|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            $includeFile = self::$includeFile;
            $includeFile($file);

            return true;
        }

        return null;
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    /**
     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     *
     * @return array<string, self>
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }

    /**
     * @param  string       $class
     * @param  string       $ext
     * @return string|false
     */
    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }

    /**
     * @return void
     */
    private static function initializeIncludeClosure()
    {
        if (self::$includeFile !== null) {
            return;
        }

        /**
         * Scope isolated include.
         *
         * Prevents access to $this/self from included files.
         *
         * @param  string $file
         * @return void
         */
        self::$includeFile = \Closure::bind(static function($file) {
            include $file;
        }, null, null);
    }
}
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'BeyondCode\\HerdConfiguration\\HerdConfiguration' => $vendorDir . '/beyondcode/herd-configuration/src/HerdConfiguration.php',
    'Carbon\\AbstractTranslator' => $vendorDir . '/nesbot/carbon/src/Carbon/AbstractTranslator.php',
    'Carbon\\Callback' => $vendorDir . '/nesbot/carbon/src/Carbon/Callback.php',
    'Carbon\\Carbon' => $vendorDir . '/nesbot/carbon/src/Carbon/Carbon.php',
    'Carbon\\CarbonConverterInterface' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonConverterInterface.php',
    'Carbon\\CarbonImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonImmutable.php',
    'Carbon\\CarbonInterface' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonInterface.php',
    'Carbon\\CarbonInterval' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
    'Carbon\\CarbonPeriod' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonPeriod.php',
    'Carbon\\CarbonPeriodImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonPeriodImmutable.php',
    'Carbon\\CarbonTimeZone' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonTimeZone.php',
    'Carbon\\Cli\\Invoker' => $vendorDir . '/nesbot/carbon/src/Carbon/Cli/Invoker.php',
    'Carbon\\Constants\\DiffOptions' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/DiffOptions.php',
    'Carbon\\Constants\\Format' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/Format.php',
    'Carbon\\Constants\\TranslationOptions' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/TranslationOptions.php',
    'Carbon\\Constants\\UnitValue' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/UnitValue.php',
    'Carbon\\Doctrine\\CarbonDoctrineType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonDoctrineType.php',
    'Carbon\\Doctrine\\CarbonImmutableType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonImmutableType.php',
    'Carbon\\Doctrine\\CarbonType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonType.php',
    'Carbon\\Doctrine\\CarbonTypeConverter' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonTypeConverter.php',
    'Carbon\\Doctrine\\DateTimeDefaultPrecision' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeDefaultPrecision.php',
    'Carbon\\Doctrine\\DateTimeImmutableType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeImmutableType.php',
    'Carbon\\Doctrine\\DateTimeType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeType.php',
    'Carbon\\Exceptions\\BadComparisonUnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php',
    'Carbon\\Exceptions\\BadFluentConstructorException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.php',
    'Carbon\\Exceptions\\BadFluentSetterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php',
    'Carbon\\Exceptions\\BadMethodCallException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php',
    'Carbon\\Exceptions\\EndLessPeriodException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/EndLessPeriodException.php',
    'Carbon\\Exceptions\\Exception' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/Exception.php',
    'Carbon\\Exceptions\\ImmutableException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php',
    'Carbon\\Exceptions\\InvalidArgumentException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.php',
    'Carbon\\Exceptions\\InvalidCastException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php',
    'Carbon\\Exceptions\\InvalidDateException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php',
    'Carbon\\Exceptions\\InvalidFormatException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php',
    'Carbon\\Exceptions\\InvalidIntervalException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php',
    'Carbon\\Exceptions\\InvalidPeriodDateException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php',
    'Carbon\\Exceptions\\InvalidPeriodParameterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php',
    'Carbon\\Exceptions\\InvalidTimeZoneException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php',
    'Carbon\\Exceptions\\InvalidTypeException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php',
    'Carbon\\Exceptions\\NotACarbonClassException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php',
    'Carbon\\Exceptions\\NotAPeriodException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php',
    'Carbon\\Exceptions\\NotLocaleAwareException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php',
    'Carbon\\Exceptions\\OutOfRangeException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php',
    'Carbon\\Exceptions\\ParseErrorException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php',
    'Carbon\\Exceptions\\RuntimeException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.php',
    'Carbon\\Exceptions\\UnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnitException.php',
    'Carbon\\Exceptions\\UnitNotConfiguredException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php',
    'Carbon\\Exceptions\\UnknownGetterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php',
    'Carbon\\Exceptions\\UnknownMethodException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php',
    'Carbon\\Exceptions\\UnknownSetterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php',
    'Carbon\\Exceptions\\UnknownUnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php',
    'Carbon\\Exceptions\\UnreachableException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php',
    'Carbon\\Exceptions\\UnsupportedUnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnsupportedUnitException.php',
    'Carbon\\Factory' => $vendorDir . '/nesbot/carbon/src/Carbon/Factory.php',
    'Carbon\\FactoryImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/FactoryImmutable.php',
    'Carbon\\Language' => $vendorDir . '/nesbot/carbon/src/Carbon/Language.php',
    'Carbon\\Laravel\\ServiceProvider' => $vendorDir . '/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php',
    'Carbon\\MessageFormatter\\MessageFormatterMapper' => $vendorDir . '/nesbot/carbon/src/Carbon/MessageFormatter/MessageFormatterMapper.php',
    'Carbon\\Month' => $vendorDir . '/nesbot/carbon/src/Carbon/Month.php',
    'Carbon\\PHPStan\\MacroExtension' => $vendorDir . '/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php',
    'Carbon\\PHPStan\\MacroMethodReflection' => $vendorDir . '/nesbot/carbon/src/Carbon/PHPStan/MacroMethodReflection.php',
    'Carbon\\Traits\\Boundaries' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Boundaries.php',
    'Carbon\\Traits\\Cast' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Cast.php',
    'Carbon\\Traits\\Comparison' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Comparison.php',
    'Carbon\\Traits\\Converter' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Converter.php',
    'Carbon\\Traits\\Creator' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Creator.php',
    'Carbon\\Traits\\Date' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Date.php',
    'Carbon\\Traits\\DeprecatedPeriodProperties' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/DeprecatedPeriodProperties.php',
    'Carbon\\Traits\\Difference' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Difference.php',
    'Carbon\\Traits\\IntervalRounding' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php',
    'Carbon\\Traits\\IntervalStep' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/IntervalStep.php',
    'Carbon\\Traits\\LocalFactory' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/LocalFactory.php',
    'Carbon\\Traits\\Localization' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Localization.php',
    'Carbon\\Traits\\Macro' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Macro.php',
    'Carbon\\Traits\\MagicParameter' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/MagicParameter.php',
    'Carbon\\Traits\\Mixin' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Mixin.php',
    'Carbon\\Traits\\Modifiers' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Modifiers.php',
    'Carbon\\Traits\\Mutability' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Mutability.php',
    'Carbon\\Traits\\ObjectInitialisation' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php',
    'Carbon\\Traits\\Options' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Options.php',
    'Carbon\\Traits\\Rounding' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Rounding.php',
    'Carbon\\Traits\\Serialization' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Serialization.php',
    'Carbon\\Traits\\StaticLocalization' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/StaticLocalization.php',
    'Carbon\\Traits\\StaticOptions' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/StaticOptions.php',
    'Carbon\\Traits\\Test' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Test.php',
    'Carbon\\Traits\\Timestamp' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Timestamp.php',
    'Carbon\\Traits\\ToStringFormat' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/ToStringFormat.php',
    'Carbon\\Traits\\Units' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Units.php',
    'Carbon\\Traits\\Week' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Week.php',
    'Carbon\\Translator' => $vendorDir . '/nesbot/carbon/src/Carbon/Translator.php',
    'Carbon\\TranslatorImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/TranslatorImmutable.php',
    'Carbon\\TranslatorStrongTypeInterface' => $vendorDir . '/nesbot/carbon/src/Carbon/TranslatorStrongTypeInterface.php',
    'Carbon\\Unit' => $vendorDir . '/nesbot/carbon/src/Carbon/Unit.php',
    'Carbon\\WeekDay' => $vendorDir . '/nesbot/carbon/src/Carbon/WeekDay.php',
    'Carbon\\WrapperClock' => $vendorDir . '/nesbot/carbon/src/Carbon/WrapperClock.php',
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    'DateError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateError.php',
    'DateException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateException.php',
    'DateInvalidOperationException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php',
    'DateInvalidTimeZoneException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php',
    'DateMalformedIntervalStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php',
    'DateMalformedPeriodStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php',
    'DateMalformedStringException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php',
    'DateObjectError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php',
    'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
    'DelayedTargetValidation' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php',
    'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
    'Doctrine\\Inflector\\CachedWordInflector' => $vendorDir . '/doctrine/inflector/src/CachedWordInflector.php',
    'Doctrine\\Inflector\\GenericLanguageInflectorFactory' => $vendorDir . '/doctrine/inflector/src/GenericLanguageInflectorFactory.php',
    'Doctrine\\Inflector\\Inflector' => $vendorDir . '/doctrine/inflector/src/Inflector.php',
    'Doctrine\\Inflector\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/InflectorFactory.php',
    'Doctrine\\Inflector\\Language' => $vendorDir . '/doctrine/inflector/src/Language.php',
    'Doctrine\\Inflector\\LanguageInflectorFactory' => $vendorDir . '/doctrine/inflector/src/LanguageInflectorFactory.php',
    'Doctrine\\Inflector\\NoopWordInflector' => $vendorDir . '/doctrine/inflector/src/NoopWordInflector.php',
    'Doctrine\\Inflector\\Rules\\English\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/English/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\English\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/English/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\English\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/English/Rules.php',
    'Doctrine\\Inflector\\Rules\\English\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/English/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\Esperanto\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/Esperanto/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\Esperanto\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/Esperanto/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\Esperanto\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/Esperanto/Rules.php',
    'Doctrine\\Inflector\\Rules\\Esperanto\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/Esperanto/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\French\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/French/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\French\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/French/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\French\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/French/Rules.php',
    'Doctrine\\Inflector\\Rules\\French\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/French/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\Italian\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/Italian/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\Italian\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/Italian/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\Italian\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/Italian/Rules.php',
    'Doctrine\\Inflector\\Rules\\Italian\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/Italian/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/NorwegianBokmal/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/NorwegianBokmal/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/NorwegianBokmal/Rules.php',
    'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/NorwegianBokmal/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\Pattern' => $vendorDir . '/doctrine/inflector/src/Rules/Pattern.php',
    'Doctrine\\Inflector\\Rules\\Patterns' => $vendorDir . '/doctrine/inflector/src/Rules/Patterns.php',
    'Doctrine\\Inflector\\Rules\\Portuguese\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/Portuguese/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\Portuguese\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/Portuguese/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\Portuguese\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/Portuguese/Rules.php',
    'Doctrine\\Inflector\\Rules\\Portuguese\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/Portuguese/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\Ruleset' => $vendorDir . '/doctrine/inflector/src/Rules/Ruleset.php',
    'Doctrine\\Inflector\\Rules\\Spanish\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/Spanish/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\Spanish\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/Spanish/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\Spanish\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/Spanish/Rules.php',
    'Doctrine\\Inflector\\Rules\\Spanish\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/Spanish/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\Substitution' => $vendorDir . '/doctrine/inflector/src/Rules/Substitution.php',
    'Doctrine\\Inflector\\Rules\\Substitutions' => $vendorDir . '/doctrine/inflector/src/Rules/Substitutions.php',
    'Doctrine\\Inflector\\Rules\\Transformation' => $vendorDir . '/doctrine/inflector/src/Rules/Transformation.php',
    'Doctrine\\Inflector\\Rules\\Transformations' => $vendorDir . '/doctrine/inflector/src/Rules/Transformations.php',
    'Doctrine\\Inflector\\Rules\\Turkish\\Inflectible' => $vendorDir . '/doctrine/inflector/src/Rules/Turkish/Inflectible.php',
    'Doctrine\\Inflector\\Rules\\Turkish\\InflectorFactory' => $vendorDir . '/doctrine/inflector/src/Rules/Turkish/InflectorFactory.php',
    'Doctrine\\Inflector\\Rules\\Turkish\\Rules' => $vendorDir . '/doctrine/inflector/src/Rules/Turkish/Rules.php',
    'Doctrine\\Inflector\\Rules\\Turkish\\Uninflected' => $vendorDir . '/doctrine/inflector/src/Rules/Turkish/Uninflected.php',
    'Doctrine\\Inflector\\Rules\\Word' => $vendorDir . '/doctrine/inflector/src/Rules/Word.php',
    'Doctrine\\Inflector\\RulesetInflector' => $vendorDir . '/doctrine/inflector/src/RulesetInflector.php',
    'Doctrine\\Inflector\\WordInflector' => $vendorDir . '/doctrine/inflector/src/WordInflector.php',
    'Filter\\FilterException' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterException.php',
    'Filter\\FilterFailedException' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterFailedException.php',
    'Illuminate\\Contracts\\Auth\\Access\\Authorizable' => $vendorDir . '/illuminate/contracts/Auth/Access/Authorizable.php',
    'Illuminate\\Contracts\\Auth\\Access\\Gate' => $vendorDir . '/illuminate/contracts/Auth/Access/Gate.php',
    'Illuminate\\Contracts\\Auth\\Authenticatable' => $vendorDir . '/illuminate/contracts/Auth/Authenticatable.php',
    'Illuminate\\Contracts\\Auth\\CanResetPassword' => $vendorDir . '/illuminate/contracts/Auth/CanResetPassword.php',
    'Illuminate\\Contracts\\Auth\\Factory' => $vendorDir . '/illuminate/contracts/Auth/Factory.php',
    'Illuminate\\Contracts\\Auth\\Guard' => $vendorDir . '/illuminate/contracts/Auth/Guard.php',
    'Illuminate\\Contracts\\Auth\\Middleware\\AuthenticatesRequests' => $vendorDir . '/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.php',
    'Illuminate\\Contracts\\Auth\\MustVerifyEmail' => $vendorDir . '/illuminate/contracts/Auth/MustVerifyEmail.php',
    'Illuminate\\Contracts\\Auth\\PasswordBroker' => $vendorDir . '/illuminate/contracts/Auth/PasswordBroker.php',
    'Illuminate\\Contracts\\Auth\\PasswordBrokerFactory' => $vendorDir . '/illuminate/contracts/Auth/PasswordBrokerFactory.php',
    'Illuminate\\Contracts\\Auth\\StatefulGuard' => $vendorDir . '/illuminate/contracts/Auth/StatefulGuard.php',
    'Illuminate\\Contracts\\Auth\\SupportsBasicAuth' => $vendorDir . '/illuminate/contracts/Auth/SupportsBasicAuth.php',
    'Illuminate\\Contracts\\Auth\\UserProvider' => $vendorDir . '/illuminate/contracts/Auth/UserProvider.php',
    'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => $vendorDir . '/illuminate/contracts/Broadcasting/Broadcaster.php',
    'Illuminate\\Contracts\\Broadcasting\\Factory' => $vendorDir . '/illuminate/contracts/Broadcasting/Factory.php',
    'Illuminate\\Contracts\\Broadcasting\\HasBroadcastChannel' => $vendorDir . '/illuminate/contracts/Broadcasting/HasBroadcastChannel.php',
    'Illuminate\\Contracts\\Broadcasting\\ShouldBeUnique' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldBeUnique.php',
    'Illuminate\\Contracts\\Broadcasting\\ShouldBroadcast' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldBroadcast.php',
    'Illuminate\\Contracts\\Broadcasting\\ShouldBroadcastNow' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldBroadcastNow.php',
    'Illuminate\\Contracts\\Broadcasting\\ShouldRescue' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldRescue.php',
    'Illuminate\\Contracts\\Bus\\Dispatcher' => $vendorDir . '/illuminate/contracts/Bus/Dispatcher.php',
    'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => $vendorDir . '/illuminate/contracts/Bus/QueueingDispatcher.php',
    'Illuminate\\Contracts\\Cache\\CanFlushLocks' => $vendorDir . '/illuminate/contracts/Cache/CanFlushLocks.php',
    'Illuminate\\Contracts\\Cache\\Factory' => $vendorDir . '/illuminate/contracts/Cache/Factory.php',
    'Illuminate\\Contracts\\Cache\\Lock' => $vendorDir . '/illuminate/contracts/Cache/Lock.php',
    'Illuminate\\Contracts\\Cache\\LockProvider' => $vendorDir . '/illuminate/contracts/Cache/LockProvider.php',
    'Illuminate\\Contracts\\Cache\\LockTimeoutException' => $vendorDir . '/illuminate/contracts/Cache/LockTimeoutException.php',
    'Illuminate\\Contracts\\Cache\\Repository' => $vendorDir . '/illuminate/contracts/Cache/Repository.php',
    'Illuminate\\Contracts\\Cache\\Store' => $vendorDir . '/illuminate/contracts/Cache/Store.php',
    'Illuminate\\Contracts\\Concurrency\\Driver' => $vendorDir . '/illuminate/contracts/Concurrency/Driver.php',
    'Illuminate\\Contracts\\Config\\Repository' => $vendorDir . '/illuminate/contracts/Config/Repository.php',
    'Illuminate\\Contracts\\Console\\Application' => $vendorDir . '/illuminate/contracts/Console/Application.php',
    'Illuminate\\Contracts\\Console\\Isolatable' => $vendorDir . '/illuminate/contracts/Console/Isolatable.php',
    'Illuminate\\Contracts\\Console\\Kernel' => $vendorDir . '/illuminate/contracts/Console/Kernel.php',
    'Illuminate\\Contracts\\Console\\PromptsForMissingInput' => $vendorDir . '/illuminate/contracts/Console/PromptsForMissingInput.php',
    'Illuminate\\Contracts\\Container\\BindingResolutionException' => $vendorDir . '/illuminate/contracts/Container/BindingResolutionException.php',
    'Illuminate\\Contracts\\Container\\CircularDependencyException' => $vendorDir . '/illuminate/contracts/Container/CircularDependencyException.php',
    'Illuminate\\Contracts\\Container\\Container' => $vendorDir . '/illuminate/contracts/Container/Container.php',
    'Illuminate\\Contracts\\Container\\ContextualAttribute' => $vendorDir . '/illuminate/contracts/Container/ContextualAttribute.php',
    'Illuminate\\Contracts\\Container\\ContextualBindingBuilder' => $vendorDir . '/illuminate/contracts/Container/ContextualBindingBuilder.php',
    'Illuminate\\Contracts\\Container\\SelfBuilding' => $vendorDir . '/illuminate/contracts/Container/SelfBuilding.php',
    'Illuminate\\Contracts\\Cookie\\Factory' => $vendorDir . '/illuminate/contracts/Cookie/Factory.php',
    'Illuminate\\Contracts\\Cookie\\QueueingFactory' => $vendorDir . '/illuminate/contracts/Cookie/QueueingFactory.php',
    'Illuminate\\Contracts\\Database\\ConcurrencyErrorDetector' => $vendorDir . '/illuminate/contracts/Database/ConcurrencyErrorDetector.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\Builder' => $vendorDir . '/illuminate/contracts/Database/Eloquent/Builder.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\Castable' => $vendorDir . '/illuminate/contracts/Database/Eloquent/Castable.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\CastsAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/CastsAttributes.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\CastsInboundAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\ComparesCastableAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/ComparesCastableAttributes.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\DeviatesCastableAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\SerializesCastableAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php',
    'Illuminate\\Contracts\\Database\\Eloquent\\SupportsPartialRelations' => $vendorDir . '/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php',
    'Illuminate\\Contracts\\Database\\Events\\MigrationEvent' => $vendorDir . '/illuminate/contracts/Database/Events/MigrationEvent.php',
    'Illuminate\\Contracts\\Database\\LostConnectionDetector' => $vendorDir . '/illuminate/contracts/Database/LostConnectionDetector.php',
    'Illuminate\\Contracts\\Database\\ModelIdentifier' => $vendorDir . '/illuminate/contracts/Database/ModelIdentifier.php',
    'Illuminate\\Contracts\\Database\\Query\\Builder' => $vendorDir . '/illuminate/contracts/Database/Query/Builder.php',
    'Illuminate\\Contracts\\Database\\Query\\ConditionExpression' => $vendorDir . '/illuminate/contracts/Database/Query/ConditionExpression.php',
    'Illuminate\\Contracts\\Database\\Query\\Expression' => $vendorDir . '/illuminate/contracts/Database/Query/Expression.php',
    'Illuminate\\Contracts\\Debug\\ExceptionHandler' => $vendorDir . '/illuminate/contracts/Debug/ExceptionHandler.php',
    'Illuminate\\Contracts\\Debug\\ShouldntReport' => $vendorDir . '/illuminate/contracts/Debug/ShouldntReport.php',
    'Illuminate\\Contracts\\Encryption\\DecryptException' => $vendorDir . '/illuminate/contracts/Encryption/DecryptException.php',
    'Illuminate\\Contracts\\Encryption\\EncryptException' => $vendorDir . '/illuminate/contracts/Encryption/EncryptException.php',
    'Illuminate\\Contracts\\Encryption\\Encrypter' => $vendorDir . '/illuminate/contracts/Encryption/Encrypter.php',
    'Illuminate\\Contracts\\Encryption\\StringEncrypter' => $vendorDir . '/illuminate/contracts/Encryption/StringEncrypter.php',
    'Illuminate\\Contracts\\Events\\Dispatcher' => $vendorDir . '/illuminate/contracts/Events/Dispatcher.php',
    'Illuminate\\Contracts\\Events\\ShouldDispatchAfterCommit' => $vendorDir . '/illuminate/contracts/Events/ShouldDispatchAfterCommit.php',
    'Illuminate\\Contracts\\Events\\ShouldHandleEventsAfterCommit' => $vendorDir . '/illuminate/contracts/Events/ShouldHandleEventsAfterCommit.php',
    'Illuminate\\Contracts\\Filesystem\\Cloud' => $vendorDir . '/illuminate/contracts/Filesystem/Cloud.php',
    'Illuminate\\Contracts\\Filesystem\\Factory' => $vendorDir . '/illuminate/contracts/Filesystem/Factory.php',
    'Illuminate\\Contracts\\Filesystem\\FileNotFoundException' => $vendorDir . '/illuminate/contracts/Filesystem/FileNotFoundException.php',
    'Illuminate\\Contracts\\Filesystem\\Filesystem' => $vendorDir . '/illuminate/contracts/Filesystem/Filesystem.php',
    'Illuminate\\Contracts\\Filesystem\\LockTimeoutException' => $vendorDir . '/illuminate/contracts/Filesystem/LockTimeoutException.php',
    'Illuminate\\Contracts\\Foundation\\Application' => $vendorDir . '/illuminate/contracts/Foundation/Application.php',
    'Illuminate\\Contracts\\Foundation\\CachesConfiguration' => $vendorDir . '/illuminate/contracts/Foundation/CachesConfiguration.php',
    'Illuminate\\Contracts\\Foundation\\CachesRoutes' => $vendorDir . '/illuminate/contracts/Foundation/CachesRoutes.php',
    'Illuminate\\Contracts\\Foundation\\ExceptionRenderer' => $vendorDir . '/illuminate/contracts/Foundation/ExceptionRenderer.php',
    'Illuminate\\Contracts\\Foundation\\MaintenanceMode' => $vendorDir . '/illuminate/contracts/Foundation/MaintenanceMode.php',
    'Illuminate\\Contracts\\Hashing\\Hasher' => $vendorDir . '/illuminate/contracts/Hashing/Hasher.php',
    'Illuminate\\Contracts\\Http\\Kernel' => $vendorDir . '/illuminate/contracts/Http/Kernel.php',
    'Illuminate\\Contracts\\JsonSchema\\JsonSchema' => $vendorDir . '/illuminate/contracts/JsonSchema/JsonSchema.php',
    'Illuminate\\Contracts\\Log\\ContextLogProcessor' => $vendorDir . '/illuminate/contracts/Log/ContextLogProcessor.php',
    'Illuminate\\Contracts\\Mail\\Attachable' => $vendorDir . '/illuminate/contracts/Mail/Attachable.php',
    'Illuminate\\Contracts\\Mail\\Factory' => $vendorDir . '/illuminate/contracts/Mail/Factory.php',
    'Illuminate\\Contracts\\Mail\\MailQueue' => $vendorDir . '/illuminate/contracts/Mail/MailQueue.php',
    'Illuminate\\Contracts\\Mail\\Mailable' => $vendorDir . '/illuminate/contracts/Mail/Mailable.php',
    'Illuminate\\Contracts\\Mail\\Mailer' => $vendorDir . '/illuminate/contracts/Mail/Mailer.php',
    'Illuminate\\Contracts\\Notifications\\Dispatcher' => $vendorDir . '/illuminate/contracts/Notifications/Dispatcher.php',
    'Illuminate\\Contracts\\Notifications\\Factory' => $vendorDir . '/illuminate/contracts/Notifications/Factory.php',
    'Illuminate\\Contracts\\Pagination\\CursorPaginator' => $vendorDir . '/illuminate/contracts/Pagination/CursorPaginator.php',
    'Illuminate\\Contracts\\Pagination\\LengthAwarePaginator' => $vendorDir . '/illuminate/contracts/Pagination/LengthAwarePaginator.php',
    'Illuminate\\Contracts\\Pagination\\Paginator' => $vendorDir . '/illuminate/contracts/Pagination/Paginator.php',
    'Illuminate\\Contracts\\Pipeline\\Hub' => $vendorDir . '/illuminate/contracts/Pipeline/Hub.php',
    'Illuminate\\Contracts\\Pipeline\\Pipeline' => $vendorDir . '/illuminate/contracts/Pipeline/Pipeline.php',
    'Illuminate\\Contracts\\Process\\InvokedProcess' => $vendorDir . '/illuminate/contracts/Process/InvokedProcess.php',
    'Illuminate\\Contracts\\Process\\ProcessResult' => $vendorDir . '/illuminate/contracts/Process/ProcessResult.php',
    'Illuminate\\Contracts\\Queue\\ClearableQueue' => $vendorDir . '/illuminate/contracts/Queue/ClearableQueue.php',
    'Illuminate\\Contracts\\Queue\\EntityNotFoundException' => $vendorDir . '/illuminate/contracts/Queue/EntityNotFoundException.php',
    'Illuminate\\Contracts\\Queue\\EntityResolver' => $vendorDir . '/illuminate/contracts/Queue/EntityResolver.php',
    'Illuminate\\Contracts\\Queue\\Factory' => $vendorDir . '/illuminate/contracts/Queue/Factory.php',
    'Illuminate\\Contracts\\Queue\\Interruptible' => $vendorDir . '/illuminate/contracts/Queue/Interruptible.php',
    'Illuminate\\Contracts\\Queue\\Job' => $vendorDir . '/illuminate/contracts/Queue/Job.php',
    'Illuminate\\Contracts\\Queue\\Monitor' => $vendorDir . '/illuminate/contracts/Queue/Monitor.php',
    'Illuminate\\Contracts\\Queue\\PreparesForDispatch' => $vendorDir . '/illuminate/contracts/Queue/PreparesForDispatch.php',
    'Illuminate\\Contracts\\Queue\\Queue' => $vendorDir . '/illuminate/contracts/Queue/Queue.php',
    'Illuminate\\Contracts\\Queue\\QueueableCollection' => $vendorDir . '/illuminate/contracts/Queue/QueueableCollection.php',
    'Illuminate\\Contracts\\Queue\\QueueableEntity' => $vendorDir . '/illuminate/contracts/Queue/QueueableEntity.php',
    'Illuminate\\Contracts\\Queue\\ShouldBeEncrypted' => $vendorDir . '/illuminate/contracts/Queue/ShouldBeEncrypted.php',
    'Illuminate\\Contracts\\Queue\\ShouldBeUnique' => $vendorDir . '/illuminate/contracts/Queue/ShouldBeUnique.php',
    'Illuminate\\Contracts\\Queue\\ShouldBeUniqueUntilProcessing' => $vendorDir . '/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.php',
    'Illuminate\\Contracts\\Queue\\ShouldQueue' => $vendorDir . '/illuminate/contracts/Queue/ShouldQueue.php',
    'Illuminate\\Contracts\\Queue\\ShouldQueueAfterCommit' => $vendorDir . '/illuminate/contracts/Queue/ShouldQueueAfterCommit.php',
    'Illuminate\\Contracts\\Redis\\Connection' => $vendorDir . '/illuminate/contracts/Redis/Connection.php',
    'Illuminate\\Contracts\\Redis\\Connector' => $vendorDir . '/illuminate/contracts/Redis/Connector.php',
    'Illuminate\\Contracts\\Redis\\Factory' => $vendorDir . '/illuminate/contracts/Redis/Factory.php',
    'Illuminate\\Contracts\\Redis\\LimiterTimeoutException' => $vendorDir . '/illuminate/contracts/Redis/LimiterTimeoutException.php',
    'Illuminate\\Contracts\\Routing\\BindingRegistrar' => $vendorDir . '/illuminate/contracts/Routing/BindingRegistrar.php',
    'Illuminate\\Contracts\\Routing\\Registrar' => $vendorDir . '/illuminate/contracts/Routing/Registrar.php',
    'Illuminate\\Contracts\\Routing\\ResponseFactory' => $vendorDir . '/illuminate/contracts/Routing/ResponseFactory.php',
    'Illuminate\\Contracts\\Routing\\UrlGenerator' => $vendorDir . '/illuminate/contracts/Routing/UrlGenerator.php',
    'Illuminate\\Contracts\\Routing\\UrlRoutable' => $vendorDir . '/illuminate/contracts/Routing/UrlRoutable.php',
    'Illuminate\\Contracts\\Session\\Middleware\\AuthenticatesSessions' => $vendorDir . '/illuminate/contracts/Session/Middleware/AuthenticatesSessions.php',
    'Illuminate\\Contracts\\Session\\Session' => $vendorDir . '/illuminate/contracts/Session/Session.php',
    'Illuminate\\Contracts\\Support\\Arrayable' => $vendorDir . '/illuminate/contracts/Support/Arrayable.php',
    'Illuminate\\Contracts\\Support\\CanBeEscapedWhenCastToString' => $vendorDir . '/illuminate/contracts/Support/CanBeEscapedWhenCastToString.php',
    'Illuminate\\Contracts\\Support\\DeferrableProvider' => $vendorDir . '/illuminate/contracts/Support/DeferrableProvider.php',
    'Illuminate\\Contracts\\Support\\DeferringDisplayableValue' => $vendorDir . '/illuminate/contracts/Support/DeferringDisplayableValue.php',
    'Illuminate\\Contracts\\Support\\HasOnceHash' => $vendorDir . '/illuminate/contracts/Support/HasOnceHash.php',
    'Illuminate\\Contracts\\Support\\Htmlable' => $vendorDir . '/illuminate/contracts/Support/Htmlable.php',
    'Illuminate\\Contracts\\Support\\Jsonable' => $vendorDir . '/illuminate/contracts/Support/Jsonable.php',
    'Illuminate\\Contracts\\Support\\MessageBag' => $vendorDir . '/illuminate/contracts/Support/MessageBag.php',
    'Illuminate\\Contracts\\Support\\MessageProvider' => $vendorDir . '/illuminate/contracts/Support/MessageProvider.php',
    'Illuminate\\Contracts\\Support\\Renderable' => $vendorDir . '/illuminate/contracts/Support/Renderable.php',
    'Illuminate\\Contracts\\Support\\Responsable' => $vendorDir . '/illuminate/contracts/Support/Responsable.php',
    'Illuminate\\Contracts\\Support\\ValidatedData' => $vendorDir . '/illuminate/contracts/Support/ValidatedData.php',
    'Illuminate\\Contracts\\Translation\\HasLocalePreference' => $vendorDir . '/illuminate/contracts/Translation/HasLocalePreference.php',
    'Illuminate\\Contracts\\Translation\\Loader' => $vendorDir . '/illuminate/contracts/Translation/Loader.php',
    'Illuminate\\Contracts\\Translation\\Translator' => $vendorDir . '/illuminate/contracts/Translation/Translator.php',
    'Illuminate\\Contracts\\Validation\\CompilableRules' => $vendorDir . '/illuminate/contracts/Validation/CompilableRules.php',
    'Illuminate\\Contracts\\Validation\\DataAwareRule' => $vendorDir . '/illuminate/contracts/Validation/DataAwareRule.php',
    'Illuminate\\Contracts\\Validation\\Factory' => $vendorDir . '/illuminate/contracts/Validation/Factory.php',
    'Illuminate\\Contracts\\Validation\\ImplicitRule' => $vendorDir . '/illuminate/contracts/Validation/ImplicitRule.php',
    'Illuminate\\Contracts\\Validation\\InvokableRule' => $vendorDir . '/illuminate/contracts/Validation/InvokableRule.php',
    'Illuminate\\Contracts\\Validation\\Rule' => $vendorDir . '/illuminate/contracts/Validation/Rule.php',
    'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => $vendorDir . '/illuminate/contracts/Validation/UncompromisedVerifier.php',
    'Illuminate\\Contracts\\Validation\\ValidatesWhenResolved' => $vendorDir . '/illuminate/contracts/Validation/ValidatesWhenResolved.php',
    'Illuminate\\Contracts\\Validation\\ValidationRule' => $vendorDir . '/illuminate/contracts/Validation/ValidationRule.php',
    'Illuminate\\Contracts\\Validation\\Validator' => $vendorDir . '/illuminate/contracts/Validation/Validator.php',
    'Illuminate\\Contracts\\Validation\\ValidatorAwareRule' => $vendorDir . '/illuminate/contracts/Validation/ValidatorAwareRule.php',
    'Illuminate\\Contracts\\View\\Engine' => $vendorDir . '/illuminate/contracts/View/Engine.php',
    'Illuminate\\Contracts\\View\\Factory' => $vendorDir . '/illuminate/contracts/View/Factory.php',
    'Illuminate\\Contracts\\View\\View' => $vendorDir . '/illuminate/contracts/View/View.php',
    'Illuminate\\Contracts\\View\\ViewCompilationException' => $vendorDir . '/illuminate/contracts/View/ViewCompilationException.php',
    'Illuminate\\Filesystem\\AwsS3V3Adapter' => $vendorDir . '/illuminate/filesystem/AwsS3V3Adapter.php',
    'Illuminate\\Filesystem\\Filesystem' => $vendorDir . '/illuminate/filesystem/Filesystem.php',
    'Illuminate\\Filesystem\\FilesystemAdapter' => $vendorDir . '/illuminate/filesystem/FilesystemAdapter.php',
    'Illuminate\\Filesystem\\FilesystemManager' => $vendorDir . '/illuminate/filesystem/FilesystemManager.php',
    'Illuminate\\Filesystem\\FilesystemServiceProvider' => $vendorDir . '/illuminate/filesystem/FilesystemServiceProvider.php',
    'Illuminate\\Filesystem\\LocalFilesystemAdapter' => $vendorDir . '/illuminate/filesystem/LocalFilesystemAdapter.php',
    'Illuminate\\Filesystem\\LockableFile' => $vendorDir . '/illuminate/filesystem/LockableFile.php',
    'Illuminate\\Filesystem\\ReceiveFile' => $vendorDir . '/illuminate/filesystem/ReceiveFile.php',
    'Illuminate\\Filesystem\\ServeFile' => $vendorDir . '/illuminate/filesystem/ServeFile.php',
    'Illuminate\\Support\\AggregateServiceProvider' => $vendorDir . '/illuminate/support/AggregateServiceProvider.php',
    'Illuminate\\Support\\Arr' => $vendorDir . '/illuminate/collections/Arr.php',
    'Illuminate\\Support\\Benchmark' => $vendorDir . '/illuminate/support/Benchmark.php',
    'Illuminate\\Support\\BinaryCodec' => $vendorDir . '/illuminate/support/BinaryCodec.php',
    'Illuminate\\Support\\Carbon' => $vendorDir . '/illuminate/support/Carbon.php',
    'Illuminate\\Support\\Collection' => $vendorDir . '/illuminate/collections/Collection.php',
    'Illuminate\\Support\\Composer' => $vendorDir . '/illuminate/support/Composer.php',
    'Illuminate\\Support\\ConfigurationUrlParser' => $vendorDir . '/illuminate/support/ConfigurationUrlParser.php',
    'Illuminate\\Support\\DateFactory' => $vendorDir . '/illuminate/support/DateFactory.php',
    'Illuminate\\Support\\DefaultProviders' => $vendorDir . '/illuminate/support/DefaultProviders.php',
    'Illuminate\\Support\\Defer\\DeferredCallback' => $vendorDir . '/illuminate/support/Defer/DeferredCallback.php',
    'Illuminate\\Support\\Defer\\DeferredCallbackCollection' => $vendorDir . '/illuminate/support/Defer/DeferredCallbackCollection.php',
    'Illuminate\\Support\\EncodedHtmlString' => $vendorDir . '/illuminate/support/EncodedHtmlString.php',
    'Illuminate\\Support\\Enumerable' => $vendorDir . '/illuminate/collections/Enumerable.php',
    'Illuminate\\Support\\Env' => $vendorDir . '/illuminate/support/Env.php',
    'Illuminate\\Support\\Exceptions\\MathException' => $vendorDir . '/illuminate/support/Exceptions/MathException.php',
    'Illuminate\\Support\\Facades\\App' => $vendorDir . '/illuminate/support/Facades/App.php',
    'Illuminate\\Support\\Facades\\Artisan' => $vendorDir . '/illuminate/support/Facades/Artisan.php',
    'Illuminate\\Support\\Facades\\Auth' => $vendorDir . '/illuminate/support/Facades/Auth.php',
    'Illuminate\\Support\\Facades\\Blade' => $vendorDir . '/illuminate/support/Facades/Blade.php',
    'Illuminate\\Support\\Facades\\Broadcast' => $vendorDir . '/illuminate/support/Facades/Broadcast.php',
    'Illuminate\\Support\\Facades\\Bus' => $vendorDir . '/illuminate/support/Facades/Bus.php',
    'Illuminate\\Support\\Facades\\Cache' => $vendorDir . '/illuminate/support/Facades/Cache.php',
    'Illuminate\\Support\\Facades\\Concurrency' => $vendorDir . '/illuminate/support/Facades/Concurrency.php',
    'Illuminate\\Support\\Facades\\Config' => $vendorDir . '/illuminate/support/Facades/Config.php',
    'Illuminate\\Support\\Facades\\Context' => $vendorDir . '/illuminate/support/Facades/Context.php',
    'Illuminate\\Support\\Facades\\Cookie' => $vendorDir . '/illuminate/support/Facades/Cookie.php',
    'Illuminate\\Support\\Facades\\Crypt' => $vendorDir . '/illuminate/support/Facades/Crypt.php',
    'Illuminate\\Support\\Facades\\DB' => $vendorDir . '/illuminate/support/Facades/DB.php',
    'Illuminate\\Support\\Facades\\Date' => $vendorDir . '/illuminate/support/Facades/Date.php',
    'Illuminate\\Support\\Facades\\Event' => $vendorDir . '/illuminate/support/Facades/Event.php',
    'Illuminate\\Support\\Facades\\Exceptions' => $vendorDir . '/illuminate/support/Facades/Exceptions.php',
    'Illuminate\\Support\\Facades\\Facade' => $vendorDir . '/illuminate/support/Facades/Facade.php',
    'Illuminate\\Support\\Facades\\File' => $vendorDir . '/illuminate/support/Facades/File.php',
    'Illuminate\\Support\\Facades\\Gate' => $vendorDir . '/illuminate/support/Facades/Gate.php',
    'Illuminate\\Support\\Facades\\Hash' => $vendorDir . '/illuminate/support/Facades/Hash.php',
    'Illuminate\\Support\\Facades\\Http' => $vendorDir . '/illuminate/support/Facades/Http.php',
    'Illuminate\\Support\\Facades\\Lang' => $vendorDir . '/illuminate/support/Facades/Lang.php',
    'Illuminate\\Support\\Facades\\Log' => $vendorDir . '/illuminate/support/Facades/Log.php',
    'Illuminate\\Support\\Facades\\Mail' => $vendorDir . '/illuminate/support/Facades/Mail.php',
    'Illuminate\\Support\\Facades\\MaintenanceMode' => $vendorDir . '/illuminate/support/Facades/MaintenanceMode.php',
    'Illuminate\\Support\\Facades\\Notification' => $vendorDir . '/illuminate/support/Facades/Notification.php',
    'Illuminate\\Support\\Facades\\ParallelTesting' => $vendorDir . '/illuminate/support/Facades/ParallelTesting.php',
    'Illuminate\\Support\\Facades\\Password' => $vendorDir . '/illuminate/support/Facades/Password.php',
    'Illuminate\\Support\\Facades\\Pipeline' => $vendorDir . '/illuminate/support/Facades/Pipeline.php',
    'Illuminate\\Support\\Facades\\Process' => $vendorDir . '/illuminate/support/Facades/Process.php',
    'Illuminate\\Support\\Facades\\Queue' => $vendorDir . '/illuminate/support/Facades/Queue.php',
    'Illuminate\\Support\\Facades\\RateLimiter' => $vendorDir . '/illuminate/support/Facades/RateLimiter.php',
    'Illuminate\\Support\\Facades\\Redirect' => $vendorDir . '/illuminate/support/Facades/Redirect.php',
    'Illuminate\\Support\\Facades\\Redis' => $vendorDir . '/illuminate/support/Facades/Redis.php',
    'Illuminate\\Support\\Facades\\Request' => $vendorDir . '/illuminate/support/Facades/Request.php',
    'Illuminate\\Support\\Facades\\Response' => $vendorDir . '/illuminate/support/Facades/Response.php',
    'Illuminate\\Support\\Facades\\Route' => $vendorDir . '/illuminate/support/Facades/Route.php',
    'Illuminate\\Support\\Facades\\Schedule' => $vendorDir . '/illuminate/support/Facades/Schedule.php',
    'Illuminate\\Support\\Facades\\Schema' => $vendorDir . '/illuminate/support/Facades/Schema.php',
    'Illuminate\\Support\\Facades\\Session' => $vendorDir . '/illuminate/support/Facades/Session.php',
    'Illuminate\\Support\\Facades\\Storage' => $vendorDir . '/illuminate/support/Facades/Storage.php',
    'Illuminate\\Support\\Facades\\URL' => $vendorDir . '/illuminate/support/Facades/URL.php',
    'Illuminate\\Support\\Facades\\Validator' => $vendorDir . '/illuminate/support/Facades/Validator.php',
    'Illuminate\\Support\\Facades\\View' => $vendorDir . '/illuminate/support/Facades/View.php',
    'Illuminate\\Support\\Facades\\Vite' => $vendorDir . '/illuminate/support/Facades/Vite.php',
    'Illuminate\\Support\\Fluent' => $vendorDir . '/illuminate/support/Fluent.php',
    'Illuminate\\Support\\HigherOrderCollectionProxy' => $vendorDir . '/illuminate/collections/HigherOrderCollectionProxy.php',
    'Illuminate\\Support\\HigherOrderTapProxy' => $vendorDir . '/illuminate/support/HigherOrderTapProxy.php',
    'Illuminate\\Support\\HigherOrderWhenProxy' => $vendorDir . '/illuminate/conditionable/HigherOrderWhenProxy.php',
    'Illuminate\\Support\\HtmlString' => $vendorDir . '/illuminate/support/HtmlString.php',
    'Illuminate\\Support\\InteractsWithTime' => $vendorDir . '/illuminate/support/InteractsWithTime.php',
    'Illuminate\\Support\\ItemNotFoundException' => $vendorDir . '/illuminate/collections/ItemNotFoundException.php',
    'Illuminate\\Support\\Js' => $vendorDir . '/illuminate/support/Js.php',
    'Illuminate\\Support\\LazyCollection' => $vendorDir . '/illuminate/collections/LazyCollection.php',
    'Illuminate\\Support\\Lottery' => $vendorDir . '/illuminate/support/Lottery.php',
    'Illuminate\\Support\\Manager' => $vendorDir . '/illuminate/support/Manager.php',
    'Illuminate\\Support\\MessageBag' => $vendorDir . '/illuminate/support/MessageBag.php',
    'Illuminate\\Support\\MultipleInstanceManager' => $vendorDir . '/illuminate/support/MultipleInstanceManager.php',
    'Illuminate\\Support\\MultipleItemsFoundException' => $vendorDir . '/illuminate/collections/MultipleItemsFoundException.php',
    'Illuminate\\Support\\NamespacedItemResolver' => $vendorDir . '/illuminate/support/NamespacedItemResolver.php',
    'Illuminate\\Support\\Number' => $vendorDir . '/illuminate/support/Number.php',
    'Illuminate\\Support\\Once' => $vendorDir . '/illuminate/support/Once.php',
    'Illuminate\\Support\\Onceable' => $vendorDir . '/illuminate/support/Onceable.php',
    'Illuminate\\Support\\Optional' => $vendorDir . '/illuminate/support/Optional.php',
    'Illuminate\\Support\\Pluralizer' => $vendorDir . '/illuminate/support/Pluralizer.php',
    'Illuminate\\Support\\ProcessUtils' => $vendorDir . '/illuminate/support/ProcessUtils.php',
    'Illuminate\\Support\\Queue\\Concerns\\ResolvesQueueRoutes' => $vendorDir . '/illuminate/support/Queue/Concerns/ResolvesQueueRoutes.php',
    'Illuminate\\Support\\RebindsCallbacksToSelf' => $vendorDir . '/illuminate/support/RebindsCallbacksToSelf.php',
    'Illuminate\\Support\\Reflector' => $vendorDir . '/illuminate/reflection/Reflector.php',
    'Illuminate\\Support\\ServiceProvider' => $vendorDir . '/illuminate/support/ServiceProvider.php',
    'Illuminate\\Support\\Sleep' => $vendorDir . '/illuminate/support/Sleep.php',
    'Illuminate\\Support\\Str' => $vendorDir . '/illuminate/support/Str.php',
    'Illuminate\\Support\\Stringable' => $vendorDir . '/illuminate/support/Stringable.php',
    'Illuminate\\Support\\Testing\\Fakes\\BatchFake' => $vendorDir . '/illuminate/support/Testing/Fakes/BatchFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\BatchRepositoryFake' => $vendorDir . '/illuminate/support/Testing/Fakes/BatchRepositoryFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\BusFake' => $vendorDir . '/illuminate/support/Testing/Fakes/BusFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\ChainedBatchTruthTest' => $vendorDir . '/illuminate/support/Testing/Fakes/ChainedBatchTruthTest.php',
    'Illuminate\\Support\\Testing\\Fakes\\EventFake' => $vendorDir . '/illuminate/support/Testing/Fakes/EventFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\ExceptionHandlerFake' => $vendorDir . '/illuminate/support/Testing/Fakes/ExceptionHandlerFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\Fake' => $vendorDir . '/illuminate/support/Testing/Fakes/Fake.php',
    'Illuminate\\Support\\Testing\\Fakes\\MailFake' => $vendorDir . '/illuminate/support/Testing/Fakes/MailFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\NotificationFake' => $vendorDir . '/illuminate/support/Testing/Fakes/NotificationFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\PendingBatchFake' => $vendorDir . '/illuminate/support/Testing/Fakes/PendingBatchFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\PendingChainFake' => $vendorDir . '/illuminate/support/Testing/Fakes/PendingChainFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\PendingMailFake' => $vendorDir . '/illuminate/support/Testing/Fakes/PendingMailFake.php',
    'Illuminate\\Support\\Testing\\Fakes\\QueueFake' => $vendorDir . '/illuminate/support/Testing/Fakes/QueueFake.php',
    'Illuminate\\Support\\Timebox' => $vendorDir . '/illuminate/support/Timebox.php',
    'Illuminate\\Support\\Traits\\CapsuleManagerTrait' => $vendorDir . '/illuminate/support/Traits/CapsuleManagerTrait.php',
    'Illuminate\\Support\\Traits\\Conditionable' => $vendorDir . '/illuminate/conditionable/Traits/Conditionable.php',
    'Illuminate\\Support\\Traits\\Dumpable' => $vendorDir . '/illuminate/support/Traits/Dumpable.php',
    'Illuminate\\Support\\Traits\\EnumeratesValues' => $vendorDir . '/illuminate/collections/Traits/EnumeratesValues.php',
    'Illuminate\\Support\\Traits\\ForwardsCalls' => $vendorDir . '/illuminate/support/Traits/ForwardsCalls.php',
    'Illuminate\\Support\\Traits\\InteractsWithData' => $vendorDir . '/illuminate/support/Traits/InteractsWithData.php',
    'Illuminate\\Support\\Traits\\Localizable' => $vendorDir . '/illuminate/support/Traits/Localizable.php',
    'Illuminate\\Support\\Traits\\Macroable' => $vendorDir . '/illuminate/macroable/Traits/Macroable.php',
    'Illuminate\\Support\\Traits\\ReadsClassAttributes' => $vendorDir . '/illuminate/support/Traits/ReadsClassAttributes.php',
    'Illuminate\\Support\\Traits\\ReflectsClosures' => $vendorDir . '/illuminate/reflection/Traits/ReflectsClosures.php',
    'Illuminate\\Support\\Traits\\Tappable' => $vendorDir . '/illuminate/support/Traits/Tappable.php',
    'Illuminate\\Support\\Traits\\TransformsToResourceCollection' => $vendorDir . '/illuminate/collections/Traits/TransformsToResourceCollection.php',
    'Illuminate\\Support\\Uri' => $vendorDir . '/illuminate/support/Uri.php',
    'Illuminate\\Support\\UriQueryString' => $vendorDir . '/illuminate/support/UriQueryString.php',
    'Illuminate\\Support\\ValidatedInput' => $vendorDir . '/illuminate/support/ValidatedInput.php',
    'Illuminate\\Support\\ViewErrorBag' => $vendorDir . '/illuminate/support/ViewErrorBag.php',
    'Laravel\\AgentDetector\\AgentDetector' => $vendorDir . '/laravel/agent-detector/src/AgentDetector.php',
    'Laravel\\AgentDetector\\AgentResult' => $vendorDir . '/laravel/agent-detector/src/AgentResult.php',
    'Laravel\\AgentDetector\\KnownAgent' => $vendorDir . '/laravel/agent-detector/src/KnownAgent.php',
    'Laravel\\Installer\\Console\\Agent' => $baseDir . '/src/Agent.php',
    'Laravel\\Installer\\Console\\Concerns\\ConfiguresPrompts' => $baseDir . '/src/Concerns/ConfiguresPrompts.php',
    'Laravel\\Installer\\Console\\Concerns\\InteractsWithHerdOrValet' => $baseDir . '/src/Concerns/InteractsWithHerdOrValet.php',
    'Laravel\\Installer\\Console\\Enums\\NodePackageManager' => $baseDir . '/src/Enums/NodePackageManager.php',
    'Laravel\\Installer\\Console\\NewCommand' => $baseDir . '/src/NewCommand.php',
    'Laravel\\Prompts\\AutoCompletePrompt' => $vendorDir . '/laravel/prompts/src/AutoCompletePrompt.php',
    'Laravel\\Prompts\\Clear' => $vendorDir . '/laravel/prompts/src/Clear.php',
    'Laravel\\Prompts\\Concerns\\Colors' => $vendorDir . '/laravel/prompts/src/Concerns/Colors.php',
    'Laravel\\Prompts\\Concerns\\Cursor' => $vendorDir . '/laravel/prompts/src/Concerns/Cursor.php',
    'Laravel\\Prompts\\Concerns\\Erase' => $vendorDir . '/laravel/prompts/src/Concerns/Erase.php',
    'Laravel\\Prompts\\Concerns\\Events' => $vendorDir . '/laravel/prompts/src/Concerns/Events.php',
    'Laravel\\Prompts\\Concerns\\FakesInputOutput' => $vendorDir . '/laravel/prompts/src/Concerns/FakesInputOutput.php',
    'Laravel\\Prompts\\Concerns\\Fallback' => $vendorDir . '/laravel/prompts/src/Concerns/Fallback.php',
    'Laravel\\Prompts\\Concerns\\HasInfo' => $vendorDir . '/laravel/prompts/src/Concerns/HasInfo.php',
    'Laravel\\Prompts\\Concerns\\HasSpinner' => $vendorDir . '/laravel/prompts/src/Concerns/HasSpinner.php',
    'Laravel\\Prompts\\Concerns\\Interactivity' => $vendorDir . '/laravel/prompts/src/Concerns/Interactivity.php',
    'Laravel\\Prompts\\Concerns\\Scrolling' => $vendorDir . '/laravel/prompts/src/Concerns/Scrolling.php',
    'Laravel\\Prompts\\Concerns\\Termwind' => $vendorDir . '/laravel/prompts/src/Concerns/Termwind.php',
    'Laravel\\Prompts\\Concerns\\Themes' => $vendorDir . '/laravel/prompts/src/Concerns/Themes.php',
    'Laravel\\Prompts\\Concerns\\Truncation' => $vendorDir . '/laravel/prompts/src/Concerns/Truncation.php',
    'Laravel\\Prompts\\Concerns\\TypedValue' => $vendorDir . '/laravel/prompts/src/Concerns/TypedValue.php',
    'Laravel\\Prompts\\ConfirmPrompt' => $vendorDir . '/laravel/prompts/src/ConfirmPrompt.php',
    'Laravel\\Prompts\\DataTablePrompt' => $vendorDir . '/laravel/prompts/src/DataTablePrompt.php',
    'Laravel\\Prompts\\Exceptions\\FormRevertedException' => $vendorDir . '/laravel/prompts/src/Exceptions/FormRevertedException.php',
    'Laravel\\Prompts\\Exceptions\\NonInteractiveValidationException' => $vendorDir . '/laravel/prompts/src/Exceptions/NonInteractiveValidationException.php',
    'Laravel\\Prompts\\FormBuilder' => $vendorDir . '/laravel/prompts/src/FormBuilder.php',
    'Laravel\\Prompts\\FormStep' => $vendorDir . '/laravel/prompts/src/FormStep.php',
    'Laravel\\Prompts\\Grid' => $vendorDir . '/laravel/prompts/src/Grid.php',
    'Laravel\\Prompts\\Key' => $vendorDir . '/laravel/prompts/src/Key.php',
    'Laravel\\Prompts\\MultiSearchPrompt' => $vendorDir . '/laravel/prompts/src/MultiSearchPrompt.php',
    'Laravel\\Prompts\\MultiSelectPrompt' => $vendorDir . '/laravel/prompts/src/MultiSelectPrompt.php',
    'Laravel\\Prompts\\Note' => $vendorDir . '/laravel/prompts/src/Note.php',
    'Laravel\\Prompts\\NotifyPrompt' => $vendorDir . '/laravel/prompts/src/NotifyPrompt.php',
    'Laravel\\Prompts\\NumberPrompt' => $vendorDir . '/laravel/prompts/src/NumberPrompt.php',
    'Laravel\\Prompts\\Output\\BufferedConsoleOutput' => $vendorDir . '/laravel/prompts/src/Output/BufferedConsoleOutput.php',
    'Laravel\\Prompts\\Output\\ConsoleOutput' => $vendorDir . '/laravel/prompts/src/Output/ConsoleOutput.php',
    'Laravel\\Prompts\\PasswordPrompt' => $vendorDir . '/laravel/prompts/src/PasswordPrompt.php',
    'Laravel\\Prompts\\PausePrompt' => $vendorDir . '/laravel/prompts/src/PausePrompt.php',
    'Laravel\\Prompts\\Progress' => $vendorDir . '/laravel/prompts/src/Progress.php',
    'Laravel\\Prompts\\Prompt' => $vendorDir . '/laravel/prompts/src/Prompt.php',
    'Laravel\\Prompts\\SearchPrompt' => $vendorDir . '/laravel/prompts/src/SearchPrompt.php',
    'Laravel\\Prompts\\SelectPrompt' => $vendorDir . '/laravel/prompts/src/SelectPrompt.php',
    'Laravel\\Prompts\\Spinner' => $vendorDir . '/laravel/prompts/src/Spinner.php',
    'Laravel\\Prompts\\Stream' => $vendorDir . '/laravel/prompts/src/Stream.php',
    'Laravel\\Prompts\\SuggestPrompt' => $vendorDir . '/laravel/prompts/src/SuggestPrompt.php',
    'Laravel\\Prompts\\Support\\Logger' => $vendorDir . '/laravel/prompts/src/Support/Logger.php',
    'Laravel\\Prompts\\Support\\Result' => $vendorDir . '/laravel/prompts/src/Support/Result.php',
    'Laravel\\Prompts\\Support\\Utils' => $vendorDir . '/laravel/prompts/src/Support/Utils.php',
    'Laravel\\Prompts\\Table' => $vendorDir . '/laravel/prompts/src/Table.php',
    'Laravel\\Prompts\\Task' => $vendorDir . '/laravel/prompts/src/Task.php',
    'Laravel\\Prompts\\Terminal' => $vendorDir . '/laravel/prompts/src/Terminal.php',
    'Laravel\\Prompts\\TextPrompt' => $vendorDir . '/laravel/prompts/src/TextPrompt.php',
    'Laravel\\Prompts\\TextareaPrompt' => $vendorDir . '/laravel/prompts/src/TextareaPrompt.php',
    'Laravel\\Prompts\\Themes\\Contracts\\Scrolling' => $vendorDir . '/laravel/prompts/src/Themes/Contracts/Scrolling.php',
    'Laravel\\Prompts\\Themes\\Default\\AutoCompletePromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/AutoCompletePromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\ClearRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/ClearRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\Concerns\\DrawsBoxes' => $vendorDir . '/laravel/prompts/src/Themes/Default/Concerns/DrawsBoxes.php',
    'Laravel\\Prompts\\Themes\\Default\\Concerns\\DrawsScrollbars' => $vendorDir . '/laravel/prompts/src/Themes/Default/Concerns/DrawsScrollbars.php',
    'Laravel\\Prompts\\Themes\\Default\\Concerns\\InteractsWithStrings' => $vendorDir . '/laravel/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php',
    'Laravel\\Prompts\\Themes\\Default\\ConfirmPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/ConfirmPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\DataTableRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/DataTableRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\GridRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/GridRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\MultiSearchPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/MultiSearchPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\MultiSelectPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/MultiSelectPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\NoteRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/NoteRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\NumberPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/NumberPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\PasswordPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/PasswordPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\PausePromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/PausePromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\ProgressRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/ProgressRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\Renderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/Renderer.php',
    'Laravel\\Prompts\\Themes\\Default\\SearchPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/SearchPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\SelectPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/SelectPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\SpinnerRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/SpinnerRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\StreamRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/StreamRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\SuggestPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/SuggestPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\TableRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/TableRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\TaskRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/TaskRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\TextPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/TextPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\TextareaPromptRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/TextareaPromptRenderer.php',
    'Laravel\\Prompts\\Themes\\Default\\TitleRenderer' => $vendorDir . '/laravel/prompts/src/Themes/Default/TitleRenderer.php',
    'Laravel\\Prompts\\Title' => $vendorDir . '/laravel/prompts/src/Title.php',
    'NoDiscard' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/NoDiscard.php',
    'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
    'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php',
    'Pdo\\Dblib' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php',
    'Pdo\\Firebird' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.php',
    'Pdo\\Mysql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php',
    'Pdo\\Odbc' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php',
    'Pdo\\Pgsql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php',
    'Pdo\\Sqlite' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php',
    'Psr\\Clock\\ClockInterface' => $vendorDir . '/psr/clock/src/ClockInterface.php',
    'Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php',
    'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php',
    'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php',
    'Psr\\SimpleCache\\CacheException' => $vendorDir . '/psr/simple-cache/src/CacheException.php',
    'Psr\\SimpleCache\\CacheInterface' => $vendorDir . '/psr/simple-cache/src/CacheInterface.php',
    'Psr\\SimpleCache\\InvalidArgumentException' => $vendorDir . '/psr/simple-cache/src/InvalidArgumentException.php',
    'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
    'RoundingMode' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php',
    'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php',
    'SortDirection' => $vendorDir . '/symfony/polyfill-php86/Resources/stubs/SortDirection.php',
    'Symfony\\Component\\Clock\\Clock' => $vendorDir . '/symfony/clock/Clock.php',
    'Symfony\\Component\\Clock\\ClockAwareTrait' => $vendorDir . '/symfony/clock/ClockAwareTrait.php',
    'Symfony\\Component\\Clock\\ClockInterface' => $vendorDir . '/symfony/clock/ClockInterface.php',
    'Symfony\\Component\\Clock\\DatePoint' => $vendorDir . '/symfony/clock/DatePoint.php',
    'Symfony\\Component\\Clock\\MockClock' => $vendorDir . '/symfony/clock/MockClock.php',
    'Symfony\\Component\\Clock\\MonotonicClock' => $vendorDir . '/symfony/clock/MonotonicClock.php',
    'Symfony\\Component\\Clock\\NativeClock' => $vendorDir . '/symfony/clock/NativeClock.php',
    'Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => $vendorDir . '/symfony/clock/Test/ClockSensitiveTrait.php',
    'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Application.php',
    'Symfony\\Component\\Console\\Attribute\\Argument' => $vendorDir . '/symfony/console/Attribute/Argument.php',
    'Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/symfony/console/Attribute/AsCommand.php',
    'Symfony\\Component\\Console\\Attribute\\Ask' => $vendorDir . '/symfony/console/Attribute/Ask.php',
    'Symfony\\Component\\Console\\Attribute\\Interact' => $vendorDir . '/symfony/console/Attribute/Interact.php',
    'Symfony\\Component\\Console\\Attribute\\InteractiveAttributeInterface' => $vendorDir . '/symfony/console/Attribute/InteractiveAttributeInterface.php',
    'Symfony\\Component\\Console\\Attribute\\MapInput' => $vendorDir . '/symfony/console/Attribute/MapInput.php',
    'Symfony\\Component\\Console\\Attribute\\Option' => $vendorDir . '/symfony/console/Attribute/Option.php',
    'Symfony\\Component\\Console\\Attribute\\Reflection\\ReflectionMember' => $vendorDir . '/symfony/console/Attribute/Reflection/ReflectionMember.php',
    'Symfony\\Component\\Console\\CI\\GithubActionReporter' => $vendorDir . '/symfony/console/CI/GithubActionReporter.php',
    'Symfony\\Component\\Console\\Color' => $vendorDir . '/symfony/console/Color.php',
    'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
    'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
    'Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/symfony/console/CommandLoader/FactoryCommandLoader.php',
    'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Command/Command.php',
    'Symfony\\Component\\Console\\Command\\CompleteCommand' => $vendorDir . '/symfony/console/Command/CompleteCommand.php',
    'Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => $vendorDir . '/symfony/console/Command/DumpCompletionCommand.php',
    'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Command/HelpCommand.php',
    'Symfony\\Component\\Console\\Command\\InvokableCommand' => $vendorDir . '/symfony/console/Command/InvokableCommand.php',
    'Symfony\\Component\\Console\\Command\\LazyCommand' => $vendorDir . '/symfony/console/Command/LazyCommand.php',
    'Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Command/ListCommand.php',
    'Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/symfony/console/Command/LockableTrait.php',
    'Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => $vendorDir . '/symfony/console/Command/SignalableCommandInterface.php',
    'Symfony\\Component\\Console\\Command\\TraceableCommand' => $vendorDir . '/symfony/console/Command/TraceableCommand.php',
    'Symfony\\Component\\Console\\Completion\\CompletionInput' => $vendorDir . '/symfony/console/Completion/CompletionInput.php',
    'Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => $vendorDir . '/symfony/console/Completion/CompletionSuggestions.php',
    'Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/BashCompletionOutput.php',
    'Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => $vendorDir . '/symfony/console/Completion/Output/CompletionOutputInterface.php',
    'Symfony\\Component\\Console\\Completion\\Output\\FishCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/FishCompletionOutput.php',
    'Symfony\\Component\\Console\\Completion\\Output\\ZshCompletionOutput' => $vendorDir . '/symfony/console/Completion/Output/ZshCompletionOutput.php',
    'Symfony\\Component\\Console\\Completion\\Suggestion' => $vendorDir . '/symfony/console/Completion/Suggestion.php',
    'Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/ConsoleEvents.php',
    'Symfony\\Component\\Console\\Cursor' => $vendorDir . '/symfony/console/Cursor.php',
    'Symfony\\Component\\Console\\DataCollector\\CommandDataCollector' => $vendorDir . '/symfony/console/DataCollector/CommandDataCollector.php',
    'Symfony\\Component\\Console\\Debug\\CliRequest' => $vendorDir . '/symfony/console/Debug/CliRequest.php',
    'Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
    'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Descriptor/ApplicationDescription.php',
    'Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Descriptor/Descriptor.php',
    'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Descriptor/DescriptorInterface.php',
    'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Descriptor/JsonDescriptor.php',
    'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Descriptor/MarkdownDescriptor.php',
    'Symfony\\Component\\Console\\Descriptor\\ReStructuredTextDescriptor' => $vendorDir . '/symfony/console/Descriptor/ReStructuredTextDescriptor.php',
    'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Descriptor/TextDescriptor.php',
    'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Descriptor/XmlDescriptor.php',
    'Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/symfony/console/EventListener/ErrorListener.php',
    'Symfony\\Component\\Console\\Event\\ConsoleAlarmEvent' => $vendorDir . '/symfony/console/Event/ConsoleAlarmEvent.php',
    'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Event/ConsoleCommandEvent.php',
    'Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/symfony/console/Event/ConsoleErrorEvent.php',
    'Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Event/ConsoleEvent.php',
    'Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => $vendorDir . '/symfony/console/Event/ConsoleSignalEvent.php',
    'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Event/ConsoleTerminateEvent.php',
    'Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/symfony/console/Exception/CommandNotFoundException.php',
    'Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/console/Exception/ExceptionInterface.php',
    'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/console/Exception/InvalidArgumentException.php',
    'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/symfony/console/Exception/InvalidOptionException.php',
    'Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/symfony/console/Exception/LogicException.php',
    'Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/symfony/console/Exception/MissingInputException.php',
    'Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/symfony/console/Exception/NamespaceNotFoundException.php',
    'Symfony\\Component\\Console\\Exception\\RunCommandFailedException' => $vendorDir . '/symfony/console/Exception/RunCommandFailedException.php',
    'Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/symfony/console/Exception/RuntimeException.php',
    'Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatter.php',
    'Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/NullOutputFormatterStyle.php',
    'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Formatter/OutputFormatter.php',
    'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterInterface.php',
    'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyle.php',
    'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
    'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
    'Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php',
    'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Helper/DebugFormatterHelper.php',
    'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Helper/DescriptorHelper.php',
    'Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/symfony/console/Helper/Dumper.php',
    'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Helper/FormatterHelper.php',
    'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Helper/Helper.php',
    'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Helper/HelperInterface.php',
    'Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Helper/HelperSet.php',
    'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Helper/InputAwareHelper.php',
    'Symfony\\Component\\Console\\Helper\\OutputWrapper' => $vendorDir . '/symfony/console/Helper/OutputWrapper.php',
    'Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Helper/ProcessHelper.php',
    'Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Helper/ProgressBar.php',
    'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/symfony/console/Helper/ProgressIndicator.php',
    'Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Helper/QuestionHelper.php',
    'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/symfony/console/Helper/SymfonyQuestionHelper.php',
    'Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Helper/Table.php',
    'Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/symfony/console/Helper/TableCell.php',
    'Symfony\\Component\\Console\\Helper\\TableCellStyle' => $vendorDir . '/symfony/console/Helper/TableCellStyle.php',
    'Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/symfony/console/Helper/TableRows.php',
    'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Helper/TableSeparator.php',
    'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Helper/TableStyle.php',
    'Symfony\\Component\\Console\\Helper\\TerminalInputHelper' => $vendorDir . '/symfony/console/Helper/TerminalInputHelper.php',
    'Symfony\\Component\\Console\\Helper\\TreeHelper' => $vendorDir . '/symfony/console/Helper/TreeHelper.php',
    'Symfony\\Component\\Console\\Helper\\TreeNode' => $vendorDir . '/symfony/console/Helper/TreeNode.php',
    'Symfony\\Component\\Console\\Helper\\TreeStyle' => $vendorDir . '/symfony/console/Helper/TreeStyle.php',
    'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Input/ArgvInput.php',
    'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Input/ArrayInput.php',
    'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Input/Input.php',
    'Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Input/InputArgument.php',
    'Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Input/InputAwareInterface.php',
    'Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Input/InputDefinition.php',
    'Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Input/InputInterface.php',
    'Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Input/InputOption.php',
    'Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/symfony/console/Input/StreamableInputInterface.php',
    'Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Input/StringInput.php',
    'Symfony\\Component\\Console\\Interaction\\Interaction' => $vendorDir . '/symfony/console/Interaction/Interaction.php',
    'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Logger/ConsoleLogger.php',
    'Symfony\\Component\\Console\\Messenger\\RunCommandContext' => $vendorDir . '/symfony/console/Messenger/RunCommandContext.php',
    'Symfony\\Component\\Console\\Messenger\\RunCommandMessage' => $vendorDir . '/symfony/console/Messenger/RunCommandMessage.php',
    'Symfony\\Component\\Console\\Messenger\\RunCommandMessageHandler' => $vendorDir . '/symfony/console/Messenger/RunCommandMessageHandler.php',
    'Symfony\\Component\\Console\\Output\\AnsiColorMode' => $vendorDir . '/symfony/console/Output/AnsiColorMode.php',
    'Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Output/BufferedOutput.php',
    'Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Output/ConsoleOutput.php',
    'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Output/ConsoleOutputInterface.php',
    'Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/symfony/console/Output/ConsoleSectionOutput.php',
    'Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Output/NullOutput.php',
    'Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Output/Output.php',
    'Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Output/OutputInterface.php',
    'Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Output/StreamOutput.php',
    'Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/symfony/console/Output/TrimmedBufferOutput.php',
    'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Question/ChoiceQuestion.php',
    'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Question/ConfirmationQuestion.php',
    'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Question/Question.php',
    'Symfony\\Component\\Console\\SignalRegistry\\SignalMap' => $vendorDir . '/symfony/console/SignalRegistry/SignalMap.php',
    'Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => $vendorDir . '/symfony/console/SignalRegistry/SignalRegistry.php',
    'Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/symfony/console/SingleCommandApplication.php',
    'Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/symfony/console/Style/OutputStyle.php',
    'Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/symfony/console/Style/StyleInterface.php',
    'Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/symfony/console/Style/SymfonyStyle.php',
    'Symfony\\Component\\Console\\Terminal' => $vendorDir . '/symfony/console/Terminal.php',
    'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Tester/ApplicationTester.php',
    'Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => $vendorDir . '/symfony/console/Tester/CommandCompletionTester.php',
    'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Tester/CommandTester.php',
    'Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => $vendorDir . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php',
    'Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/symfony/console/Tester/TesterTrait.php',
    'Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Comparator/Comparator.php',
    'Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Comparator/DateComparator.php',
    'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Comparator/NumberComparator.php',
    'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Exception/AccessDeniedException.php',
    'Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => $vendorDir . '/symfony/finder/Exception/DirectoryNotFoundException.php',
    'Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Finder.php',
    'Symfony\\Component\\Finder\\Gitignore' => $vendorDir . '/symfony/finder/Gitignore.php',
    'Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Glob.php',
    'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Iterator/CustomFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Iterator/FilenameFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => $vendorDir . '/symfony/finder/Iterator/LazyIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Iterator/PathFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Iterator/SortableIterator.php',
    'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => $vendorDir . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php',
    'Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/SplFileInfo.php',
    'Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Exception/ExceptionInterface.php',
    'Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Exception/InvalidArgumentException.php',
    'Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php',
    'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php',
    'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php',
    'Symfony\\Component\\Process\\Exception\\ProcessStartFailedException' => $vendorDir . '/symfony/process/Exception/ProcessStartFailedException.php',
    'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php',
    'Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => $vendorDir . '/symfony/process/Exception/RunProcessFailedException.php',
    'Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php',
    'Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/ExecutableFinder.php',
    'Symfony\\Component\\Process\\InputStream' => $vendorDir . '/symfony/process/InputStream.php',
    'Symfony\\Component\\Process\\Messenger\\RunProcessContext' => $vendorDir . '/symfony/process/Messenger/RunProcessContext.php',
    'Symfony\\Component\\Process\\Messenger\\RunProcessMessage' => $vendorDir . '/symfony/process/Messenger/RunProcessMessage.php',
    'Symfony\\Component\\Process\\Messenger\\RunProcessMessageHandler' => $vendorDir . '/symfony/process/Messenger/RunProcessMessageHandler.php',
    'Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/PhpExecutableFinder.php',
    'Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/PhpProcess.php',
    'Symfony\\Component\\Process\\PhpSubprocess' => $vendorDir . '/symfony/process/PhpSubprocess.php',
    'Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Pipes/AbstractPipes.php',
    'Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Pipes/PipesInterface.php',
    'Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Pipes/UnixPipes.php',
    'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Pipes/WindowsPipes.php',
    'Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Process.php',
    'Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/ProcessUtils.php',
    'Symfony\\Component\\String\\AbstractString' => $vendorDir . '/symfony/string/AbstractString.php',
    'Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/symfony/string/AbstractUnicodeString.php',
    'Symfony\\Component\\String\\ByteString' => $vendorDir . '/symfony/string/ByteString.php',
    'Symfony\\Component\\String\\CodePointString' => $vendorDir . '/symfony/string/CodePointString.php',
    'Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/string/Exception/ExceptionInterface.php',
    'Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/string/Exception/InvalidArgumentException.php',
    'Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/symfony/string/Exception/RuntimeException.php',
    'Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/symfony/string/Inflector/EnglishInflector.php',
    'Symfony\\Component\\String\\Inflector\\FrenchInflector' => $vendorDir . '/symfony/string/Inflector/FrenchInflector.php',
    'Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/symfony/string/Inflector/InflectorInterface.php',
    'Symfony\\Component\\String\\Inflector\\SpanishInflector' => $vendorDir . '/symfony/string/Inflector/SpanishInflector.php',
    'Symfony\\Component\\String\\LazyString' => $vendorDir . '/symfony/string/LazyString.php',
    'Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/symfony/string/Slugger/AsciiSlugger.php',
    'Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/symfony/string/Slugger/SluggerInterface.php',
    'Symfony\\Component\\String\\TruncateMode' => $vendorDir . '/symfony/string/TruncateMode.php',
    'Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/symfony/string/UnicodeString.php',
    'Symfony\\Component\\Translation\\CatalogueMetadataAwareInterface' => $vendorDir . '/symfony/translation/CatalogueMetadataAwareInterface.php',
    'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => $vendorDir . '/symfony/translation/Catalogue/AbstractOperation.php',
    'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => $vendorDir . '/symfony/translation/Catalogue/MergeOperation.php',
    'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => $vendorDir . '/symfony/translation/Catalogue/OperationInterface.php',
    'Symfony\\Component\\Translation\\Catalogue\\TargetOperation' => $vendorDir . '/symfony/translation/Catalogue/TargetOperation.php',
    'Symfony\\Component\\Translation\\Command\\TranslationLintCommand' => $vendorDir . '/symfony/translation/Command/TranslationLintCommand.php',
    'Symfony\\Component\\Translation\\Command\\TranslationPullCommand' => $vendorDir . '/symfony/translation/Command/TranslationPullCommand.php',
    'Symfony\\Component\\Translation\\Command\\TranslationPushCommand' => $vendorDir . '/symfony/translation/Command/TranslationPushCommand.php',
    'Symfony\\Component\\Translation\\Command\\TranslationTrait' => $vendorDir . '/symfony/translation/Command/TranslationTrait.php',
    'Symfony\\Component\\Translation\\Command\\XliffLintCommand' => $vendorDir . '/symfony/translation/Command/XliffLintCommand.php',
    'Symfony\\Component\\Translation\\DataCollectorTranslator' => $vendorDir . '/symfony/translation/DataCollectorTranslator.php',
    'Symfony\\Component\\Translation\\DataCollector\\TranslationDataCollector' => $vendorDir . '/symfony/translation/DataCollector/TranslationDataCollector.php',
    'Symfony\\Component\\Translation\\DependencyInjection\\DataCollectorTranslatorPass' => $vendorDir . '/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php',
    'Symfony\\Component\\Translation\\DependencyInjection\\LoggingTranslatorPass' => $vendorDir . '/symfony/translation/DependencyInjection/LoggingTranslatorPass.php',
    'Symfony\\Component\\Translation\\DependencyInjection\\TranslationDumperPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslationDumperPass.php',
    'Symfony\\Component\\Translation\\DependencyInjection\\TranslationExtractorPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslationExtractorPass.php',
    'Symfony\\Component\\Translation\\DependencyInjection\\TranslatorPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslatorPass.php',
    'Symfony\\Component\\Translation\\DependencyInjection\\TranslatorPathsPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslatorPathsPass.php',
    'Symfony\\Component\\Translation\\Dumper\\CsvFileDumper' => $vendorDir . '/symfony/translation/Dumper/CsvFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\DumperInterface' => $vendorDir . '/symfony/translation/Dumper/DumperInterface.php',
    'Symfony\\Component\\Translation\\Dumper\\FileDumper' => $vendorDir . '/symfony/translation/Dumper/FileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\IcuResFileDumper' => $vendorDir . '/symfony/translation/Dumper/IcuResFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\IniFileDumper' => $vendorDir . '/symfony/translation/Dumper/IniFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\JsonFileDumper' => $vendorDir . '/symfony/translation/Dumper/JsonFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\MoFileDumper' => $vendorDir . '/symfony/translation/Dumper/MoFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\PhpFileDumper' => $vendorDir . '/symfony/translation/Dumper/PhpFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\PoFileDumper' => $vendorDir . '/symfony/translation/Dumper/PoFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\QtFileDumper' => $vendorDir . '/symfony/translation/Dumper/QtFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\XliffFileDumper' => $vendorDir . '/symfony/translation/Dumper/XliffFileDumper.php',
    'Symfony\\Component\\Translation\\Dumper\\YamlFileDumper' => $vendorDir . '/symfony/translation/Dumper/YamlFileDumper.php',
    'Symfony\\Component\\Translation\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/translation/Exception/ExceptionInterface.php',
    'Symfony\\Component\\Translation\\Exception\\IncompleteDsnException' => $vendorDir . '/symfony/translation/Exception/IncompleteDsnException.php',
    'Symfony\\Component\\Translation\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/translation/Exception/InvalidArgumentException.php',
    'Symfony\\Component\\Translation\\Exception\\InvalidResourceException' => $vendorDir . '/symfony/translation/Exception/InvalidResourceException.php',
    'Symfony\\Component\\Translation\\Exception\\LogicException' => $vendorDir . '/symfony/translation/Exception/LogicException.php',
    'Symfony\\Component\\Translation\\Exception\\MissingRequiredOptionException' => $vendorDir . '/symfony/translation/Exception/MissingRequiredOptionException.php',
    'Symfony\\Component\\Translation\\Exception\\NotFoundResourceException' => $vendorDir . '/symfony/translation/Exception/NotFoundResourceException.php',
    'Symfony\\Component\\Translation\\Exception\\ProviderException' => $vendorDir . '/symfony/translation/Exception/ProviderException.php',
    'Symfony\\Component\\Translation\\Exception\\ProviderExceptionInterface' => $vendorDir . '/symfony/translation/Exception/ProviderExceptionInterface.php',
    'Symfony\\Component\\Translation\\Exception\\RuntimeException' => $vendorDir . '/symfony/translation/Exception/RuntimeException.php',
    'Symfony\\Component\\Translation\\Exception\\UnsupportedSchemeException' => $vendorDir . '/symfony/translation/Exception/UnsupportedSchemeException.php',
    'Symfony\\Component\\Translation\\Extractor\\AbstractFileExtractor' => $vendorDir . '/symfony/translation/Extractor/AbstractFileExtractor.php',
    'Symfony\\Component\\Translation\\Extractor\\ChainExtractor' => $vendorDir . '/symfony/translation/Extractor/ChainExtractor.php',
    'Symfony\\Component\\Translation\\Extractor\\ExtractorInterface' => $vendorDir . '/symfony/translation/Extractor/ExtractorInterface.php',
    'Symfony\\Component\\Translation\\Extractor\\PhpAstExtractor' => $vendorDir . '/symfony/translation/Extractor/PhpAstExtractor.php',
    'Symfony\\Component\\Translation\\Extractor\\Visitor\\AbstractVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/AbstractVisitor.php',
    'Symfony\\Component\\Translation\\Extractor\\Visitor\\ConstraintVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/ConstraintVisitor.php',
    'Symfony\\Component\\Translation\\Extractor\\Visitor\\TransMethodVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/TransMethodVisitor.php',
    'Symfony\\Component\\Translation\\Extractor\\Visitor\\TranslatableMessageVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php',
    'Symfony\\Component\\Translation\\Formatter\\IntlFormatter' => $vendorDir . '/symfony/translation/Formatter/IntlFormatter.php',
    'Symfony\\Component\\Translation\\Formatter\\IntlFormatterInterface' => $vendorDir . '/symfony/translation/Formatter/IntlFormatterInterface.php',
    'Symfony\\Component\\Translation\\Formatter\\MessageFormatter' => $vendorDir . '/symfony/translation/Formatter/MessageFormatter.php',
    'Symfony\\Component\\Translation\\Formatter\\MessageFormatterInterface' => $vendorDir . '/symfony/translation/Formatter/MessageFormatterInterface.php',
    'Symfony\\Component\\Translation\\IdentityTranslator' => $vendorDir . '/symfony/translation/IdentityTranslator.php',
    'Symfony\\Component\\Translation\\Loader\\ArrayLoader' => $vendorDir . '/symfony/translation/Loader/ArrayLoader.php',
    'Symfony\\Component\\Translation\\Loader\\CsvFileLoader' => $vendorDir . '/symfony/translation/Loader/CsvFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\FileLoader' => $vendorDir . '/symfony/translation/Loader/FileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\IcuDatFileLoader' => $vendorDir . '/symfony/translation/Loader/IcuDatFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\IcuResFileLoader' => $vendorDir . '/symfony/translation/Loader/IcuResFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\IniFileLoader' => $vendorDir . '/symfony/translation/Loader/IniFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\JsonFileLoader' => $vendorDir . '/symfony/translation/Loader/JsonFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\LoaderInterface' => $vendorDir . '/symfony/translation/Loader/LoaderInterface.php',
    'Symfony\\Component\\Translation\\Loader\\MoFileLoader' => $vendorDir . '/symfony/translation/Loader/MoFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/translation/Loader/PhpFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\PoFileLoader' => $vendorDir . '/symfony/translation/Loader/PoFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\QtFileLoader' => $vendorDir . '/symfony/translation/Loader/QtFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\XliffFileLoader' => $vendorDir . '/symfony/translation/Loader/XliffFileLoader.php',
    'Symfony\\Component\\Translation\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/translation/Loader/YamlFileLoader.php',
    'Symfony\\Component\\Translation\\LocaleSwitcher' => $vendorDir . '/symfony/translation/LocaleSwitcher.php',
    'Symfony\\Component\\Translation\\LoggingTranslator' => $vendorDir . '/symfony/translation/LoggingTranslator.php',
    'Symfony\\Component\\Translation\\MessageCatalogue' => $vendorDir . '/symfony/translation/MessageCatalogue.php',
    'Symfony\\Component\\Translation\\MessageCatalogueInterface' => $vendorDir . '/symfony/translation/MessageCatalogueInterface.php',
    'Symfony\\Component\\Translation\\MetadataAwareInterface' => $vendorDir . '/symfony/translation/MetadataAwareInterface.php',
    'Symfony\\Component\\Translation\\Provider\\AbstractProviderFactory' => $vendorDir . '/symfony/translation/Provider/AbstractProviderFactory.php',
    'Symfony\\Component\\Translation\\Provider\\Dsn' => $vendorDir . '/symfony/translation/Provider/Dsn.php',
    'Symfony\\Component\\Translation\\Provider\\FilteringProvider' => $vendorDir . '/symfony/translation/Provider/FilteringProvider.php',
    'Symfony\\Component\\Translation\\Provider\\NullProvider' => $vendorDir . '/symfony/translation/Provider/NullProvider.php',
    'Symfony\\Component\\Translation\\Provider\\NullProviderFactory' => $vendorDir . '/symfony/translation/Provider/NullProviderFactory.php',
    'Symfony\\Component\\Translation\\Provider\\ProviderFactoryInterface' => $vendorDir . '/symfony/translation/Provider/ProviderFactoryInterface.php',
    'Symfony\\Component\\Translation\\Provider\\ProviderInterface' => $vendorDir . '/symfony/translation/Provider/ProviderInterface.php',
    'Symfony\\Component\\Translation\\Provider\\TranslationProviderCollection' => $vendorDir . '/symfony/translation/Provider/TranslationProviderCollection.php',
    'Symfony\\Component\\Translation\\Provider\\TranslationProviderCollectionFactory' => $vendorDir . '/symfony/translation/Provider/TranslationProviderCollectionFactory.php',
    'Symfony\\Component\\Translation\\PseudoLocalizationTranslator' => $vendorDir . '/symfony/translation/PseudoLocalizationTranslator.php',
    'Symfony\\Component\\Translation\\Reader\\TranslationReader' => $vendorDir . '/symfony/translation/Reader/TranslationReader.php',
    'Symfony\\Component\\Translation\\Reader\\TranslationReaderInterface' => $vendorDir . '/symfony/translation/Reader/TranslationReaderInterface.php',
    'Symfony\\Component\\Translation\\StaticMessage' => $vendorDir . '/symfony/translation/StaticMessage.php',
    'Symfony\\Component\\Translation\\Test\\AbstractProviderFactoryTestCase' => $vendorDir . '/symfony/translation/Test/AbstractProviderFactoryTestCase.php',
    'Symfony\\Component\\Translation\\Test\\IncompleteDsnTestTrait' => $vendorDir . '/symfony/translation/Test/IncompleteDsnTestTrait.php',
    'Symfony\\Component\\Translation\\Test\\ProviderFactoryTestCase' => $vendorDir . '/symfony/translation/Test/ProviderFactoryTestCase.php',
    'Symfony\\Component\\Translation\\Test\\ProviderTestCase' => $vendorDir . '/symfony/translation/Test/ProviderTestCase.php',
    'Symfony\\Component\\Translation\\TranslatableMessage' => $vendorDir . '/symfony/translation/TranslatableMessage.php',
    'Symfony\\Component\\Translation\\Translator' => $vendorDir . '/symfony/translation/Translator.php',
    'Symfony\\Component\\Translation\\TranslatorBag' => $vendorDir . '/symfony/translation/TranslatorBag.php',
    'Symfony\\Component\\Translation\\TranslatorBagInterface' => $vendorDir . '/symfony/translation/TranslatorBagInterface.php',
    'Symfony\\Component\\Translation\\Util\\ArrayConverter' => $vendorDir . '/symfony/translation/Util/ArrayConverter.php',
    'Symfony\\Component\\Translation\\Util\\XliffUtils' => $vendorDir . '/symfony/translation/Util/XliffUtils.php',
    'Symfony\\Component\\Translation\\Writer\\TranslationWriter' => $vendorDir . '/symfony/translation/Writer/TranslationWriter.php',
    'Symfony\\Component\\Translation\\Writer\\TranslationWriterInterface' => $vendorDir . '/symfony/translation/Writer/TranslationWriterInterface.php',
    'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php',
    'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php',
    'Symfony\\Contracts\\Service\\ContainerAwareInterface' => $vendorDir . '/symfony/service-contracts/ContainerAwareInterface.php',
    'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php',
    'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => $vendorDir . '/symfony/service-contracts/ServiceCollectionInterface.php',
    'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php',
    'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php',
    'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php',
    'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php',
    'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php',
    'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => $vendorDir . '/symfony/translation-contracts/LocaleAwareInterface.php',
    'Symfony\\Contracts\\Translation\\TranslatableInterface' => $vendorDir . '/symfony/translation-contracts/TranslatableInterface.php',
    'Symfony\\Contracts\\Translation\\TranslatorInterface' => $vendorDir . '/symfony/translation-contracts/TranslatorInterface.php',
    'Symfony\\Contracts\\Translation\\TranslatorTrait' => $vendorDir . '/symfony/translation-contracts/TranslatorTrait.php',
    'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/symfony/polyfill-ctype/Ctype.php',
    'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/symfony/polyfill-intl-grapheme/Grapheme.php',
    'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php',
    'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
    'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php',
    'Symfony\\Polyfill\\Php84\\Php84' => $vendorDir . '/symfony/polyfill-php84/Php84.php',
    'Symfony\\Polyfill\\Php85\\Php85' => $vendorDir . '/symfony/polyfill-php85/Php85.php',
    'Symfony\\Polyfill\\Php86\\Php86' => $vendorDir . '/symfony/polyfill-php86/Php86.php',
    'voku\\helper\\ASCII' => $vendorDir . '/voku/portable-ascii/src/voku/helper/ASCII.php',
);
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
    'Symfony\\Polyfill\\Php86\\' => array($vendorDir . '/symfony/polyfill-php86'),
    'Symfony\\Polyfill\\Php85\\' => array($vendorDir . '/symfony/polyfill-php85'),
    'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
    'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'),
    'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
    'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
    'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
    'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
    'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
    'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
    'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
    'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
    'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
    'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
    'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
    'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
    'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
    'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
    'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
    'Laravel\\Prompts\\' => array($vendorDir . '/laravel/prompts/src'),
    'Laravel\\Installer\\Console\\' => array($baseDir . '/src'),
    'Laravel\\AgentDetector\\' => array($vendorDir . '/laravel/agent-detector/src'),
    'Illuminate\\Support\\' => array($vendorDir . '/illuminate/support', $vendorDir . '/illuminate/reflection', $vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/conditionable', $vendorDir . '/illuminate/macroable'),
    'Illuminate\\Filesystem\\' => array($vendorDir . '/illuminate/filesystem'),
    'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
    'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/src'),
    'Carbon\\Doctrine\\' => array($vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine'),
    'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
    'BeyondCode\\HerdConfiguration\\' => array($vendorDir . '/beyondcode/herd-configuration/src'),
);
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer;

use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;

/**
 * This class is copied in every Composer installed project and available to all
 *
 * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
 *
 * To require its presence, you can require `composer-runtime-api ^2.0`
 *
 * @final
 */
class InstalledVersions
{
    /**
     * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
     * @internal
     */
    private static $selfDir = null;

    /**
     * @var mixed[]|null
     * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
     */
    private static $installed;

    /**
     * @var bool
     */
    private static $installedIsLocalDir;

    /**
     * @var bool|null
     */
    private static $canGetVendors;

    /**
     * @var array[]
     * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static $installedByVendor = array();

    /**
     * Returns a list of all package names which are present, either by being installed, replaced or provided
     *
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }

        if (1 === \count($packages)) {
            return $packages[0];
        }

        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }

    /**
     * Returns a list of all package names with a specific type e.g. 'library'
     *
     * @param  string   $type
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackagesByType($type)
    {
        $packagesByType = array();

        foreach (self::getInstalled() as $installed) {
            foreach ($installed['versions'] as $name => $package) {
                if (isset($package['type']) && $package['type'] === $type) {
                    $packagesByType[] = $name;
                }
            }
        }

        return $packagesByType;
    }

    /**
     * Checks whether the given package is installed
     *
     * This also returns true if the package name is provided or replaced by another package
     *
     * @param  string $packageName
     * @param  bool   $includeDevRequirements
     * @return bool
     */
    public static function isInstalled($packageName, $includeDevRequirements = true)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
            }
        }

        return false;
    }

    /**
     * Checks whether the given package satisfies a version constraint
     *
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     *
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     *
     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
     * @param  string        $packageName
     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     * @return bool
     */
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints((string) $constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));

        return $provided->matches($constraint);
    }

    /**
     * Returns a version constraint representing all the range(s) which are installed for a given package
     *
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     * whether a given version of a package is installed, and not just whether it exists
     *
     * @param  string $packageName
     * @return string Version constraint usable with composer/semver
     */
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }

            return implode(' || ', $ranges);
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }

            return $installed['versions'][$packageName]['version'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }

            return $installed['versions'][$packageName]['pretty_version'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     */
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }

            return $installed['versions'][$packageName]['reference'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
     */
    public static function getInstallPath($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @return array
     * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
     */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();

        return $installed[0]['root'];
    }

    /**
     * Returns the raw installed.php data for custom implementations
     *
     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
     * @return array[]
     * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
     */
    public static function getRawData()
    {
        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);

        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                self::$installed = include __DIR__ . '/installed.php';
            } else {
                self::$installed = array();
            }
        }

        return self::$installed;
    }

    /**
     * Returns the raw data of all installed.php which are currently loaded for custom implementations
     *
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    public static function getAllRawData()
    {
        return self::getInstalled();
    }

    /**
     * Lets you reload the static array from another file
     *
     * This is only useful for complex integrations in which a project needs to use
     * this class but then also needs to execute another project's autoloader in process,
     * and wants to ensure both projects have access to their version of installed.php.
     *
     * A typical case would be PHPUnit, where it would need to make sure it reads all
     * the data it needs from this class, then call reload() with
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     * the project in which it runs can then also use this class safely, without
     * interference between PHPUnit's dependencies and the project's dependencies.
     *
     * @param  array[] $data A vendor/composer/installed.php data set
     * @return void
     *
     * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
     */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();

        // when using reload, we disable the duplicate protection to ensure that self::$installed data is
        // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
        // so we have to assume it does not, and that may result in duplicate data being returned when listing
        // all installed packages for example
        self::$installedIsLocalDir = false;
    }

    /**
     * @return string
     */
    private static function getSelfDir()
    {
        if (self::$selfDir === null) {
            self::$selfDir = strtr(__DIR__, '\\', '/');
        }

        return self::$selfDir;
    }

    /**
     * @return array[]
     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
     */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }

        $installed = array();
        $copiedLocalDir = false;

        if (self::$canGetVendors) {
            $selfDir = self::getSelfDir();
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                $vendorDir = strtr($vendorDir, '\\', '/');
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir.'/composer/installed.php')) {
                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                    $required = require $vendorDir.'/composer/installed.php';
                    self::$installedByVendor[$vendorDir] = $required;
                    $installed[] = $required;
                    if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
                        self::$installed = $required;
                        self::$installedIsLocalDir = true;
                    }
                }
                if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
                    $copiedLocalDir = true;
                }
            }
        }

        if (null === self::$installed) {
            // only require the installed.php file if this file is loaded from its dumped location,
            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
            if (substr(__DIR__, -8, 1) !== 'C') {
                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
                $required = require __DIR__ . '/installed.php';
                self::$installed = $required;
            } else {
                self::$installed = array();
            }
        }

        if (self::$installed !== array() && !$copiedLocalDir) {
            $installed[] = self::$installed;
        }

        return $installed;
    }
}
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
);

Copyright (c) Nils Adermann, Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);

return array(
    '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
    '606a39d89246991a373564698c2d8383' => $vendorDir . '/symfony/polyfill-php85/bootstrap.php',
    '9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
    '2c2415ec15363ede1bff13a287462ba1' => $vendorDir . '/symfony/polyfill-php86/bootstrap.php',
    '23f09fe3194f8c2f70923f90d6702129' => $vendorDir . '/illuminate/collections/functions.php',
    '60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
    '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
    '2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php',
    '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
    '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
    'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
    'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
    '19e6faa27d773988183e0f384143fcad' => $vendorDir . '/illuminate/reflection/helpers.php',
    'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
    'f625ee536139dfb962a398b200bdb2bd' => $vendorDir . '/illuminate/support/functions.php',
    '72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
    '06a34129a50df3d9257ee706cf3c875b' => $vendorDir . '/illuminate/filesystem/functions.php',
    '23dd7ece5822da3d0100ef3deb0ef55f' => $vendorDir . '/laravel/agent-detector/src/functions.php',
    '47e1160838b5e5a10346ac4084b58c23' => $vendorDir . '/laravel/prompts/src/helpers.php',
);
<?php

// platform_check.php @generated by Composer

$issues = array();

if (!(PHP_VERSION_ID >= 80300)) {
    $issues[] = 'Your Composer dependencies require a PHP version ">= 8.3.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
        }
    }
    throw new \RuntimeException(
        'Composer detected issues in your platform: ' . implode(' ', $issues)
    );
}
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInita408f660b5e9690e372ddcb0227a007b
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        require __DIR__ . '/platform_check.php';

        spl_autoload_register(array('ComposerAutoloaderInita408f660b5e9690e372ddcb0227a007b', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
        spl_autoload_unregister(array('ComposerAutoloaderInita408f660b5e9690e372ddcb0227a007b', 'loadClassLoader'));

        require __DIR__ . '/autoload_static.php';
        call_user_func(\Composer\Autoload\ComposerStaticInita408f660b5e9690e372ddcb0227a007b::getInitializer($loader));

        $loader->setClassMapAuthoritative(true);
        $loader->register(true);

        $filesToLoad = \Composer\Autoload\ComposerStaticInita408f660b5e9690e372ddcb0227a007b::$files;
        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

                require $file;
            }
        }, null, null);
        foreach ($filesToLoad as $fileIdentifier => $file) {
            $requireFile($fileIdentifier, $file);
        }

        return $loader;
    }
}
<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInita408f660b5e9690e372ddcb0227a007b
{
    public static $files = array (
        '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
        '606a39d89246991a373564698c2d8383' => __DIR__ . '/..' . '/symfony/polyfill-php85/bootstrap.php',
        '9d2b9fc6db0f153a0a149fefb182415e' => __DIR__ . '/..' . '/symfony/polyfill-php84/bootstrap.php',
        '2c2415ec15363ede1bff13a287462ba1' => __DIR__ . '/..' . '/symfony/polyfill-php86/bootstrap.php',
        '23f09fe3194f8c2f70923f90d6702129' => __DIR__ . '/..' . '/illuminate/collections/functions.php',
        '60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
        '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php',
        '2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php',
        '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
        '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
        'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
        'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
        '19e6faa27d773988183e0f384143fcad' => __DIR__ . '/..' . '/illuminate/reflection/helpers.php',
        'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
        'f625ee536139dfb962a398b200bdb2bd' => __DIR__ . '/..' . '/illuminate/support/functions.php',
        '72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
        '06a34129a50df3d9257ee706cf3c875b' => __DIR__ . '/..' . '/illuminate/filesystem/functions.php',
        '23dd7ece5822da3d0100ef3deb0ef55f' => __DIR__ . '/..' . '/laravel/agent-detector/src/functions.php',
        '47e1160838b5e5a10346ac4084b58c23' => __DIR__ . '/..' . '/laravel/prompts/src/helpers.php',
    );

    public static $prefixLengthsPsr4 = array (
        'v' =>
        array (
            'voku\\' => 5,
        ),
        'S' =>
        array (
            'Symfony\\Polyfill\\Php86\\' => 23,
            'Symfony\\Polyfill\\Php85\\' => 23,
            'Symfony\\Polyfill\\Php84\\' => 23,
            'Symfony\\Polyfill\\Php83\\' => 23,
            'Symfony\\Polyfill\\Mbstring\\' => 26,
            'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
            'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
            'Symfony\\Polyfill\\Ctype\\' => 23,
            'Symfony\\Contracts\\Translation\\' => 30,
            'Symfony\\Contracts\\Service\\' => 26,
            'Symfony\\Component\\Translation\\' => 30,
            'Symfony\\Component\\String\\' => 25,
            'Symfony\\Component\\Process\\' => 26,
            'Symfony\\Component\\Finder\\' => 25,
            'Symfony\\Component\\Console\\' => 26,
            'Symfony\\Component\\Clock\\' => 24,
        ),
        'P' =>
        array (
            'Psr\\SimpleCache\\' => 16,
            'Psr\\Container\\' => 14,
            'Psr\\Clock\\' => 10,
        ),
        'L' =>
        array (
            'Laravel\\Prompts\\' => 16,
            'Laravel\\Installer\\Console\\' => 26,
            'Laravel\\AgentDetector\\' => 22,
        ),
        'I' =>
        array (
            'Illuminate\\Support\\' => 19,
            'Illuminate\\Filesystem\\' => 22,
            'Illuminate\\Contracts\\' => 21,
        ),
        'D' =>
        array (
            'Doctrine\\Inflector\\' => 19,
        ),
        'C' =>
        array (
            'Carbon\\Doctrine\\' => 16,
            'Carbon\\' => 7,
        ),
        'B' =>
        array (
            'BeyondCode\\HerdConfiguration\\' => 29,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'voku\\' =>
        array (
            0 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
        ),
        'Symfony\\Polyfill\\Php86\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php86',
        ),
        'Symfony\\Polyfill\\Php85\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php85',
        ),
        'Symfony\\Polyfill\\Php84\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php84',
        ),
        'Symfony\\Polyfill\\Php83\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-php83',
        ),
        'Symfony\\Polyfill\\Mbstring\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
        ),
        'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
        ),
        'Symfony\\Polyfill\\Intl\\Grapheme\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme',
        ),
        'Symfony\\Polyfill\\Ctype\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
        ),
        'Symfony\\Contracts\\Translation\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/translation-contracts',
        ),
        'Symfony\\Contracts\\Service\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/service-contracts',
        ),
        'Symfony\\Component\\Translation\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/translation',
        ),
        'Symfony\\Component\\String\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/string',
        ),
        'Symfony\\Component\\Process\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/process',
        ),
        'Symfony\\Component\\Finder\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/finder',
        ),
        'Symfony\\Component\\Console\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/console',
        ),
        'Symfony\\Component\\Clock\\' =>
        array (
            0 => __DIR__ . '/..' . '/symfony/clock',
        ),
        'Psr\\SimpleCache\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/simple-cache/src',
        ),
        'Psr\\Container\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/container/src',
        ),
        'Psr\\Clock\\' =>
        array (
            0 => __DIR__ . '/..' . '/psr/clock/src',
        ),
        'Laravel\\Prompts\\' =>
        array (
            0 => __DIR__ . '/..' . '/laravel/prompts/src',
        ),
        'Laravel\\Installer\\Console\\' =>
        array (
            0 => __DIR__ . '/../..' . '/src',
        ),
        'Laravel\\AgentDetector\\' =>
        array (
            0 => __DIR__ . '/..' . '/laravel/agent-detector/src',
        ),
        'Illuminate\\Support\\' =>
        array (
            0 => __DIR__ . '/..' . '/illuminate/support',
            1 => __DIR__ . '/..' . '/illuminate/reflection',
            2 => __DIR__ . '/..' . '/illuminate/collections',
            3 => __DIR__ . '/..' . '/illuminate/conditionable',
            4 => __DIR__ . '/..' . '/illuminate/macroable',
        ),
        'Illuminate\\Filesystem\\' =>
        array (
            0 => __DIR__ . '/..' . '/illuminate/filesystem',
        ),
        'Illuminate\\Contracts\\' =>
        array (
            0 => __DIR__ . '/..' . '/illuminate/contracts',
        ),
        'Doctrine\\Inflector\\' =>
        array (
            0 => __DIR__ . '/..' . '/doctrine/inflector/src',
        ),
        'Carbon\\Doctrine\\' =>
        array (
            0 => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine',
        ),
        'Carbon\\' =>
        array (
            0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
        ),
        'BeyondCode\\HerdConfiguration\\' =>
        array (
            0 => __DIR__ . '/..' . '/beyondcode/herd-configuration/src',
        ),
    );

    public static $classMap = array (
        'BeyondCode\\HerdConfiguration\\HerdConfiguration' => __DIR__ . '/..' . '/beyondcode/herd-configuration/src/HerdConfiguration.php',
        'Carbon\\AbstractTranslator' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/AbstractTranslator.php',
        'Carbon\\Callback' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Callback.php',
        'Carbon\\Carbon' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Carbon.php',
        'Carbon\\CarbonConverterInterface' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonConverterInterface.php',
        'Carbon\\CarbonImmutable' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonImmutable.php',
        'Carbon\\CarbonInterface' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonInterface.php',
        'Carbon\\CarbonInterval' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
        'Carbon\\CarbonPeriod' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonPeriod.php',
        'Carbon\\CarbonPeriodImmutable' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonPeriodImmutable.php',
        'Carbon\\CarbonTimeZone' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonTimeZone.php',
        'Carbon\\Cli\\Invoker' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Cli/Invoker.php',
        'Carbon\\Constants\\DiffOptions' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Constants/DiffOptions.php',
        'Carbon\\Constants\\Format' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Constants/Format.php',
        'Carbon\\Constants\\TranslationOptions' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Constants/TranslationOptions.php',
        'Carbon\\Constants\\UnitValue' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Constants/UnitValue.php',
        'Carbon\\Doctrine\\CarbonDoctrineType' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonDoctrineType.php',
        'Carbon\\Doctrine\\CarbonImmutableType' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonImmutableType.php',
        'Carbon\\Doctrine\\CarbonType' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonType.php',
        'Carbon\\Doctrine\\CarbonTypeConverter' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonTypeConverter.php',
        'Carbon\\Doctrine\\DateTimeDefaultPrecision' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeDefaultPrecision.php',
        'Carbon\\Doctrine\\DateTimeImmutableType' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeImmutableType.php',
        'Carbon\\Doctrine\\DateTimeType' => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeType.php',
        'Carbon\\Exceptions\\BadComparisonUnitException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php',
        'Carbon\\Exceptions\\BadFluentConstructorException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.php',
        'Carbon\\Exceptions\\BadFluentSetterException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php',
        'Carbon\\Exceptions\\BadMethodCallException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php',
        'Carbon\\Exceptions\\EndLessPeriodException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/EndLessPeriodException.php',
        'Carbon\\Exceptions\\Exception' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/Exception.php',
        'Carbon\\Exceptions\\ImmutableException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php',
        'Carbon\\Exceptions\\InvalidArgumentException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.php',
        'Carbon\\Exceptions\\InvalidCastException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php',
        'Carbon\\Exceptions\\InvalidDateException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php',
        'Carbon\\Exceptions\\InvalidFormatException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php',
        'Carbon\\Exceptions\\InvalidIntervalException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php',
        'Carbon\\Exceptions\\InvalidPeriodDateException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php',
        'Carbon\\Exceptions\\InvalidPeriodParameterException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php',
        'Carbon\\Exceptions\\InvalidTimeZoneException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php',
        'Carbon\\Exceptions\\InvalidTypeException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php',
        'Carbon\\Exceptions\\NotACarbonClassException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php',
        'Carbon\\Exceptions\\NotAPeriodException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php',
        'Carbon\\Exceptions\\NotLocaleAwareException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php',
        'Carbon\\Exceptions\\OutOfRangeException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php',
        'Carbon\\Exceptions\\ParseErrorException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php',
        'Carbon\\Exceptions\\RuntimeException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.php',
        'Carbon\\Exceptions\\UnitException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnitException.php',
        'Carbon\\Exceptions\\UnitNotConfiguredException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php',
        'Carbon\\Exceptions\\UnknownGetterException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php',
        'Carbon\\Exceptions\\UnknownMethodException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php',
        'Carbon\\Exceptions\\UnknownSetterException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php',
        'Carbon\\Exceptions\\UnknownUnitException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php',
        'Carbon\\Exceptions\\UnreachableException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php',
        'Carbon\\Exceptions\\UnsupportedUnitException' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Exceptions/UnsupportedUnitException.php',
        'Carbon\\Factory' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Factory.php',
        'Carbon\\FactoryImmutable' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/FactoryImmutable.php',
        'Carbon\\Language' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Language.php',
        'Carbon\\Laravel\\ServiceProvider' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php',
        'Carbon\\MessageFormatter\\MessageFormatterMapper' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/MessageFormatter/MessageFormatterMapper.php',
        'Carbon\\Month' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Month.php',
        'Carbon\\PHPStan\\MacroExtension' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php',
        'Carbon\\PHPStan\\MacroMethodReflection' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/PHPStan/MacroMethodReflection.php',
        'Carbon\\Traits\\Boundaries' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Boundaries.php',
        'Carbon\\Traits\\Cast' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Cast.php',
        'Carbon\\Traits\\Comparison' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Comparison.php',
        'Carbon\\Traits\\Converter' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Converter.php',
        'Carbon\\Traits\\Creator' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Creator.php',
        'Carbon\\Traits\\Date' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Date.php',
        'Carbon\\Traits\\DeprecatedPeriodProperties' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/DeprecatedPeriodProperties.php',
        'Carbon\\Traits\\Difference' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Difference.php',
        'Carbon\\Traits\\IntervalRounding' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php',
        'Carbon\\Traits\\IntervalStep' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/IntervalStep.php',
        'Carbon\\Traits\\LocalFactory' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/LocalFactory.php',
        'Carbon\\Traits\\Localization' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Localization.php',
        'Carbon\\Traits\\Macro' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Macro.php',
        'Carbon\\Traits\\MagicParameter' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/MagicParameter.php',
        'Carbon\\Traits\\Mixin' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Mixin.php',
        'Carbon\\Traits\\Modifiers' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Modifiers.php',
        'Carbon\\Traits\\Mutability' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Mutability.php',
        'Carbon\\Traits\\ObjectInitialisation' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php',
        'Carbon\\Traits\\Options' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Options.php',
        'Carbon\\Traits\\Rounding' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Rounding.php',
        'Carbon\\Traits\\Serialization' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Serialization.php',
        'Carbon\\Traits\\StaticLocalization' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/StaticLocalization.php',
        'Carbon\\Traits\\StaticOptions' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/StaticOptions.php',
        'Carbon\\Traits\\Test' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Test.php',
        'Carbon\\Traits\\Timestamp' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Timestamp.php',
        'Carbon\\Traits\\ToStringFormat' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/ToStringFormat.php',
        'Carbon\\Traits\\Units' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Units.php',
        'Carbon\\Traits\\Week' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Traits/Week.php',
        'Carbon\\Translator' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Translator.php',
        'Carbon\\TranslatorImmutable' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/TranslatorImmutable.php',
        'Carbon\\TranslatorStrongTypeInterface' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/TranslatorStrongTypeInterface.php',
        'Carbon\\Unit' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Unit.php',
        'Carbon\\WeekDay' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/WeekDay.php',
        'Carbon\\WrapperClock' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/WrapperClock.php',
        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
        'DateError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateError.php',
        'DateException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateException.php',
        'DateInvalidOperationException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php',
        'DateInvalidTimeZoneException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php',
        'DateMalformedIntervalStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php',
        'DateMalformedPeriodStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php',
        'DateMalformedStringException' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php',
        'DateObjectError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateObjectError.php',
        'DateRangeError' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
        'DelayedTargetValidation' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php',
        'Deprecated' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
        'Doctrine\\Inflector\\CachedWordInflector' => __DIR__ . '/..' . '/doctrine/inflector/src/CachedWordInflector.php',
        'Doctrine\\Inflector\\GenericLanguageInflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/GenericLanguageInflectorFactory.php',
        'Doctrine\\Inflector\\Inflector' => __DIR__ . '/..' . '/doctrine/inflector/src/Inflector.php',
        'Doctrine\\Inflector\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/InflectorFactory.php',
        'Doctrine\\Inflector\\Language' => __DIR__ . '/..' . '/doctrine/inflector/src/Language.php',
        'Doctrine\\Inflector\\LanguageInflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/LanguageInflectorFactory.php',
        'Doctrine\\Inflector\\NoopWordInflector' => __DIR__ . '/..' . '/doctrine/inflector/src/NoopWordInflector.php',
        'Doctrine\\Inflector\\Rules\\English\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/English/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\English\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/English/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\English\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/English/Rules.php',
        'Doctrine\\Inflector\\Rules\\English\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/English/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\Esperanto\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Esperanto/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\Esperanto\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Esperanto/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\Esperanto\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Esperanto/Rules.php',
        'Doctrine\\Inflector\\Rules\\Esperanto\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Esperanto/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\French\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/French/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\French\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/French/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\French\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/French/Rules.php',
        'Doctrine\\Inflector\\Rules\\French\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/French/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\Italian\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Italian/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\Italian\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Italian/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\Italian\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Italian/Rules.php',
        'Doctrine\\Inflector\\Rules\\Italian\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Italian/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/NorwegianBokmal/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/NorwegianBokmal/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/NorwegianBokmal/Rules.php',
        'Doctrine\\Inflector\\Rules\\NorwegianBokmal\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/NorwegianBokmal/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\Pattern' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Pattern.php',
        'Doctrine\\Inflector\\Rules\\Patterns' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Patterns.php',
        'Doctrine\\Inflector\\Rules\\Portuguese\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Portuguese/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\Portuguese\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Portuguese/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\Portuguese\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Portuguese/Rules.php',
        'Doctrine\\Inflector\\Rules\\Portuguese\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Portuguese/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\Ruleset' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Ruleset.php',
        'Doctrine\\Inflector\\Rules\\Spanish\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Spanish/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\Spanish\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Spanish/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\Spanish\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Spanish/Rules.php',
        'Doctrine\\Inflector\\Rules\\Spanish\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Spanish/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\Substitution' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Substitution.php',
        'Doctrine\\Inflector\\Rules\\Substitutions' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Substitutions.php',
        'Doctrine\\Inflector\\Rules\\Transformation' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Transformation.php',
        'Doctrine\\Inflector\\Rules\\Transformations' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Transformations.php',
        'Doctrine\\Inflector\\Rules\\Turkish\\Inflectible' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Turkish/Inflectible.php',
        'Doctrine\\Inflector\\Rules\\Turkish\\InflectorFactory' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Turkish/InflectorFactory.php',
        'Doctrine\\Inflector\\Rules\\Turkish\\Rules' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Turkish/Rules.php',
        'Doctrine\\Inflector\\Rules\\Turkish\\Uninflected' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Turkish/Uninflected.php',
        'Doctrine\\Inflector\\Rules\\Word' => __DIR__ . '/..' . '/doctrine/inflector/src/Rules/Word.php',
        'Doctrine\\Inflector\\RulesetInflector' => __DIR__ . '/..' . '/doctrine/inflector/src/RulesetInflector.php',
        'Doctrine\\Inflector\\WordInflector' => __DIR__ . '/..' . '/doctrine/inflector/src/WordInflector.php',
        'Filter\\FilterException' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterException.php',
        'Filter\\FilterFailedException' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterFailedException.php',
        'Illuminate\\Contracts\\Auth\\Access\\Authorizable' => __DIR__ . '/..' . '/illuminate/contracts/Auth/Access/Authorizable.php',
        'Illuminate\\Contracts\\Auth\\Access\\Gate' => __DIR__ . '/..' . '/illuminate/contracts/Auth/Access/Gate.php',
        'Illuminate\\Contracts\\Auth\\Authenticatable' => __DIR__ . '/..' . '/illuminate/contracts/Auth/Authenticatable.php',
        'Illuminate\\Contracts\\Auth\\CanResetPassword' => __DIR__ . '/..' . '/illuminate/contracts/Auth/CanResetPassword.php',
        'Illuminate\\Contracts\\Auth\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Auth/Factory.php',
        'Illuminate\\Contracts\\Auth\\Guard' => __DIR__ . '/..' . '/illuminate/contracts/Auth/Guard.php',
        'Illuminate\\Contracts\\Auth\\Middleware\\AuthenticatesRequests' => __DIR__ . '/..' . '/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.php',
        'Illuminate\\Contracts\\Auth\\MustVerifyEmail' => __DIR__ . '/..' . '/illuminate/contracts/Auth/MustVerifyEmail.php',
        'Illuminate\\Contracts\\Auth\\PasswordBroker' => __DIR__ . '/..' . '/illuminate/contracts/Auth/PasswordBroker.php',
        'Illuminate\\Contracts\\Auth\\PasswordBrokerFactory' => __DIR__ . '/..' . '/illuminate/contracts/Auth/PasswordBrokerFactory.php',
        'Illuminate\\Contracts\\Auth\\StatefulGuard' => __DIR__ . '/..' . '/illuminate/contracts/Auth/StatefulGuard.php',
        'Illuminate\\Contracts\\Auth\\SupportsBasicAuth' => __DIR__ . '/..' . '/illuminate/contracts/Auth/SupportsBasicAuth.php',
        'Illuminate\\Contracts\\Auth\\UserProvider' => __DIR__ . '/..' . '/illuminate/contracts/Auth/UserProvider.php',
        'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/Broadcaster.php',
        'Illuminate\\Contracts\\Broadcasting\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/Factory.php',
        'Illuminate\\Contracts\\Broadcasting\\HasBroadcastChannel' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/HasBroadcastChannel.php',
        'Illuminate\\Contracts\\Broadcasting\\ShouldBeUnique' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/ShouldBeUnique.php',
        'Illuminate\\Contracts\\Broadcasting\\ShouldBroadcast' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/ShouldBroadcast.php',
        'Illuminate\\Contracts\\Broadcasting\\ShouldBroadcastNow' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/ShouldBroadcastNow.php',
        'Illuminate\\Contracts\\Broadcasting\\ShouldRescue' => __DIR__ . '/..' . '/illuminate/contracts/Broadcasting/ShouldRescue.php',
        'Illuminate\\Contracts\\Bus\\Dispatcher' => __DIR__ . '/..' . '/illuminate/contracts/Bus/Dispatcher.php',
        'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => __DIR__ . '/..' . '/illuminate/contracts/Bus/QueueingDispatcher.php',
        'Illuminate\\Contracts\\Cache\\CanFlushLocks' => __DIR__ . '/..' . '/illuminate/contracts/Cache/CanFlushLocks.php',
        'Illuminate\\Contracts\\Cache\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Cache/Factory.php',
        'Illuminate\\Contracts\\Cache\\Lock' => __DIR__ . '/..' . '/illuminate/contracts/Cache/Lock.php',
        'Illuminate\\Contracts\\Cache\\LockProvider' => __DIR__ . '/..' . '/illuminate/contracts/Cache/LockProvider.php',
        'Illuminate\\Contracts\\Cache\\LockTimeoutException' => __DIR__ . '/..' . '/illuminate/contracts/Cache/LockTimeoutException.php',
        'Illuminate\\Contracts\\Cache\\Repository' => __DIR__ . '/..' . '/illuminate/contracts/Cache/Repository.php',
        'Illuminate\\Contracts\\Cache\\Store' => __DIR__ . '/..' . '/illuminate/contracts/Cache/Store.php',
        'Illuminate\\Contracts\\Concurrency\\Driver' => __DIR__ . '/..' . '/illuminate/contracts/Concurrency/Driver.php',
        'Illuminate\\Contracts\\Config\\Repository' => __DIR__ . '/..' . '/illuminate/contracts/Config/Repository.php',
        'Illuminate\\Contracts\\Console\\Application' => __DIR__ . '/..' . '/illuminate/contracts/Console/Application.php',
        'Illuminate\\Contracts\\Console\\Isolatable' => __DIR__ . '/..' . '/illuminate/contracts/Console/Isolatable.php',
        'Illuminate\\Contracts\\Console\\Kernel' => __DIR__ . '/..' . '/illuminate/contracts/Console/Kernel.php',
        'Illuminate\\Contracts\\Console\\PromptsForMissingInput' => __DIR__ . '/..' . '/illuminate/contracts/Console/PromptsForMissingInput.php',
        'Illuminate\\Contracts\\Container\\BindingResolutionException' => __DIR__ . '/..' . '/illuminate/contracts/Container/BindingResolutionException.php',
        'Illuminate\\Contracts\\Container\\CircularDependencyException' => __DIR__ . '/..' . '/illuminate/contracts/Container/CircularDependencyException.php',
        'Illuminate\\Contracts\\Container\\Container' => __DIR__ . '/..' . '/illuminate/contracts/Container/Container.php',
        'Illuminate\\Contracts\\Container\\ContextualAttribute' => __DIR__ . '/..' . '/illuminate/contracts/Container/ContextualAttribute.php',
        'Illuminate\\Contracts\\Container\\ContextualBindingBuilder' => __DIR__ . '/..' . '/illuminate/contracts/Container/ContextualBindingBuilder.php',
        'Illuminate\\Contracts\\Container\\SelfBuilding' => __DIR__ . '/..' . '/illuminate/contracts/Container/SelfBuilding.php',
        'Illuminate\\Contracts\\Cookie\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Cookie/Factory.php',
        'Illuminate\\Contracts\\Cookie\\QueueingFactory' => __DIR__ . '/..' . '/illuminate/contracts/Cookie/QueueingFactory.php',
        'Illuminate\\Contracts\\Database\\ConcurrencyErrorDetector' => __DIR__ . '/..' . '/illuminate/contracts/Database/ConcurrencyErrorDetector.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\Builder' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/Builder.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\Castable' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/Castable.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\CastsAttributes' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/CastsAttributes.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\CastsInboundAttributes' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\ComparesCastableAttributes' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/ComparesCastableAttributes.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\DeviatesCastableAttributes' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\SerializesCastableAttributes' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php',
        'Illuminate\\Contracts\\Database\\Eloquent\\SupportsPartialRelations' => __DIR__ . '/..' . '/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php',
        'Illuminate\\Contracts\\Database\\Events\\MigrationEvent' => __DIR__ . '/..' . '/illuminate/contracts/Database/Events/MigrationEvent.php',
        'Illuminate\\Contracts\\Database\\LostConnectionDetector' => __DIR__ . '/..' . '/illuminate/contracts/Database/LostConnectionDetector.php',
        'Illuminate\\Contracts\\Database\\ModelIdentifier' => __DIR__ . '/..' . '/illuminate/contracts/Database/ModelIdentifier.php',
        'Illuminate\\Contracts\\Database\\Query\\Builder' => __DIR__ . '/..' . '/illuminate/contracts/Database/Query/Builder.php',
        'Illuminate\\Contracts\\Database\\Query\\ConditionExpression' => __DIR__ . '/..' . '/illuminate/contracts/Database/Query/ConditionExpression.php',
        'Illuminate\\Contracts\\Database\\Query\\Expression' => __DIR__ . '/..' . '/illuminate/contracts/Database/Query/Expression.php',
        'Illuminate\\Contracts\\Debug\\ExceptionHandler' => __DIR__ . '/..' . '/illuminate/contracts/Debug/ExceptionHandler.php',
        'Illuminate\\Contracts\\Debug\\ShouldntReport' => __DIR__ . '/..' . '/illuminate/contracts/Debug/ShouldntReport.php',
        'Illuminate\\Contracts\\Encryption\\DecryptException' => __DIR__ . '/..' . '/illuminate/contracts/Encryption/DecryptException.php',
        'Illuminate\\Contracts\\Encryption\\EncryptException' => __DIR__ . '/..' . '/illuminate/contracts/Encryption/EncryptException.php',
        'Illuminate\\Contracts\\Encryption\\Encrypter' => __DIR__ . '/..' . '/illuminate/contracts/Encryption/Encrypter.php',
        'Illuminate\\Contracts\\Encryption\\StringEncrypter' => __DIR__ . '/..' . '/illuminate/contracts/Encryption/StringEncrypter.php',
        'Illuminate\\Contracts\\Events\\Dispatcher' => __DIR__ . '/..' . '/illuminate/contracts/Events/Dispatcher.php',
        'Illuminate\\Contracts\\Events\\ShouldDispatchAfterCommit' => __DIR__ . '/..' . '/illuminate/contracts/Events/ShouldDispatchAfterCommit.php',
        'Illuminate\\Contracts\\Events\\ShouldHandleEventsAfterCommit' => __DIR__ . '/..' . '/illuminate/contracts/Events/ShouldHandleEventsAfterCommit.php',
        'Illuminate\\Contracts\\Filesystem\\Cloud' => __DIR__ . '/..' . '/illuminate/contracts/Filesystem/Cloud.php',
        'Illuminate\\Contracts\\Filesystem\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Filesystem/Factory.php',
        'Illuminate\\Contracts\\Filesystem\\FileNotFoundException' => __DIR__ . '/..' . '/illuminate/contracts/Filesystem/FileNotFoundException.php',
        'Illuminate\\Contracts\\Filesystem\\Filesystem' => __DIR__ . '/..' . '/illuminate/contracts/Filesystem/Filesystem.php',
        'Illuminate\\Contracts\\Filesystem\\LockTimeoutException' => __DIR__ . '/..' . '/illuminate/contracts/Filesystem/LockTimeoutException.php',
        'Illuminate\\Contracts\\Foundation\\Application' => __DIR__ . '/..' . '/illuminate/contracts/Foundation/Application.php',
        'Illuminate\\Contracts\\Foundation\\CachesConfiguration' => __DIR__ . '/..' . '/illuminate/contracts/Foundation/CachesConfiguration.php',
        'Illuminate\\Contracts\\Foundation\\CachesRoutes' => __DIR__ . '/..' . '/illuminate/contracts/Foundation/CachesRoutes.php',
        'Illuminate\\Contracts\\Foundation\\ExceptionRenderer' => __DIR__ . '/..' . '/illuminate/contracts/Foundation/ExceptionRenderer.php',
        'Illuminate\\Contracts\\Foundation\\MaintenanceMode' => __DIR__ . '/..' . '/illuminate/contracts/Foundation/MaintenanceMode.php',
        'Illuminate\\Contracts\\Hashing\\Hasher' => __DIR__ . '/..' . '/illuminate/contracts/Hashing/Hasher.php',
        'Illuminate\\Contracts\\Http\\Kernel' => __DIR__ . '/..' . '/illuminate/contracts/Http/Kernel.php',
        'Illuminate\\Contracts\\JsonSchema\\JsonSchema' => __DIR__ . '/..' . '/illuminate/contracts/JsonSchema/JsonSchema.php',
        'Illuminate\\Contracts\\Log\\ContextLogProcessor' => __DIR__ . '/..' . '/illuminate/contracts/Log/ContextLogProcessor.php',
        'Illuminate\\Contracts\\Mail\\Attachable' => __DIR__ . '/..' . '/illuminate/contracts/Mail/Attachable.php',
        'Illuminate\\Contracts\\Mail\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Mail/Factory.php',
        'Illuminate\\Contracts\\Mail\\MailQueue' => __DIR__ . '/..' . '/illuminate/contracts/Mail/MailQueue.php',
        'Illuminate\\Contracts\\Mail\\Mailable' => __DIR__ . '/..' . '/illuminate/contracts/Mail/Mailable.php',
        'Illuminate\\Contracts\\Mail\\Mailer' => __DIR__ . '/..' . '/illuminate/contracts/Mail/Mailer.php',
        'Illuminate\\Contracts\\Notifications\\Dispatcher' => __DIR__ . '/..' . '/illuminate/contracts/Notifications/Dispatcher.php',
        'Illuminate\\Contracts\\Notifications\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Notifications/Factory.php',
        'Illuminate\\Contracts\\Pagination\\CursorPaginator' => __DIR__ . '/..' . '/illuminate/contracts/Pagination/CursorPaginator.php',
        'Illuminate\\Contracts\\Pagination\\LengthAwarePaginator' => __DIR__ . '/..' . '/illuminate/contracts/Pagination/LengthAwarePaginator.php',
        'Illuminate\\Contracts\\Pagination\\Paginator' => __DIR__ . '/..' . '/illuminate/contracts/Pagination/Paginator.php',
        'Illuminate\\Contracts\\Pipeline\\Hub' => __DIR__ . '/..' . '/illuminate/contracts/Pipeline/Hub.php',
        'Illuminate\\Contracts\\Pipeline\\Pipeline' => __DIR__ . '/..' . '/illuminate/contracts/Pipeline/Pipeline.php',
        'Illuminate\\Contracts\\Process\\InvokedProcess' => __DIR__ . '/..' . '/illuminate/contracts/Process/InvokedProcess.php',
        'Illuminate\\Contracts\\Process\\ProcessResult' => __DIR__ . '/..' . '/illuminate/contracts/Process/ProcessResult.php',
        'Illuminate\\Contracts\\Queue\\ClearableQueue' => __DIR__ . '/..' . '/illuminate/contracts/Queue/ClearableQueue.php',
        'Illuminate\\Contracts\\Queue\\EntityNotFoundException' => __DIR__ . '/..' . '/illuminate/contracts/Queue/EntityNotFoundException.php',
        'Illuminate\\Contracts\\Queue\\EntityResolver' => __DIR__ . '/..' . '/illuminate/contracts/Queue/EntityResolver.php',
        'Illuminate\\Contracts\\Queue\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Queue/Factory.php',
        'Illuminate\\Contracts\\Queue\\Interruptible' => __DIR__ . '/..' . '/illuminate/contracts/Queue/Interruptible.php',
        'Illuminate\\Contracts\\Queue\\Job' => __DIR__ . '/..' . '/illuminate/contracts/Queue/Job.php',
        'Illuminate\\Contracts\\Queue\\Monitor' => __DIR__ . '/..' . '/illuminate/contracts/Queue/Monitor.php',
        'Illuminate\\Contracts\\Queue\\PreparesForDispatch' => __DIR__ . '/..' . '/illuminate/contracts/Queue/PreparesForDispatch.php',
        'Illuminate\\Contracts\\Queue\\Queue' => __DIR__ . '/..' . '/illuminate/contracts/Queue/Queue.php',
        'Illuminate\\Contracts\\Queue\\QueueableCollection' => __DIR__ . '/..' . '/illuminate/contracts/Queue/QueueableCollection.php',
        'Illuminate\\Contracts\\Queue\\QueueableEntity' => __DIR__ . '/..' . '/illuminate/contracts/Queue/QueueableEntity.php',
        'Illuminate\\Contracts\\Queue\\ShouldBeEncrypted' => __DIR__ . '/..' . '/illuminate/contracts/Queue/ShouldBeEncrypted.php',
        'Illuminate\\Contracts\\Queue\\ShouldBeUnique' => __DIR__ . '/..' . '/illuminate/contracts/Queue/ShouldBeUnique.php',
        'Illuminate\\Contracts\\Queue\\ShouldBeUniqueUntilProcessing' => __DIR__ . '/..' . '/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.php',
        'Illuminate\\Contracts\\Queue\\ShouldQueue' => __DIR__ . '/..' . '/illuminate/contracts/Queue/ShouldQueue.php',
        'Illuminate\\Contracts\\Queue\\ShouldQueueAfterCommit' => __DIR__ . '/..' . '/illuminate/contracts/Queue/ShouldQueueAfterCommit.php',
        'Illuminate\\Contracts\\Redis\\Connection' => __DIR__ . '/..' . '/illuminate/contracts/Redis/Connection.php',
        'Illuminate\\Contracts\\Redis\\Connector' => __DIR__ . '/..' . '/illuminate/contracts/Redis/Connector.php',
        'Illuminate\\Contracts\\Redis\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Redis/Factory.php',
        'Illuminate\\Contracts\\Redis\\LimiterTimeoutException' => __DIR__ . '/..' . '/illuminate/contracts/Redis/LimiterTimeoutException.php',
        'Illuminate\\Contracts\\Routing\\BindingRegistrar' => __DIR__ . '/..' . '/illuminate/contracts/Routing/BindingRegistrar.php',
        'Illuminate\\Contracts\\Routing\\Registrar' => __DIR__ . '/..' . '/illuminate/contracts/Routing/Registrar.php',
        'Illuminate\\Contracts\\Routing\\ResponseFactory' => __DIR__ . '/..' . '/illuminate/contracts/Routing/ResponseFactory.php',
        'Illuminate\\Contracts\\Routing\\UrlGenerator' => __DIR__ . '/..' . '/illuminate/contracts/Routing/UrlGenerator.php',
        'Illuminate\\Contracts\\Routing\\UrlRoutable' => __DIR__ . '/..' . '/illuminate/contracts/Routing/UrlRoutable.php',
        'Illuminate\\Contracts\\Session\\Middleware\\AuthenticatesSessions' => __DIR__ . '/..' . '/illuminate/contracts/Session/Middleware/AuthenticatesSessions.php',
        'Illuminate\\Contracts\\Session\\Session' => __DIR__ . '/..' . '/illuminate/contracts/Session/Session.php',
        'Illuminate\\Contracts\\Support\\Arrayable' => __DIR__ . '/..' . '/illuminate/contracts/Support/Arrayable.php',
        'Illuminate\\Contracts\\Support\\CanBeEscapedWhenCastToString' => __DIR__ . '/..' . '/illuminate/contracts/Support/CanBeEscapedWhenCastToString.php',
        'Illuminate\\Contracts\\Support\\DeferrableProvider' => __DIR__ . '/..' . '/illuminate/contracts/Support/DeferrableProvider.php',
        'Illuminate\\Contracts\\Support\\DeferringDisplayableValue' => __DIR__ . '/..' . '/illuminate/contracts/Support/DeferringDisplayableValue.php',
        'Illuminate\\Contracts\\Support\\HasOnceHash' => __DIR__ . '/..' . '/illuminate/contracts/Support/HasOnceHash.php',
        'Illuminate\\Contracts\\Support\\Htmlable' => __DIR__ . '/..' . '/illuminate/contracts/Support/Htmlable.php',
        'Illuminate\\Contracts\\Support\\Jsonable' => __DIR__ . '/..' . '/illuminate/contracts/Support/Jsonable.php',
        'Illuminate\\Contracts\\Support\\MessageBag' => __DIR__ . '/..' . '/illuminate/contracts/Support/MessageBag.php',
        'Illuminate\\Contracts\\Support\\MessageProvider' => __DIR__ . '/..' . '/illuminate/contracts/Support/MessageProvider.php',
        'Illuminate\\Contracts\\Support\\Renderable' => __DIR__ . '/..' . '/illuminate/contracts/Support/Renderable.php',
        'Illuminate\\Contracts\\Support\\Responsable' => __DIR__ . '/..' . '/illuminate/contracts/Support/Responsable.php',
        'Illuminate\\Contracts\\Support\\ValidatedData' => __DIR__ . '/..' . '/illuminate/contracts/Support/ValidatedData.php',
        'Illuminate\\Contracts\\Translation\\HasLocalePreference' => __DIR__ . '/..' . '/illuminate/contracts/Translation/HasLocalePreference.php',
        'Illuminate\\Contracts\\Translation\\Loader' => __DIR__ . '/..' . '/illuminate/contracts/Translation/Loader.php',
        'Illuminate\\Contracts\\Translation\\Translator' => __DIR__ . '/..' . '/illuminate/contracts/Translation/Translator.php',
        'Illuminate\\Contracts\\Validation\\CompilableRules' => __DIR__ . '/..' . '/illuminate/contracts/Validation/CompilableRules.php',
        'Illuminate\\Contracts\\Validation\\DataAwareRule' => __DIR__ . '/..' . '/illuminate/contracts/Validation/DataAwareRule.php',
        'Illuminate\\Contracts\\Validation\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/Validation/Factory.php',
        'Illuminate\\Contracts\\Validation\\ImplicitRule' => __DIR__ . '/..' . '/illuminate/contracts/Validation/ImplicitRule.php',
        'Illuminate\\Contracts\\Validation\\InvokableRule' => __DIR__ . '/..' . '/illuminate/contracts/Validation/InvokableRule.php',
        'Illuminate\\Contracts\\Validation\\Rule' => __DIR__ . '/..' . '/illuminate/contracts/Validation/Rule.php',
        'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => __DIR__ . '/..' . '/illuminate/contracts/Validation/UncompromisedVerifier.php',
        'Illuminate\\Contracts\\Validation\\ValidatesWhenResolved' => __DIR__ . '/..' . '/illuminate/contracts/Validation/ValidatesWhenResolved.php',
        'Illuminate\\Contracts\\Validation\\ValidationRule' => __DIR__ . '/..' . '/illuminate/contracts/Validation/ValidationRule.php',
        'Illuminate\\Contracts\\Validation\\Validator' => __DIR__ . '/..' . '/illuminate/contracts/Validation/Validator.php',
        'Illuminate\\Contracts\\Validation\\ValidatorAwareRule' => __DIR__ . '/..' . '/illuminate/contracts/Validation/ValidatorAwareRule.php',
        'Illuminate\\Contracts\\View\\Engine' => __DIR__ . '/..' . '/illuminate/contracts/View/Engine.php',
        'Illuminate\\Contracts\\View\\Factory' => __DIR__ . '/..' . '/illuminate/contracts/View/Factory.php',
        'Illuminate\\Contracts\\View\\View' => __DIR__ . '/..' . '/illuminate/contracts/View/View.php',
        'Illuminate\\Contracts\\View\\ViewCompilationException' => __DIR__ . '/..' . '/illuminate/contracts/View/ViewCompilationException.php',
        'Illuminate\\Filesystem\\AwsS3V3Adapter' => __DIR__ . '/..' . '/illuminate/filesystem/AwsS3V3Adapter.php',
        'Illuminate\\Filesystem\\Filesystem' => __DIR__ . '/..' . '/illuminate/filesystem/Filesystem.php',
        'Illuminate\\Filesystem\\FilesystemAdapter' => __DIR__ . '/..' . '/illuminate/filesystem/FilesystemAdapter.php',
        'Illuminate\\Filesystem\\FilesystemManager' => __DIR__ . '/..' . '/illuminate/filesystem/FilesystemManager.php',
        'Illuminate\\Filesystem\\FilesystemServiceProvider' => __DIR__ . '/..' . '/illuminate/filesystem/FilesystemServiceProvider.php',
        'Illuminate\\Filesystem\\LocalFilesystemAdapter' => __DIR__ . '/..' . '/illuminate/filesystem/LocalFilesystemAdapter.php',
        'Illuminate\\Filesystem\\LockableFile' => __DIR__ . '/..' . '/illuminate/filesystem/LockableFile.php',
        'Illuminate\\Filesystem\\ReceiveFile' => __DIR__ . '/..' . '/illuminate/filesystem/ReceiveFile.php',
        'Illuminate\\Filesystem\\ServeFile' => __DIR__ . '/..' . '/illuminate/filesystem/ServeFile.php',
        'Illuminate\\Support\\AggregateServiceProvider' => __DIR__ . '/..' . '/illuminate/support/AggregateServiceProvider.php',
        'Illuminate\\Support\\Arr' => __DIR__ . '/..' . '/illuminate/collections/Arr.php',
        'Illuminate\\Support\\Benchmark' => __DIR__ . '/..' . '/illuminate/support/Benchmark.php',
        'Illuminate\\Support\\BinaryCodec' => __DIR__ . '/..' . '/illuminate/support/BinaryCodec.php',
        'Illuminate\\Support\\Carbon' => __DIR__ . '/..' . '/illuminate/support/Carbon.php',
        'Illuminate\\Support\\Collection' => __DIR__ . '/..' . '/illuminate/collections/Collection.php',
        'Illuminate\\Support\\Composer' => __DIR__ . '/..' . '/illuminate/support/Composer.php',
        'Illuminate\\Support\\ConfigurationUrlParser' => __DIR__ . '/..' . '/illuminate/support/ConfigurationUrlParser.php',
        'Illuminate\\Support\\DateFactory' => __DIR__ . '/..' . '/illuminate/support/DateFactory.php',
        'Illuminate\\Support\\DefaultProviders' => __DIR__ . '/..' . '/illuminate/support/DefaultProviders.php',
        'Illuminate\\Support\\Defer\\DeferredCallback' => __DIR__ . '/..' . '/illuminate/support/Defer/DeferredCallback.php',
        'Illuminate\\Support\\Defer\\DeferredCallbackCollection' => __DIR__ . '/..' . '/illuminate/support/Defer/DeferredCallbackCollection.php',
        'Illuminate\\Support\\EncodedHtmlString' => __DIR__ . '/..' . '/illuminate/support/EncodedHtmlString.php',
        'Illuminate\\Support\\Enumerable' => __DIR__ . '/..' . '/illuminate/collections/Enumerable.php',
        'Illuminate\\Support\\Env' => __DIR__ . '/..' . '/illuminate/support/Env.php',
        'Illuminate\\Support\\Exceptions\\MathException' => __DIR__ . '/..' . '/illuminate/support/Exceptions/MathException.php',
        'Illuminate\\Support\\Facades\\App' => __DIR__ . '/..' . '/illuminate/support/Facades/App.php',
        'Illuminate\\Support\\Facades\\Artisan' => __DIR__ . '/..' . '/illuminate/support/Facades/Artisan.php',
        'Illuminate\\Support\\Facades\\Auth' => __DIR__ . '/..' . '/illuminate/support/Facades/Auth.php',
        'Illuminate\\Support\\Facades\\Blade' => __DIR__ . '/..' . '/illuminate/support/Facades/Blade.php',
        'Illuminate\\Support\\Facades\\Broadcast' => __DIR__ . '/..' . '/illuminate/support/Facades/Broadcast.php',
        'Illuminate\\Support\\Facades\\Bus' => __DIR__ . '/..' . '/illuminate/support/Facades/Bus.php',
        'Illuminate\\Support\\Facades\\Cache' => __DIR__ . '/..' . '/illuminate/support/Facades/Cache.php',
        'Illuminate\\Support\\Facades\\Concurrency' => __DIR__ . '/..' . '/illuminate/support/Facades/Concurrency.php',
        'Illuminate\\Support\\Facades\\Config' => __DIR__ . '/..' . '/illuminate/support/Facades/Config.php',
        'Illuminate\\Support\\Facades\\Context' => __DIR__ . '/..' . '/illuminate/support/Facades/Context.php',
        'Illuminate\\Support\\Facades\\Cookie' => __DIR__ . '/..' . '/illuminate/support/Facades/Cookie.php',
        'Illuminate\\Support\\Facades\\Crypt' => __DIR__ . '/..' . '/illuminate/support/Facades/Crypt.php',
        'Illuminate\\Support\\Facades\\DB' => __DIR__ . '/..' . '/illuminate/support/Facades/DB.php',
        'Illuminate\\Support\\Facades\\Date' => __DIR__ . '/..' . '/illuminate/support/Facades/Date.php',
        'Illuminate\\Support\\Facades\\Event' => __DIR__ . '/..' . '/illuminate/support/Facades/Event.php',
        'Illuminate\\Support\\Facades\\Exceptions' => __DIR__ . '/..' . '/illuminate/support/Facades/Exceptions.php',
        'Illuminate\\Support\\Facades\\Facade' => __DIR__ . '/..' . '/illuminate/support/Facades/Facade.php',
        'Illuminate\\Support\\Facades\\File' => __DIR__ . '/..' . '/illuminate/support/Facades/File.php',
        'Illuminate\\Support\\Facades\\Gate' => __DIR__ . '/..' . '/illuminate/support/Facades/Gate.php',
        'Illuminate\\Support\\Facades\\Hash' => __DIR__ . '/..' . '/illuminate/support/Facades/Hash.php',
        'Illuminate\\Support\\Facades\\Http' => __DIR__ . '/..' . '/illuminate/support/Facades/Http.php',
        'Illuminate\\Support\\Facades\\Lang' => __DIR__ . '/..' . '/illuminate/support/Facades/Lang.php',
        'Illuminate\\Support\\Facades\\Log' => __DIR__ . '/..' . '/illuminate/support/Facades/Log.php',
        'Illuminate\\Support\\Facades\\Mail' => __DIR__ . '/..' . '/illuminate/support/Facades/Mail.php',
        'Illuminate\\Support\\Facades\\MaintenanceMode' => __DIR__ . '/..' . '/illuminate/support/Facades/MaintenanceMode.php',
        'Illuminate\\Support\\Facades\\Notification' => __DIR__ . '/..' . '/illuminate/support/Facades/Notification.php',
        'Illuminate\\Support\\Facades\\ParallelTesting' => __DIR__ . '/..' . '/illuminate/support/Facades/ParallelTesting.php',
        'Illuminate\\Support\\Facades\\Password' => __DIR__ . '/..' . '/illuminate/support/Facades/Password.php',
        'Illuminate\\Support\\Facades\\Pipeline' => __DIR__ . '/..' . '/illuminate/support/Facades/Pipeline.php',
        'Illuminate\\Support\\Facades\\Process' => __DIR__ . '/..' . '/illuminate/support/Facades/Process.php',
        'Illuminate\\Support\\Facades\\Queue' => __DIR__ . '/..' . '/illuminate/support/Facades/Queue.php',
        'Illuminate\\Support\\Facades\\RateLimiter' => __DIR__ . '/..' . '/illuminate/support/Facades/RateLimiter.php',
        'Illuminate\\Support\\Facades\\Redirect' => __DIR__ . '/..' . '/illuminate/support/Facades/Redirect.php',
        'Illuminate\\Support\\Facades\\Redis' => __DIR__ . '/..' . '/illuminate/support/Facades/Redis.php',
        'Illuminate\\Support\\Facades\\Request' => __DIR__ . '/..' . '/illuminate/support/Facades/Request.php',
        'Illuminate\\Support\\Facades\\Response' => __DIR__ . '/..' . '/illuminate/support/Facades/Response.php',
        'Illuminate\\Support\\Facades\\Route' => __DIR__ . '/..' . '/illuminate/support/Facades/Route.php',
        'Illuminate\\Support\\Facades\\Schedule' => __DIR__ . '/..' . '/illuminate/support/Facades/Schedule.php',
        'Illuminate\\Support\\Facades\\Schema' => __DIR__ . '/..' . '/illuminate/support/Facades/Schema.php',
        'Illuminate\\Support\\Facades\\Session' => __DIR__ . '/..' . '/illuminate/support/Facades/Session.php',
        'Illuminate\\Support\\Facades\\Storage' => __DIR__ . '/..' . '/illuminate/support/Facades/Storage.php',
        'Illuminate\\Support\\Facades\\URL' => __DIR__ . '/..' . '/illuminate/support/Facades/URL.php',
        'Illuminate\\Support\\Facades\\Validator' => __DIR__ . '/..' . '/illuminate/support/Facades/Validator.php',
        'Illuminate\\Support\\Facades\\View' => __DIR__ . '/..' . '/illuminate/support/Facades/View.php',
        'Illuminate\\Support\\Facades\\Vite' => __DIR__ . '/..' . '/illuminate/support/Facades/Vite.php',
        'Illuminate\\Support\\Fluent' => __DIR__ . '/..' . '/illuminate/support/Fluent.php',
        'Illuminate\\Support\\HigherOrderCollectionProxy' => __DIR__ . '/..' . '/illuminate/collections/HigherOrderCollectionProxy.php',
        'Illuminate\\Support\\HigherOrderTapProxy' => __DIR__ . '/..' . '/illuminate/support/HigherOrderTapProxy.php',
        'Illuminate\\Support\\HigherOrderWhenProxy' => __DIR__ . '/..' . '/illuminate/conditionable/HigherOrderWhenProxy.php',
        'Illuminate\\Support\\HtmlString' => __DIR__ . '/..' . '/illuminate/support/HtmlString.php',
        'Illuminate\\Support\\InteractsWithTime' => __DIR__ . '/..' . '/illuminate/support/InteractsWithTime.php',
        'Illuminate\\Support\\ItemNotFoundException' => __DIR__ . '/..' . '/illuminate/collections/ItemNotFoundException.php',
        'Illuminate\\Support\\Js' => __DIR__ . '/..' . '/illuminate/support/Js.php',
        'Illuminate\\Support\\LazyCollection' => __DIR__ . '/..' . '/illuminate/collections/LazyCollection.php',
        'Illuminate\\Support\\Lottery' => __DIR__ . '/..' . '/illuminate/support/Lottery.php',
        'Illuminate\\Support\\Manager' => __DIR__ . '/..' . '/illuminate/support/Manager.php',
        'Illuminate\\Support\\MessageBag' => __DIR__ . '/..' . '/illuminate/support/MessageBag.php',
        'Illuminate\\Support\\MultipleInstanceManager' => __DIR__ . '/..' . '/illuminate/support/MultipleInstanceManager.php',
        'Illuminate\\Support\\MultipleItemsFoundException' => __DIR__ . '/..' . '/illuminate/collections/MultipleItemsFoundException.php',
        'Illuminate\\Support\\NamespacedItemResolver' => __DIR__ . '/..' . '/illuminate/support/NamespacedItemResolver.php',
        'Illuminate\\Support\\Number' => __DIR__ . '/..' . '/illuminate/support/Number.php',
        'Illuminate\\Support\\Once' => __DIR__ . '/..' . '/illuminate/support/Once.php',
        'Illuminate\\Support\\Onceable' => __DIR__ . '/..' . '/illuminate/support/Onceable.php',
        'Illuminate\\Support\\Optional' => __DIR__ . '/..' . '/illuminate/support/Optional.php',
        'Illuminate\\Support\\Pluralizer' => __DIR__ . '/..' . '/illuminate/support/Pluralizer.php',
        'Illuminate\\Support\\ProcessUtils' => __DIR__ . '/..' . '/illuminate/support/ProcessUtils.php',
        'Illuminate\\Support\\Queue\\Concerns\\ResolvesQueueRoutes' => __DIR__ . '/..' . '/illuminate/support/Queue/Concerns/ResolvesQueueRoutes.php',
        'Illuminate\\Support\\RebindsCallbacksToSelf' => __DIR__ . '/..' . '/illuminate/support/RebindsCallbacksToSelf.php',
        'Illuminate\\Support\\Reflector' => __DIR__ . '/..' . '/illuminate/reflection/Reflector.php',
        'Illuminate\\Support\\ServiceProvider' => __DIR__ . '/..' . '/illuminate/support/ServiceProvider.php',
        'Illuminate\\Support\\Sleep' => __DIR__ . '/..' . '/illuminate/support/Sleep.php',
        'Illuminate\\Support\\Str' => __DIR__ . '/..' . '/illuminate/support/Str.php',
        'Illuminate\\Support\\Stringable' => __DIR__ . '/..' . '/illuminate/support/Stringable.php',
        'Illuminate\\Support\\Testing\\Fakes\\BatchFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/BatchFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\BatchRepositoryFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/BatchRepositoryFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\BusFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/BusFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\ChainedBatchTruthTest' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/ChainedBatchTruthTest.php',
        'Illuminate\\Support\\Testing\\Fakes\\EventFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/EventFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\ExceptionHandlerFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/ExceptionHandlerFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\Fake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/Fake.php',
        'Illuminate\\Support\\Testing\\Fakes\\MailFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/MailFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\NotificationFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/NotificationFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\PendingBatchFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/PendingBatchFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\PendingChainFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/PendingChainFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\PendingMailFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/PendingMailFake.php',
        'Illuminate\\Support\\Testing\\Fakes\\QueueFake' => __DIR__ . '/..' . '/illuminate/support/Testing/Fakes/QueueFake.php',
        'Illuminate\\Support\\Timebox' => __DIR__ . '/..' . '/illuminate/support/Timebox.php',
        'Illuminate\\Support\\Traits\\CapsuleManagerTrait' => __DIR__ . '/..' . '/illuminate/support/Traits/CapsuleManagerTrait.php',
        'Illuminate\\Support\\Traits\\Conditionable' => __DIR__ . '/..' . '/illuminate/conditionable/Traits/Conditionable.php',
        'Illuminate\\Support\\Traits\\Dumpable' => __DIR__ . '/..' . '/illuminate/support/Traits/Dumpable.php',
        'Illuminate\\Support\\Traits\\EnumeratesValues' => __DIR__ . '/..' . '/illuminate/collections/Traits/EnumeratesValues.php',
        'Illuminate\\Support\\Traits\\ForwardsCalls' => __DIR__ . '/..' . '/illuminate/support/Traits/ForwardsCalls.php',
        'Illuminate\\Support\\Traits\\InteractsWithData' => __DIR__ . '/..' . '/illuminate/support/Traits/InteractsWithData.php',
        'Illuminate\\Support\\Traits\\Localizable' => __DIR__ . '/..' . '/illuminate/support/Traits/Localizable.php',
        'Illuminate\\Support\\Traits\\Macroable' => __DIR__ . '/..' . '/illuminate/macroable/Traits/Macroable.php',
        'Illuminate\\Support\\Traits\\ReadsClassAttributes' => __DIR__ . '/..' . '/illuminate/support/Traits/ReadsClassAttributes.php',
        'Illuminate\\Support\\Traits\\ReflectsClosures' => __DIR__ . '/..' . '/illuminate/reflection/Traits/ReflectsClosures.php',
        'Illuminate\\Support\\Traits\\Tappable' => __DIR__ . '/..' . '/illuminate/support/Traits/Tappable.php',
        'Illuminate\\Support\\Traits\\TransformsToResourceCollection' => __DIR__ . '/..' . '/illuminate/collections/Traits/TransformsToResourceCollection.php',
        'Illuminate\\Support\\Uri' => __DIR__ . '/..' . '/illuminate/support/Uri.php',
        'Illuminate\\Support\\UriQueryString' => __DIR__ . '/..' . '/illuminate/support/UriQueryString.php',
        'Illuminate\\Support\\ValidatedInput' => __DIR__ . '/..' . '/illuminate/support/ValidatedInput.php',
        'Illuminate\\Support\\ViewErrorBag' => __DIR__ . '/..' . '/illuminate/support/ViewErrorBag.php',
        'Laravel\\AgentDetector\\AgentDetector' => __DIR__ . '/..' . '/laravel/agent-detector/src/AgentDetector.php',
        'Laravel\\AgentDetector\\AgentResult' => __DIR__ . '/..' . '/laravel/agent-detector/src/AgentResult.php',
        'Laravel\\AgentDetector\\KnownAgent' => __DIR__ . '/..' . '/laravel/agent-detector/src/KnownAgent.php',
        'Laravel\\Installer\\Console\\Agent' => __DIR__ . '/../..' . '/src/Agent.php',
        'Laravel\\Installer\\Console\\Concerns\\ConfiguresPrompts' => __DIR__ . '/../..' . '/src/Concerns/ConfiguresPrompts.php',
        'Laravel\\Installer\\Console\\Concerns\\InteractsWithHerdOrValet' => __DIR__ . '/../..' . '/src/Concerns/InteractsWithHerdOrValet.php',
        'Laravel\\Installer\\Console\\Enums\\NodePackageManager' => __DIR__ . '/../..' . '/src/Enums/NodePackageManager.php',
        'Laravel\\Installer\\Console\\NewCommand' => __DIR__ . '/../..' . '/src/NewCommand.php',
        'Laravel\\Prompts\\AutoCompletePrompt' => __DIR__ . '/..' . '/laravel/prompts/src/AutoCompletePrompt.php',
        'Laravel\\Prompts\\Clear' => __DIR__ . '/..' . '/laravel/prompts/src/Clear.php',
        'Laravel\\Prompts\\Concerns\\Colors' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Colors.php',
        'Laravel\\Prompts\\Concerns\\Cursor' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Cursor.php',
        'Laravel\\Prompts\\Concerns\\Erase' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Erase.php',
        'Laravel\\Prompts\\Concerns\\Events' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Events.php',
        'Laravel\\Prompts\\Concerns\\FakesInputOutput' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/FakesInputOutput.php',
        'Laravel\\Prompts\\Concerns\\Fallback' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Fallback.php',
        'Laravel\\Prompts\\Concerns\\HasInfo' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/HasInfo.php',
        'Laravel\\Prompts\\Concerns\\HasSpinner' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/HasSpinner.php',
        'Laravel\\Prompts\\Concerns\\Interactivity' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Interactivity.php',
        'Laravel\\Prompts\\Concerns\\Scrolling' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Scrolling.php',
        'Laravel\\Prompts\\Concerns\\Termwind' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Termwind.php',
        'Laravel\\Prompts\\Concerns\\Themes' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Themes.php',
        'Laravel\\Prompts\\Concerns\\Truncation' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/Truncation.php',
        'Laravel\\Prompts\\Concerns\\TypedValue' => __DIR__ . '/..' . '/laravel/prompts/src/Concerns/TypedValue.php',
        'Laravel\\Prompts\\ConfirmPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/ConfirmPrompt.php',
        'Laravel\\Prompts\\DataTablePrompt' => __DIR__ . '/..' . '/laravel/prompts/src/DataTablePrompt.php',
        'Laravel\\Prompts\\Exceptions\\FormRevertedException' => __DIR__ . '/..' . '/laravel/prompts/src/Exceptions/FormRevertedException.php',
        'Laravel\\Prompts\\Exceptions\\NonInteractiveValidationException' => __DIR__ . '/..' . '/laravel/prompts/src/Exceptions/NonInteractiveValidationException.php',
        'Laravel\\Prompts\\FormBuilder' => __DIR__ . '/..' . '/laravel/prompts/src/FormBuilder.php',
        'Laravel\\Prompts\\FormStep' => __DIR__ . '/..' . '/laravel/prompts/src/FormStep.php',
        'Laravel\\Prompts\\Grid' => __DIR__ . '/..' . '/laravel/prompts/src/Grid.php',
        'Laravel\\Prompts\\Key' => __DIR__ . '/..' . '/laravel/prompts/src/Key.php',
        'Laravel\\Prompts\\MultiSearchPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/MultiSearchPrompt.php',
        'Laravel\\Prompts\\MultiSelectPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/MultiSelectPrompt.php',
        'Laravel\\Prompts\\Note' => __DIR__ . '/..' . '/laravel/prompts/src/Note.php',
        'Laravel\\Prompts\\NotifyPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/NotifyPrompt.php',
        'Laravel\\Prompts\\NumberPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/NumberPrompt.php',
        'Laravel\\Prompts\\Output\\BufferedConsoleOutput' => __DIR__ . '/..' . '/laravel/prompts/src/Output/BufferedConsoleOutput.php',
        'Laravel\\Prompts\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/laravel/prompts/src/Output/ConsoleOutput.php',
        'Laravel\\Prompts\\PasswordPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/PasswordPrompt.php',
        'Laravel\\Prompts\\PausePrompt' => __DIR__ . '/..' . '/laravel/prompts/src/PausePrompt.php',
        'Laravel\\Prompts\\Progress' => __DIR__ . '/..' . '/laravel/prompts/src/Progress.php',
        'Laravel\\Prompts\\Prompt' => __DIR__ . '/..' . '/laravel/prompts/src/Prompt.php',
        'Laravel\\Prompts\\SearchPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/SearchPrompt.php',
        'Laravel\\Prompts\\SelectPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/SelectPrompt.php',
        'Laravel\\Prompts\\Spinner' => __DIR__ . '/..' . '/laravel/prompts/src/Spinner.php',
        'Laravel\\Prompts\\Stream' => __DIR__ . '/..' . '/laravel/prompts/src/Stream.php',
        'Laravel\\Prompts\\SuggestPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/SuggestPrompt.php',
        'Laravel\\Prompts\\Support\\Logger' => __DIR__ . '/..' . '/laravel/prompts/src/Support/Logger.php',
        'Laravel\\Prompts\\Support\\Result' => __DIR__ . '/..' . '/laravel/prompts/src/Support/Result.php',
        'Laravel\\Prompts\\Support\\Utils' => __DIR__ . '/..' . '/laravel/prompts/src/Support/Utils.php',
        'Laravel\\Prompts\\Table' => __DIR__ . '/..' . '/laravel/prompts/src/Table.php',
        'Laravel\\Prompts\\Task' => __DIR__ . '/..' . '/laravel/prompts/src/Task.php',
        'Laravel\\Prompts\\Terminal' => __DIR__ . '/..' . '/laravel/prompts/src/Terminal.php',
        'Laravel\\Prompts\\TextPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/TextPrompt.php',
        'Laravel\\Prompts\\TextareaPrompt' => __DIR__ . '/..' . '/laravel/prompts/src/TextareaPrompt.php',
        'Laravel\\Prompts\\Themes\\Contracts\\Scrolling' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Contracts/Scrolling.php',
        'Laravel\\Prompts\\Themes\\Default\\AutoCompletePromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/AutoCompletePromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\ClearRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/ClearRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\Concerns\\DrawsBoxes' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/Concerns/DrawsBoxes.php',
        'Laravel\\Prompts\\Themes\\Default\\Concerns\\DrawsScrollbars' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/Concerns/DrawsScrollbars.php',
        'Laravel\\Prompts\\Themes\\Default\\Concerns\\InteractsWithStrings' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/Concerns/InteractsWithStrings.php',
        'Laravel\\Prompts\\Themes\\Default\\ConfirmPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/ConfirmPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\DataTableRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/DataTableRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\GridRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/GridRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\MultiSearchPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/MultiSearchPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\MultiSelectPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/MultiSelectPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\NoteRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/NoteRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\NumberPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/NumberPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\PasswordPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/PasswordPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\PausePromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/PausePromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\ProgressRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/ProgressRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\Renderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/Renderer.php',
        'Laravel\\Prompts\\Themes\\Default\\SearchPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/SearchPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\SelectPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/SelectPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\SpinnerRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/SpinnerRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\StreamRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/StreamRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\SuggestPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/SuggestPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\TableRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/TableRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\TaskRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/TaskRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\TextPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/TextPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\TextareaPromptRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/TextareaPromptRenderer.php',
        'Laravel\\Prompts\\Themes\\Default\\TitleRenderer' => __DIR__ . '/..' . '/laravel/prompts/src/Themes/Default/TitleRenderer.php',
        'Laravel\\Prompts\\Title' => __DIR__ . '/..' . '/laravel/prompts/src/Title.php',
        'NoDiscard' => __DIR__ . '/..' . '/symfony/polyfill-php85/Resources/stubs/NoDiscard.php',
        'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
        'Override' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/Override.php',
        'Pdo\\Dblib' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Dblib.php',
        'Pdo\\Firebird' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Firebird.php',
        'Pdo\\Mysql' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Mysql.php',
        'Pdo\\Odbc' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Odbc.php',
        'Pdo\\Pgsql' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php',
        'Pdo\\Sqlite' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php',
        'Psr\\Clock\\ClockInterface' => __DIR__ . '/..' . '/psr/clock/src/ClockInterface.php',
        'Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php',
        'Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php',
        'Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php',
        'Psr\\SimpleCache\\CacheException' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheException.php',
        'Psr\\SimpleCache\\CacheInterface' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheInterface.php',
        'Psr\\SimpleCache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/simple-cache/src/InvalidArgumentException.php',
        'ReflectionConstant' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
        'RoundingMode' => __DIR__ . '/..' . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php',
        'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php',
        'SortDirection' => __DIR__ . '/..' . '/symfony/polyfill-php86/Resources/stubs/SortDirection.php',
        'Symfony\\Component\\Clock\\Clock' => __DIR__ . '/..' . '/symfony/clock/Clock.php',
        'Symfony\\Component\\Clock\\ClockAwareTrait' => __DIR__ . '/..' . '/symfony/clock/ClockAwareTrait.php',
        'Symfony\\Component\\Clock\\ClockInterface' => __DIR__ . '/..' . '/symfony/clock/ClockInterface.php',
        'Symfony\\Component\\Clock\\DatePoint' => __DIR__ . '/..' . '/symfony/clock/DatePoint.php',
        'Symfony\\Component\\Clock\\MockClock' => __DIR__ . '/..' . '/symfony/clock/MockClock.php',
        'Symfony\\Component\\Clock\\MonotonicClock' => __DIR__ . '/..' . '/symfony/clock/MonotonicClock.php',
        'Symfony\\Component\\Clock\\NativeClock' => __DIR__ . '/..' . '/symfony/clock/NativeClock.php',
        'Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => __DIR__ . '/..' . '/symfony/clock/Test/ClockSensitiveTrait.php',
        'Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/symfony/console/Application.php',
        'Symfony\\Component\\Console\\Attribute\\Argument' => __DIR__ . '/..' . '/symfony/console/Attribute/Argument.php',
        'Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/symfony/console/Attribute/AsCommand.php',
        'Symfony\\Component\\Console\\Attribute\\Ask' => __DIR__ . '/..' . '/symfony/console/Attribute/Ask.php',
        'Symfony\\Component\\Console\\Attribute\\Interact' => __DIR__ . '/..' . '/symfony/console/Attribute/Interact.php',
        'Symfony\\Component\\Console\\Attribute\\InteractiveAttributeInterface' => __DIR__ . '/..' . '/symfony/console/Attribute/InteractiveAttributeInterface.php',
        'Symfony\\Component\\Console\\Attribute\\MapInput' => __DIR__ . '/..' . '/symfony/console/Attribute/MapInput.php',
        'Symfony\\Component\\Console\\Attribute\\Option' => __DIR__ . '/..' . '/symfony/console/Attribute/Option.php',
        'Symfony\\Component\\Console\\Attribute\\Reflection\\ReflectionMember' => __DIR__ . '/..' . '/symfony/console/Attribute/Reflection/ReflectionMember.php',
        'Symfony\\Component\\Console\\CI\\GithubActionReporter' => __DIR__ . '/..' . '/symfony/console/CI/GithubActionReporter.php',
        'Symfony\\Component\\Console\\Color' => __DIR__ . '/..' . '/symfony/console/Color.php',
        'Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/symfony/console/CommandLoader/CommandLoaderInterface.php',
        'Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/ContainerCommandLoader.php',
        'Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/symfony/console/CommandLoader/FactoryCommandLoader.php',
        'Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/symfony/console/Command/Command.php',
        'Symfony\\Component\\Console\\Command\\CompleteCommand' => __DIR__ . '/..' . '/symfony/console/Command/CompleteCommand.php',
        'Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => __DIR__ . '/..' . '/symfony/console/Command/DumpCompletionCommand.php',
        'Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/symfony/console/Command/HelpCommand.php',
        'Symfony\\Component\\Console\\Command\\InvokableCommand' => __DIR__ . '/..' . '/symfony/console/Command/InvokableCommand.php',
        'Symfony\\Component\\Console\\Command\\LazyCommand' => __DIR__ . '/..' . '/symfony/console/Command/LazyCommand.php',
        'Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/symfony/console/Command/ListCommand.php',
        'Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/symfony/console/Command/LockableTrait.php',
        'Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => __DIR__ . '/..' . '/symfony/console/Command/SignalableCommandInterface.php',
        'Symfony\\Component\\Console\\Command\\TraceableCommand' => __DIR__ . '/..' . '/symfony/console/Command/TraceableCommand.php',
        'Symfony\\Component\\Console\\Completion\\CompletionInput' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionInput.php',
        'Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => __DIR__ . '/..' . '/symfony/console/Completion/CompletionSuggestions.php',
        'Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/BashCompletionOutput.php',
        'Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => __DIR__ . '/..' . '/symfony/console/Completion/Output/CompletionOutputInterface.php',
        'Symfony\\Component\\Console\\Completion\\Output\\FishCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/FishCompletionOutput.php',
        'Symfony\\Component\\Console\\Completion\\Output\\ZshCompletionOutput' => __DIR__ . '/..' . '/symfony/console/Completion/Output/ZshCompletionOutput.php',
        'Symfony\\Component\\Console\\Completion\\Suggestion' => __DIR__ . '/..' . '/symfony/console/Completion/Suggestion.php',
        'Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/symfony/console/ConsoleEvents.php',
        'Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/symfony/console/Cursor.php',
        'Symfony\\Component\\Console\\DataCollector\\CommandDataCollector' => __DIR__ . '/..' . '/symfony/console/DataCollector/CommandDataCollector.php',
        'Symfony\\Component\\Console\\Debug\\CliRequest' => __DIR__ . '/..' . '/symfony/console/Debug/CliRequest.php',
        'Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
        'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/symfony/console/Descriptor/ApplicationDescription.php',
        'Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/Descriptor.php',
        'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/symfony/console/Descriptor/DescriptorInterface.php',
        'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/JsonDescriptor.php',
        'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/MarkdownDescriptor.php',
        'Symfony\\Component\\Console\\Descriptor\\ReStructuredTextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/ReStructuredTextDescriptor.php',
        'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/TextDescriptor.php',
        'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/symfony/console/Descriptor/XmlDescriptor.php',
        'Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/symfony/console/EventListener/ErrorListener.php',
        'Symfony\\Component\\Console\\Event\\ConsoleAlarmEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleAlarmEvent.php',
        'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleCommandEvent.php',
        'Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleErrorEvent.php',
        'Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleEvent.php',
        'Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleSignalEvent.php',
        'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/symfony/console/Event/ConsoleTerminateEvent.php',
        'Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/CommandNotFoundException.php',
        'Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/console/Exception/ExceptionInterface.php',
        'Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidArgumentException.php',
        'Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/symfony/console/Exception/InvalidOptionException.php',
        'Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/console/Exception/LogicException.php',
        'Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/symfony/console/Exception/MissingInputException.php',
        'Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/symfony/console/Exception/NamespaceNotFoundException.php',
        'Symfony\\Component\\Console\\Exception\\RunCommandFailedException' => __DIR__ . '/..' . '/symfony/console/Exception/RunCommandFailedException.php',
        'Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/console/Exception/RuntimeException.php',
        'Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatter.php',
        'Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/NullOutputFormatterStyle.php',
        'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatter.php',
        'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterInterface.php',
        'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyle.php',
        'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleInterface.php',
        'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/symfony/console/Formatter/OutputFormatterStyleStack.php',
        'Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/symfony/console/Formatter/WrappableOutputFormatterInterface.php',
        'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DebugFormatterHelper.php',
        'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/symfony/console/Helper/DescriptorHelper.php',
        'Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/symfony/console/Helper/Dumper.php',
        'Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/symfony/console/Helper/FormatterHelper.php',
        'Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/symfony/console/Helper/Helper.php',
        'Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/symfony/console/Helper/HelperInterface.php',
        'Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/symfony/console/Helper/HelperSet.php',
        'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/symfony/console/Helper/InputAwareHelper.php',
        'Symfony\\Component\\Console\\Helper\\OutputWrapper' => __DIR__ . '/..' . '/symfony/console/Helper/OutputWrapper.php',
        'Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/symfony/console/Helper/ProcessHelper.php',
        'Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressBar.php',
        'Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/symfony/console/Helper/ProgressIndicator.php',
        'Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/QuestionHelper.php',
        'Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/symfony/console/Helper/SymfonyQuestionHelper.php',
        'Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/symfony/console/Helper/Table.php',
        'Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/symfony/console/Helper/TableCell.php',
        'Symfony\\Component\\Console\\Helper\\TableCellStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableCellStyle.php',
        'Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/symfony/console/Helper/TableRows.php',
        'Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/symfony/console/Helper/TableSeparator.php',
        'Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TableStyle.php',
        'Symfony\\Component\\Console\\Helper\\TerminalInputHelper' => __DIR__ . '/..' . '/symfony/console/Helper/TerminalInputHelper.php',
        'Symfony\\Component\\Console\\Helper\\TreeHelper' => __DIR__ . '/..' . '/symfony/console/Helper/TreeHelper.php',
        'Symfony\\Component\\Console\\Helper\\TreeNode' => __DIR__ . '/..' . '/symfony/console/Helper/TreeNode.php',
        'Symfony\\Component\\Console\\Helper\\TreeStyle' => __DIR__ . '/..' . '/symfony/console/Helper/TreeStyle.php',
        'Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/symfony/console/Input/ArgvInput.php',
        'Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/symfony/console/Input/ArrayInput.php',
        'Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/symfony/console/Input/Input.php',
        'Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/symfony/console/Input/InputArgument.php',
        'Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputAwareInterface.php',
        'Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/symfony/console/Input/InputDefinition.php',
        'Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/symfony/console/Input/InputInterface.php',
        'Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/symfony/console/Input/InputOption.php',
        'Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/symfony/console/Input/StreamableInputInterface.php',
        'Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/symfony/console/Input/StringInput.php',
        'Symfony\\Component\\Console\\Interaction\\Interaction' => __DIR__ . '/..' . '/symfony/console/Interaction/Interaction.php',
        'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/symfony/console/Logger/ConsoleLogger.php',
        'Symfony\\Component\\Console\\Messenger\\RunCommandContext' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandContext.php',
        'Symfony\\Component\\Console\\Messenger\\RunCommandMessage' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandMessage.php',
        'Symfony\\Component\\Console\\Messenger\\RunCommandMessageHandler' => __DIR__ . '/..' . '/symfony/console/Messenger/RunCommandMessageHandler.php',
        'Symfony\\Component\\Console\\Output\\AnsiColorMode' => __DIR__ . '/..' . '/symfony/console/Output/AnsiColorMode.php',
        'Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/symfony/console/Output/BufferedOutput.php',
        'Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutput.php',
        'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleOutputInterface.php',
        'Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/symfony/console/Output/ConsoleSectionOutput.php',
        'Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/symfony/console/Output/NullOutput.php',
        'Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/symfony/console/Output/Output.php',
        'Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/symfony/console/Output/OutputInterface.php',
        'Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/symfony/console/Output/StreamOutput.php',
        'Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/symfony/console/Output/TrimmedBufferOutput.php',
        'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ChoiceQuestion.php',
        'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/symfony/console/Question/ConfirmationQuestion.php',
        'Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/symfony/console/Question/Question.php',
        'Symfony\\Component\\Console\\SignalRegistry\\SignalMap' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalMap.php',
        'Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => __DIR__ . '/..' . '/symfony/console/SignalRegistry/SignalRegistry.php',
        'Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/symfony/console/SingleCommandApplication.php',
        'Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/symfony/console/Style/OutputStyle.php',
        'Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/symfony/console/Style/StyleInterface.php',
        'Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/symfony/console/Style/SymfonyStyle.php',
        'Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/symfony/console/Terminal.php',
        'Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/symfony/console/Tester/ApplicationTester.php',
        'Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandCompletionTester.php',
        'Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/symfony/console/Tester/CommandTester.php',
        'Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => __DIR__ . '/..' . '/symfony/console/Tester/Constraint/CommandIsSuccessful.php',
        'Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/symfony/console/Tester/TesterTrait.php',
        'Symfony\\Component\\Finder\\Comparator\\Comparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/Comparator.php',
        'Symfony\\Component\\Finder\\Comparator\\DateComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/DateComparator.php',
        'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => __DIR__ . '/..' . '/symfony/finder/Comparator/NumberComparator.php',
        'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/symfony/finder/Exception/AccessDeniedException.php',
        'Symfony\\Component\\Finder\\Exception\\DirectoryNotFoundException' => __DIR__ . '/..' . '/symfony/finder/Exception/DirectoryNotFoundException.php',
        'Symfony\\Component\\Finder\\Finder' => __DIR__ . '/..' . '/symfony/finder/Finder.php',
        'Symfony\\Component\\Finder\\Gitignore' => __DIR__ . '/..' . '/symfony/finder/Gitignore.php',
        'Symfony\\Component\\Finder\\Glob' => __DIR__ . '/..' . '/symfony/finder/Glob.php',
        'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/CustomFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DateRangeFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/DepthRangeFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FileTypeFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilecontentFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/FilenameFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\LazyIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/LazyIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/MultiplePcreFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/PathFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/RecursiveDirectoryIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SizeRangeFilterIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/SortableIterator.php',
        'Symfony\\Component\\Finder\\Iterator\\VcsIgnoredFilterIterator' => __DIR__ . '/..' . '/symfony/finder/Iterator/VcsIgnoredFilterIterator.php',
        'Symfony\\Component\\Finder\\SplFileInfo' => __DIR__ . '/..' . '/symfony/finder/SplFileInfo.php',
        'Symfony\\Component\\Process\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/process/Exception/ExceptionInterface.php',
        'Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/process/Exception/InvalidArgumentException.php',
        'Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php',
        'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php',
        'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php',
        'Symfony\\Component\\Process\\Exception\\ProcessStartFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessStartFailedException.php',
        'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php',
        'Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/RunProcessFailedException.php',
        'Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php',
        'Symfony\\Component\\Process\\ExecutableFinder' => __DIR__ . '/..' . '/symfony/process/ExecutableFinder.php',
        'Symfony\\Component\\Process\\InputStream' => __DIR__ . '/..' . '/symfony/process/InputStream.php',
        'Symfony\\Component\\Process\\Messenger\\RunProcessContext' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessContext.php',
        'Symfony\\Component\\Process\\Messenger\\RunProcessMessage' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessMessage.php',
        'Symfony\\Component\\Process\\Messenger\\RunProcessMessageHandler' => __DIR__ . '/..' . '/symfony/process/Messenger/RunProcessMessageHandler.php',
        'Symfony\\Component\\Process\\PhpExecutableFinder' => __DIR__ . '/..' . '/symfony/process/PhpExecutableFinder.php',
        'Symfony\\Component\\Process\\PhpProcess' => __DIR__ . '/..' . '/symfony/process/PhpProcess.php',
        'Symfony\\Component\\Process\\PhpSubprocess' => __DIR__ . '/..' . '/symfony/process/PhpSubprocess.php',
        'Symfony\\Component\\Process\\Pipes\\AbstractPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/AbstractPipes.php',
        'Symfony\\Component\\Process\\Pipes\\PipesInterface' => __DIR__ . '/..' . '/symfony/process/Pipes/PipesInterface.php',
        'Symfony\\Component\\Process\\Pipes\\UnixPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/UnixPipes.php',
        'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/symfony/process/Pipes/WindowsPipes.php',
        'Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/symfony/process/Process.php',
        'Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/symfony/process/ProcessUtils.php',
        'Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/symfony/string/AbstractString.php',
        'Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/symfony/string/AbstractUnicodeString.php',
        'Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/symfony/string/ByteString.php',
        'Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/symfony/string/CodePointString.php',
        'Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/string/Exception/ExceptionInterface.php',
        'Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/string/Exception/InvalidArgumentException.php',
        'Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/string/Exception/RuntimeException.php',
        'Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/EnglishInflector.php',
        'Symfony\\Component\\String\\Inflector\\FrenchInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/FrenchInflector.php',
        'Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/symfony/string/Inflector/InflectorInterface.php',
        'Symfony\\Component\\String\\Inflector\\SpanishInflector' => __DIR__ . '/..' . '/symfony/string/Inflector/SpanishInflector.php',
        'Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/symfony/string/LazyString.php',
        'Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/symfony/string/Slugger/AsciiSlugger.php',
        'Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/symfony/string/Slugger/SluggerInterface.php',
        'Symfony\\Component\\String\\TruncateMode' => __DIR__ . '/..' . '/symfony/string/TruncateMode.php',
        'Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/symfony/string/UnicodeString.php',
        'Symfony\\Component\\Translation\\CatalogueMetadataAwareInterface' => __DIR__ . '/..' . '/symfony/translation/CatalogueMetadataAwareInterface.php',
        'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/AbstractOperation.php',
        'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/MergeOperation.php',
        'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => __DIR__ . '/..' . '/symfony/translation/Catalogue/OperationInterface.php',
        'Symfony\\Component\\Translation\\Catalogue\\TargetOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/TargetOperation.php',
        'Symfony\\Component\\Translation\\Command\\TranslationLintCommand' => __DIR__ . '/..' . '/symfony/translation/Command/TranslationLintCommand.php',
        'Symfony\\Component\\Translation\\Command\\TranslationPullCommand' => __DIR__ . '/..' . '/symfony/translation/Command/TranslationPullCommand.php',
        'Symfony\\Component\\Translation\\Command\\TranslationPushCommand' => __DIR__ . '/..' . '/symfony/translation/Command/TranslationPushCommand.php',
        'Symfony\\Component\\Translation\\Command\\TranslationTrait' => __DIR__ . '/..' . '/symfony/translation/Command/TranslationTrait.php',
        'Symfony\\Component\\Translation\\Command\\XliffLintCommand' => __DIR__ . '/..' . '/symfony/translation/Command/XliffLintCommand.php',
        'Symfony\\Component\\Translation\\DataCollectorTranslator' => __DIR__ . '/..' . '/symfony/translation/DataCollectorTranslator.php',
        'Symfony\\Component\\Translation\\DataCollector\\TranslationDataCollector' => __DIR__ . '/..' . '/symfony/translation/DataCollector/TranslationDataCollector.php',
        'Symfony\\Component\\Translation\\DependencyInjection\\DataCollectorTranslatorPass' => __DIR__ . '/..' . '/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php',
        'Symfony\\Component\\Translation\\DependencyInjection\\LoggingTranslatorPass' => __DIR__ . '/..' . '/symfony/translation/DependencyInjection/LoggingTranslatorPass.php',
        'Symfony\\Component\\Translation\\DependencyInjection\\TranslationDumperPass' => __DIR__ . '/..' . '/symfony/translation/DependencyInjection/TranslationDumperPass.php',
        'Symfony\\Component\\Translation\\DependencyInjection\\TranslationExtractorPass' => __DIR__ . '/..' . '/symfony/translation/DependencyInjection/TranslationExtractorPass.php',
        'Symfony\\Component\\Translation\\DependencyInjection\\TranslatorPass' => __DIR__ . '/..' . '/symfony/translation/DependencyInjection/TranslatorPass.php',
        'Symfony\\Component\\Translation\\DependencyInjection\\TranslatorPathsPass' => __DIR__ . '/..' . '/symfony/translation/DependencyInjection/TranslatorPathsPass.php',
        'Symfony\\Component\\Translation\\Dumper\\CsvFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/CsvFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\DumperInterface' => __DIR__ . '/..' . '/symfony/translation/Dumper/DumperInterface.php',
        'Symfony\\Component\\Translation\\Dumper\\FileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/FileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\IcuResFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/IcuResFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\IniFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/IniFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\JsonFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/JsonFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\MoFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/MoFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\PhpFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/PhpFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\PoFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/PoFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\QtFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/QtFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\XliffFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/XliffFileDumper.php',
        'Symfony\\Component\\Translation\\Dumper\\YamlFileDumper' => __DIR__ . '/..' . '/symfony/translation/Dumper/YamlFileDumper.php',
        'Symfony\\Component\\Translation\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/translation/Exception/ExceptionInterface.php',
        'Symfony\\Component\\Translation\\Exception\\IncompleteDsnException' => __DIR__ . '/..' . '/symfony/translation/Exception/IncompleteDsnException.php',
        'Symfony\\Component\\Translation\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/translation/Exception/InvalidArgumentException.php',
        'Symfony\\Component\\Translation\\Exception\\InvalidResourceException' => __DIR__ . '/..' . '/symfony/translation/Exception/InvalidResourceException.php',
        'Symfony\\Component\\Translation\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/translation/Exception/LogicException.php',
        'Symfony\\Component\\Translation\\Exception\\MissingRequiredOptionException' => __DIR__ . '/..' . '/symfony/translation/Exception/MissingRequiredOptionException.php',
        'Symfony\\Component\\Translation\\Exception\\NotFoundResourceException' => __DIR__ . '/..' . '/symfony/translation/Exception/NotFoundResourceException.php',
        'Symfony\\Component\\Translation\\Exception\\ProviderException' => __DIR__ . '/..' . '/symfony/translation/Exception/ProviderException.php',
        'Symfony\\Component\\Translation\\Exception\\ProviderExceptionInterface' => __DIR__ . '/..' . '/symfony/translation/Exception/ProviderExceptionInterface.php',
        'Symfony\\Component\\Translation\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/translation/Exception/RuntimeException.php',
        'Symfony\\Component\\Translation\\Exception\\UnsupportedSchemeException' => __DIR__ . '/..' . '/symfony/translation/Exception/UnsupportedSchemeException.php',
        'Symfony\\Component\\Translation\\Extractor\\AbstractFileExtractor' => __DIR__ . '/..' . '/symfony/translation/Extractor/AbstractFileExtractor.php',
        'Symfony\\Component\\Translation\\Extractor\\ChainExtractor' => __DIR__ . '/..' . '/symfony/translation/Extractor/ChainExtractor.php',
        'Symfony\\Component\\Translation\\Extractor\\ExtractorInterface' => __DIR__ . '/..' . '/symfony/translation/Extractor/ExtractorInterface.php',
        'Symfony\\Component\\Translation\\Extractor\\PhpAstExtractor' => __DIR__ . '/..' . '/symfony/translation/Extractor/PhpAstExtractor.php',
        'Symfony\\Component\\Translation\\Extractor\\Visitor\\AbstractVisitor' => __DIR__ . '/..' . '/symfony/translation/Extractor/Visitor/AbstractVisitor.php',
        'Symfony\\Component\\Translation\\Extractor\\Visitor\\ConstraintVisitor' => __DIR__ . '/..' . '/symfony/translation/Extractor/Visitor/ConstraintVisitor.php',
        'Symfony\\Component\\Translation\\Extractor\\Visitor\\TransMethodVisitor' => __DIR__ . '/..' . '/symfony/translation/Extractor/Visitor/TransMethodVisitor.php',
        'Symfony\\Component\\Translation\\Extractor\\Visitor\\TranslatableMessageVisitor' => __DIR__ . '/..' . '/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php',
        'Symfony\\Component\\Translation\\Formatter\\IntlFormatter' => __DIR__ . '/..' . '/symfony/translation/Formatter/IntlFormatter.php',
        'Symfony\\Component\\Translation\\Formatter\\IntlFormatterInterface' => __DIR__ . '/..' . '/symfony/translation/Formatter/IntlFormatterInterface.php',
        'Symfony\\Component\\Translation\\Formatter\\MessageFormatter' => __DIR__ . '/..' . '/symfony/translation/Formatter/MessageFormatter.php',
        'Symfony\\Component\\Translation\\Formatter\\MessageFormatterInterface' => __DIR__ . '/..' . '/symfony/translation/Formatter/MessageFormatterInterface.php',
        'Symfony\\Component\\Translation\\IdentityTranslator' => __DIR__ . '/..' . '/symfony/translation/IdentityTranslator.php',
        'Symfony\\Component\\Translation\\Loader\\ArrayLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/ArrayLoader.php',
        'Symfony\\Component\\Translation\\Loader\\CsvFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/CsvFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\FileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/FileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\IcuDatFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/IcuDatFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\IcuResFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/IcuResFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\IniFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/IniFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\JsonFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/JsonFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/symfony/translation/Loader/LoaderInterface.php',
        'Symfony\\Component\\Translation\\Loader\\MoFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/MoFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/PhpFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\PoFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/PoFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\QtFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/QtFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\XliffFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/XliffFileLoader.php',
        'Symfony\\Component\\Translation\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/translation/Loader/YamlFileLoader.php',
        'Symfony\\Component\\Translation\\LocaleSwitcher' => __DIR__ . '/..' . '/symfony/translation/LocaleSwitcher.php',
        'Symfony\\Component\\Translation\\LoggingTranslator' => __DIR__ . '/..' . '/symfony/translation/LoggingTranslator.php',
        'Symfony\\Component\\Translation\\MessageCatalogue' => __DIR__ . '/..' . '/symfony/translation/MessageCatalogue.php',
        'Symfony\\Component\\Translation\\MessageCatalogueInterface' => __DIR__ . '/..' . '/symfony/translation/MessageCatalogueInterface.php',
        'Symfony\\Component\\Translation\\MetadataAwareInterface' => __DIR__ . '/..' . '/symfony/translation/MetadataAwareInterface.php',
        'Symfony\\Component\\Translation\\Provider\\AbstractProviderFactory' => __DIR__ . '/..' . '/symfony/translation/Provider/AbstractProviderFactory.php',
        'Symfony\\Component\\Translation\\Provider\\Dsn' => __DIR__ . '/..' . '/symfony/translation/Provider/Dsn.php',
        'Symfony\\Component\\Translation\\Provider\\FilteringProvider' => __DIR__ . '/..' . '/symfony/translation/Provider/FilteringProvider.php',
        'Symfony\\Component\\Translation\\Provider\\NullProvider' => __DIR__ . '/..' . '/symfony/translation/Provider/NullProvider.php',
        'Symfony\\Component\\Translation\\Provider\\NullProviderFactory' => __DIR__ . '/..' . '/symfony/translation/Provider/NullProviderFactory.php',
        'Symfony\\Component\\Translation\\Provider\\ProviderFactoryInterface' => __DIR__ . '/..' . '/symfony/translation/Provider/ProviderFactoryInterface.php',
        'Symfony\\Component\\Translation\\Provider\\ProviderInterface' => __DIR__ . '/..' . '/symfony/translation/Provider/ProviderInterface.php',
        'Symfony\\Component\\Translation\\Provider\\TranslationProviderCollection' => __DIR__ . '/..' . '/symfony/translation/Provider/TranslationProviderCollection.php',
        'Symfony\\Component\\Translation\\Provider\\TranslationProviderCollectionFactory' => __DIR__ . '/..' . '/symfony/translation/Provider/TranslationProviderCollectionFactory.php',
        'Symfony\\Component\\Translation\\PseudoLocalizationTranslator' => __DIR__ . '/..' . '/symfony/translation/PseudoLocalizationTranslator.php',
        'Symfony\\Component\\Translation\\Reader\\TranslationReader' => __DIR__ . '/..' . '/symfony/translation/Reader/TranslationReader.php',
        'Symfony\\Component\\Translation\\Reader\\TranslationReaderInterface' => __DIR__ . '/..' . '/symfony/translation/Reader/TranslationReaderInterface.php',
        'Symfony\\Component\\Translation\\StaticMessage' => __DIR__ . '/..' . '/symfony/translation/StaticMessage.php',
        'Symfony\\Component\\Translation\\Test\\AbstractProviderFactoryTestCase' => __DIR__ . '/..' . '/symfony/translation/Test/AbstractProviderFactoryTestCase.php',
        'Symfony\\Component\\Translation\\Test\\IncompleteDsnTestTrait' => __DIR__ . '/..' . '/symfony/translation/Test/IncompleteDsnTestTrait.php',
        'Symfony\\Component\\Translation\\Test\\ProviderFactoryTestCase' => __DIR__ . '/..' . '/symfony/translation/Test/ProviderFactoryTestCase.php',
        'Symfony\\Component\\Translation\\Test\\ProviderTestCase' => __DIR__ . '/..' . '/symfony/translation/Test/ProviderTestCase.php',
        'Symfony\\Component\\Translation\\TranslatableMessage' => __DIR__ . '/..' . '/symfony/translation/TranslatableMessage.php',
        'Symfony\\Component\\Translation\\Translator' => __DIR__ . '/..' . '/symfony/translation/Translator.php',
        'Symfony\\Component\\Translation\\TranslatorBag' => __DIR__ . '/..' . '/symfony/translation/TranslatorBag.php',
        'Symfony\\Component\\Translation\\TranslatorBagInterface' => __DIR__ . '/..' . '/symfony/translation/TranslatorBagInterface.php',
        'Symfony\\Component\\Translation\\Util\\ArrayConverter' => __DIR__ . '/..' . '/symfony/translation/Util/ArrayConverter.php',
        'Symfony\\Component\\Translation\\Util\\XliffUtils' => __DIR__ . '/..' . '/symfony/translation/Util/XliffUtils.php',
        'Symfony\\Component\\Translation\\Writer\\TranslationWriter' => __DIR__ . '/..' . '/symfony/translation/Writer/TranslationWriter.php',
        'Symfony\\Component\\Translation\\Writer\\TranslationWriterInterface' => __DIR__ . '/..' . '/symfony/translation/Writer/TranslationWriterInterface.php',
        'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php',
        'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php',
        'Symfony\\Contracts\\Service\\ContainerAwareInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ContainerAwareInterface.php',
        'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php',
        'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceCollectionInterface.php',
        'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php',
        'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php',
        'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php',
        'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php',
        'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php',
        'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => __DIR__ . '/..' . '/symfony/translation-contracts/LocaleAwareInterface.php',
        'Symfony\\Contracts\\Translation\\TranslatableInterface' => __DIR__ . '/..' . '/symfony/translation-contracts/TranslatableInterface.php',
        'Symfony\\Contracts\\Translation\\TranslatorInterface' => __DIR__ . '/..' . '/symfony/translation-contracts/TranslatorInterface.php',
        'Symfony\\Contracts\\Translation\\TranslatorTrait' => __DIR__ . '/..' . '/symfony/translation-contracts/TranslatorTrait.php',
        'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/symfony/polyfill-ctype/Ctype.php',
        'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/Grapheme.php',
        'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php',
        'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php',
        'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php',
        'Symfony\\Polyfill\\Php84\\Php84' => __DIR__ . '/..' . '/symfony/polyfill-php84/Php84.php',
        'Symfony\\Polyfill\\Php85\\Php85' => __DIR__ . '/..' . '/symfony/polyfill-php85/Php85.php',
        'Symfony\\Polyfill\\Php86\\Php86' => __DIR__ . '/..' . '/symfony/polyfill-php86/Php86.php',
        'voku\\helper\\ASCII' => __DIR__ . '/..' . '/voku/portable-ascii/src/voku/helper/ASCII.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInita408f660b5e9690e372ddcb0227a007b::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInita408f660b5e9690e372ddcb0227a007b::$prefixDirsPsr4;
            $loader->classMap = ComposerStaticInita408f660b5e9690e372ddcb0227a007b::$classMap;

        }, null, ClassLoader::class);
    }
}
<?php return array(
    'root' => array(
        'name' => 'laravel/installer',
        'pretty_version' => 'dev-main',
        'version' => 'dev-main',
        'reference' => '8e860f0cdbac4a6e189fbeb967ed0ded73935733',
        'type' => 'library',
        'install_path' => __DIR__ . '/../../',
        'aliases' => array(),
        'dev' => true,
    ),
    'versions' => array(
        'beyondcode/herd-configuration' => array(
            'pretty_version' => 'dev-main',
            'version' => 'dev-main',
            'reference' => '9e281e32a348ef91bd757d23918de0d4777efa06',
            'type' => 'library',
            'install_path' => __DIR__ . '/../beyondcode/herd-configuration',
            'aliases' => array(
                0 => '9999999-dev',
            ),
            'dev_requirement' => false,
        ),
        'carbonphp/carbon-doctrine-types' => array(
            'pretty_version' => '3.2.0',
            'version' => '3.2.0.0',
            'reference' => '18ba5ddfec8976260ead6e866180bd5d2f71aa1d',
            'type' => 'library',
            'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'doctrine/inflector' => array(
            'pretty_version' => '2.1.0',
            'version' => '2.1.0.0',
            'reference' => '6d6c96277ea252fc1304627204c3d5e6e15faa3b',
            'type' => 'library',
            'install_path' => __DIR__ . '/../doctrine/inflector',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/collections' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => 'dda57c96a3e2620e4218ba54c818d55c9c2fcd4f',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/collections',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/conditionable' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => '7f1ef52d9a346f829421b296adfb7644a951b216',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/conditionable',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/contracts' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => '71dba8668753f7c6ea862bc4258eba6513b592ec',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/contracts',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/filesystem' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => 'bc6d4e2b0482b86521b29ae95fdc74d8909521ac',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/filesystem',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/macroable' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => '59b5b5f3cf290a91db8cf6cd3d35ff56978bc057',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/macroable',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/reflection' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => '4fe1659f068ab2b50131cf906c5d8bba4e34df0c',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/reflection',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'illuminate/support' => array(
            'pretty_version' => 'v13.9.0',
            'version' => '13.9.0.0',
            'reference' => '3367c25b040788835fd043fbddb64bd5af659ec6',
            'type' => 'library',
            'install_path' => __DIR__ . '/../illuminate/support',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'laravel/agent-detector' => array(
            'pretty_version' => 'v2.0.2',
            'version' => '2.0.2.0',
            'reference' => '90694b9256099591cf9e55d08c18ba7a00bf099f',
            'type' => 'library',
            'install_path' => __DIR__ . '/../laravel/agent-detector',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'laravel/installer' => array(
            'pretty_version' => 'dev-main',
            'version' => 'dev-main',
            'reference' => '8e860f0cdbac4a6e189fbeb967ed0ded73935733',
            'type' => 'library',
            'install_path' => __DIR__ . '/../../',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'laravel/prompts' => array(
            'pretty_version' => 'v0.3.18',
            'version' => '0.3.18.0',
            'reference' => 'a19af51bb144bf87f08397921fa619f85c7d4e72',
            'type' => 'library',
            'install_path' => __DIR__ . '/../laravel/prompts',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'myclabs/deep-copy' => array(
            'pretty_version' => '1.13.4',
            'version' => '1.13.4.0',
            'reference' => '07d290f0c47959fd5eed98c95ee5602db07e0b6a',
            'type' => 'library',
            'install_path' => __DIR__ . '/../myclabs/deep-copy',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'nesbot/carbon' => array(
            'pretty_version' => '3.11.4',
            'version' => '3.11.4.0',
            'reference' => 'e890471a3494740f7d9326d72ce6a8c559ffee60',
            'type' => 'library',
            'install_path' => __DIR__ . '/../nesbot/carbon',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'nikic/php-parser' => array(
            'pretty_version' => 'v5.7.0',
            'version' => '5.7.0.0',
            'reference' => 'dca41cd15c2ac9d055ad70dbfd011130757d1f82',
            'type' => 'library',
            'install_path' => __DIR__ . '/../nikic/php-parser',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phar-io/manifest' => array(
            'pretty_version' => '2.0.4',
            'version' => '2.0.4.0',
            'reference' => '54750ef60c58e43759730615a392c31c80e23176',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phar-io/manifest',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phar-io/version' => array(
            'pretty_version' => '3.2.1',
            'version' => '3.2.1.0',
            'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phar-io/version',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpstan/phpstan' => array(
            'pretty_version' => '2.1.55',
            'version' => '2.1.55.0',
            'reference' => '9eaac3826ed5e9b8427350a43cac825eeca3f566',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpstan/phpstan',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpunit/php-code-coverage' => array(
            'pretty_version' => '10.1.16',
            'version' => '10.1.16.0',
            'reference' => '7e308268858ed6baedc8704a304727d20bc07c77',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpunit/php-code-coverage',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpunit/php-file-iterator' => array(
            'pretty_version' => '4.1.0',
            'version' => '4.1.0.0',
            'reference' => 'a95037b6d9e608ba092da1b23931e537cadc3c3c',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpunit/php-file-iterator',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpunit/php-invoker' => array(
            'pretty_version' => '4.0.0',
            'version' => '4.0.0.0',
            'reference' => 'f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpunit/php-invoker',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpunit/php-text-template' => array(
            'pretty_version' => '3.0.1',
            'version' => '3.0.1.0',
            'reference' => '0c7b06ff49e3d5072f057eb1fa59258bf287a748',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpunit/php-text-template',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpunit/php-timer' => array(
            'pretty_version' => '6.0.0',
            'version' => '6.0.0.0',
            'reference' => 'e2a2d67966e740530f4a3343fe2e030ffdc1161d',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpunit/php-timer',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'phpunit/phpunit' => array(
            'pretty_version' => '10.5.63',
            'version' => '10.5.63.0',
            'reference' => '33198268dad71e926626b618f3ec3966661e4d90',
            'type' => 'library',
            'install_path' => __DIR__ . '/../phpunit/phpunit',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'psr/clock' => array(
            'pretty_version' => '1.0.0',
            'version' => '1.0.0.0',
            'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
            'type' => 'library',
            'install_path' => __DIR__ . '/../psr/clock',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'psr/clock-implementation' => array(
            'dev_requirement' => false,
            'provided' => array(
                0 => '1.0',
            ),
        ),
        'psr/container' => array(
            'pretty_version' => '2.0.2',
            'version' => '2.0.2.0',
            'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
            'type' => 'library',
            'install_path' => __DIR__ . '/../psr/container',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'psr/log-implementation' => array(
            'dev_requirement' => false,
            'provided' => array(
                0 => '1.0|2.0|3.0',
            ),
        ),
        'psr/simple-cache' => array(
            'pretty_version' => '3.0.0',
            'version' => '3.0.0.0',
            'reference' => '764e0b3939f5ca87cb904f570ef9be2d78a07865',
            'type' => 'library',
            'install_path' => __DIR__ . '/../psr/simple-cache',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'sebastian/cli-parser' => array(
            'pretty_version' => '2.0.1',
            'version' => '2.0.1.0',
            'reference' => 'c34583b87e7b7a8055bf6c450c2c77ce32a24084',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/cli-parser',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/code-unit' => array(
            'pretty_version' => '2.0.0',
            'version' => '2.0.0.0',
            'reference' => 'a81fee9eef0b7a76af11d121767abc44c104e503',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/code-unit',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/code-unit-reverse-lookup' => array(
            'pretty_version' => '3.0.0',
            'version' => '3.0.0.0',
            'reference' => '5e3a687f7d8ae33fb362c5c0743794bbb2420a1d',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/comparator' => array(
            'pretty_version' => '5.0.5',
            'version' => '5.0.5.0',
            'reference' => '55dfef806eb7dfeb6e7a6935601fef866f8ca48d',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/comparator',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/complexity' => array(
            'pretty_version' => '3.2.0',
            'version' => '3.2.0.0',
            'reference' => '68ff824baeae169ec9f2137158ee529584553799',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/complexity',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/diff' => array(
            'pretty_version' => '5.1.1',
            'version' => '5.1.1.0',
            'reference' => 'c41e007b4b62af48218231d6c2275e4c9b975b2e',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/diff',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/environment' => array(
            'pretty_version' => '6.1.0',
            'version' => '6.1.0.0',
            'reference' => '8074dbcd93529b357029f5cc5058fd3e43666984',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/environment',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/exporter' => array(
            'pretty_version' => '5.1.4',
            'version' => '5.1.4.0',
            'reference' => '0735b90f4da94969541dac1da743446e276defa6',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/exporter',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/global-state' => array(
            'pretty_version' => '6.0.2',
            'version' => '6.0.2.0',
            'reference' => '987bafff24ecc4c9ac418cab1145b96dd6e9cbd9',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/global-state',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/lines-of-code' => array(
            'pretty_version' => '2.0.2',
            'version' => '2.0.2.0',
            'reference' => '856e7f6a75a84e339195d48c556f23be2ebf75d0',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/lines-of-code',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/object-enumerator' => array(
            'pretty_version' => '5.0.0',
            'version' => '5.0.0.0',
            'reference' => '202d0e344a580d7f7d04b3fafce6933e59dae906',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/object-enumerator',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/object-reflector' => array(
            'pretty_version' => '3.0.0',
            'version' => '3.0.0.0',
            'reference' => '24ed13d98130f0e7122df55d06c5c4942a577957',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/object-reflector',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/recursion-context' => array(
            'pretty_version' => '5.0.1',
            'version' => '5.0.1.0',
            'reference' => '47e34210757a2f37a97dcd207d032e1b01e64c7a',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/recursion-context',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/type' => array(
            'pretty_version' => '4.0.0',
            'version' => '4.0.0.0',
            'reference' => '462699a16464c3944eefc02ebdd77882bd3925bf',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/type',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'sebastian/version' => array(
            'pretty_version' => '4.0.1',
            'version' => '4.0.1.0',
            'reference' => 'c51fa83a5d8f43f1402e3f32a005e6262244ef17',
            'type' => 'library',
            'install_path' => __DIR__ . '/../sebastian/version',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'spatie/once' => array(
            'dev_requirement' => false,
            'replaced' => array(
                0 => '*',
            ),
        ),
        'symfony/clock' => array(
            'pretty_version' => 'v7.4.8',
            'version' => '7.4.8.0',
            'reference' => '674fa3b98e21531dd040e613479f5f6fa8f32111',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/clock',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/console' => array(
            'pretty_version' => 'v7.4.11',
            'version' => '7.4.11.0',
            'reference' => 'ed0107e43ab452aa77ae99e005b95e56b556e075',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/console',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/deprecation-contracts' => array(
            'pretty_version' => 'v3.7.0',
            'version' => '3.7.0.0',
            'reference' => '50f59d1f3ca46d41ac911f97a78626b6756af35b',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/finder' => array(
            'pretty_version' => 'v7.4.8',
            'version' => '7.4.8.0',
            'reference' => 'e0be088d22278583a82da281886e8c3592fbf149',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/finder',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-ctype' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '141046a8f9477948ff284fa65be2095baafb94f2',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-intl-grapheme' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '4864388bfbd3001ce88e234fab652acd91fdc57e',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-intl-normalizer' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '3833d7255cc303546435cb650316bff708a1c75c',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-mbstring' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '6a21eb99c6973357967f6ce3708cd55a6bec6315',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-php83' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '3600c2cb22399e25bb226e4a135ce91eeb2a6149',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-php83',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-php84' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '88486db2c389b290bf87ff1de7ebc1e13e42bb06',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-php84',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-php85' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => 'fcfa4973a9917cef23f2e38774da74a2b7d115ee',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-php85',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/polyfill-php86' => array(
            'pretty_version' => 'v1.37.0',
            'version' => '1.37.0.0',
            'reference' => '33d8fc5a705481e21fe3a81212b26f9b1f61749c',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/polyfill-php86',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/process' => array(
            'pretty_version' => 'v7.4.11',
            'version' => '7.4.11.0',
            'reference' => 'd9593c9efa40499eb078b81144de42cbc28a31f0',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/process',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/service-contracts' => array(
            'pretty_version' => 'v3.7.0',
            'version' => '3.7.0.0',
            'reference' => 'd25d82433a80eba6aa0e6c24b61d7370d99e444a',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/service-contracts',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/string' => array(
            'pretty_version' => 'v7.4.11',
            'version' => '7.4.11.0',
            'reference' => '965f7306a43383d02c6aca1e3f3bd2f0ea5dee15',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/string',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/translation' => array(
            'pretty_version' => 'v7.4.10',
            'version' => '7.4.10.0',
            'reference' => 'ada7578c30dd5feaa8259cff3e885069ea81ddde',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/translation',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/translation-contracts' => array(
            'pretty_version' => 'v3.7.0',
            'version' => '3.7.0.0',
            'reference' => '0ab302977a952b42fd51475c4ebac81f8da0a95d',
            'type' => 'library',
            'install_path' => __DIR__ . '/../symfony/translation-contracts',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
        'symfony/translation-implementation' => array(
            'dev_requirement' => false,
            'provided' => array(
                0 => '2.3|3.0',
            ),
        ),
        'theseer/tokenizer' => array(
            'pretty_version' => '1.3.1',
            'version' => '1.3.1.0',
            'reference' => 'b7489ce515e168639d17feec34b8847c326b0b3c',
            'type' => 'library',
            'install_path' => __DIR__ . '/../theseer/tokenizer',
            'aliases' => array(),
            'dev_requirement' => true,
        ),
        'voku/portable-ascii' => array(
            'pretty_version' => '2.1.1',
            'version' => '2.1.1.0',
            'reference' => '8e1051fe39379367aecf014f41744ce7539a856f',
            'type' => 'library',
            'install_path' => __DIR__ . '/../voku/portable-ascii',
            'aliases' => array(),
            'dev_requirement' => false,
        ),
    ),
);
<?php

declare(strict_types=1);

namespace Laravel\AgentDetector;

enum KnownAgent: string
{
    case Cursor = 'cursor';
    case Claude = 'claude';
    case Cowork = 'cowork';
    case Devin = 'devin';
    case Replit = 'replit';
    case Gemini = 'gemini';
    case Codex = 'codex';
    case V0 = 'v0';
    case AugmentCli = 'augment-cli';
    case Opencode = 'opencode';
    case Amp = 'amp';
    case Copilot = 'copilot';
    case Antigravity = 'antigravity';
    case Pi = 'pi';
    case KiroCli = 'kiro-cli';

    public function label(): string
    {
        return match ($this) {
            self::AugmentCli => 'Augment CLI',
            self::KiroCli => 'Kiro CLI',
            self::V0 => 'v0',
            default => ucfirst($this->value),
        };
    }
}
<?php

declare(strict_types=1);

namespace Laravel\AgentDetector;

function detectAgent(): AgentResult
{
    return AgentDetector::detect();
}
<?php

declare(strict_types=1);

namespace Laravel\AgentDetector;

class AgentDetector
{
    public const AGENT_ENV_VARS = [
        'CURSOR_AGENT' => KnownAgent::Cursor,
        'GEMINI_CLI' => KnownAgent::Gemini,
        'CODEX_SANDBOX' => KnownAgent::Codex,
        'CODEX_CI' => KnownAgent::Codex,
        'CODEX_THREAD_ID' => KnownAgent::Codex,
        'AUGMENT_AGENT' => KnownAgent::AugmentCli,
        'OPENCODE_CLIENT' => KnownAgent::Opencode,
        'OPENCODE' => KnownAgent::Opencode,
        'AMP_CURRENT_THREAD_ID' => KnownAgent::Amp,
        'CLAUDECODE' => KnownAgent::Claude,
        'CLAUDE_CODE' => KnownAgent::Claude,
        'REPL_ID' => KnownAgent::Replit,
        'COPILOT_MODEL' => KnownAgent::Copilot,
        'COPILOT_ALLOW_ALL' => KnownAgent::Copilot,
        'COPILOT_GITHUB_TOKEN' => KnownAgent::Copilot,
        'COPILOT_CLI' => KnownAgent::Copilot,
        'ANTIGRAVITY_AGENT' => KnownAgent::Antigravity,
        'PI_CODING_AGENT' => KnownAgent::Pi,
        'KIRO_AGENT_PATH' => KnownAgent::KiroCli,
    ];

    public static function detect(): AgentResult
    {
        return self::fromAiAgentEnvVar()
            ?? self::fromKnownEnvVars()
            ?? self::fromFileSystem()
            ?? AgentResult::noAgent();
    }

    protected static function fromAiAgentEnvVar(): ?AgentResult
    {
        $aiAgent = getenv('AI_AGENT');

        if ($aiAgent === false) {
            return null;
        }

        $aiAgent = trim($aiAgent);

        if ($aiAgent === '') {
            return null;
        }

        return AgentResult::forAgent(match (true) {
            in_array($aiAgent, ['github-copilot', 'github-copilot-cli']) => KnownAgent::Copilot,
            str_starts_with($aiAgent, 'claude-code') => KnownAgent::Claude,
            default => $aiAgent,
        });
    }

    protected static function fromKnownEnvVars(): ?AgentResult
    {
        foreach (self::AGENT_ENV_VARS as $envVar => $agent) {
            if (getenv($envVar) === false) {
                continue;
            }

            return AgentResult::forAgent(match ($agent) {
                KnownAgent::Claude => getenv('CLAUDE_CODE_IS_COWORK') !== false ? KnownAgent::Cowork : KnownAgent::Claude,
                default => $agent,
            });
        }

        return null;
    }

    protected static function fromFileSystem(): ?AgentResult
    {
        if (file_exists('/opt/.devin')) {
            return AgentResult::forAgent(KnownAgent::Devin);
        }

        return null;
    }
}
<?php

declare(strict_types=1);

namespace Laravel\AgentDetector;

class AgentResult
{
    public readonly bool $isAgent;

    public function __construct(public readonly ?string $name = null)
    {
        $this->isAgent = $name !== null;
    }

    public static function forAgent(KnownAgent|string $name): self
    {
        return new self($name instanceof KnownAgent ? $name->value : $name);
    }

    public static function noAgent(): self
    {
        return new self();
    }

    public function knownAgent(): ?KnownAgent
    {
        return KnownAgent::tryFrom($this->name ?? '');
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;

class SuggestPrompt extends Prompt
{
    use Concerns\HasInfo;
    use Concerns\Scrolling;
    use Concerns\Truncation;
    use Concerns\TypedValue;

    /**
     * The options for the suggest prompt.
     *
     * @var array<string>|Closure(string): (array<string>|Collection<int, string>)
     */
    public array|Closure $options;

    /**
     * The cache of matches.
     *
     * @var array<string>|null
     */
    protected ?array $matches = null;

    /**
     * Create a new SuggestPrompt instance.
     *
     * @param  array<string>|Collection<int, string>|Closure(string): (array<string>|Collection<int, string>)  $options
     */
    public function __construct(
        public string $label,
        array|Collection|Closure $options,
        public string $placeholder = '',
        public string $default = '',
        public int $scroll = 5,
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
        public string|Closure $info = '',
    ) {
        $this->options = $options instanceof Collection ? $options->all() : $options;

        $this->initializeScrolling(null);

        $this->on('key', fn ($key) => match ($key) {
            Key::UP, Key::UP_ARROW, Key::SHIFT_TAB, Key::CTRL_P => $this->highlightPrevious(count($this->matches()), true),
            Key::DOWN, Key::DOWN_ARROW, Key::TAB, Key::CTRL_N => $this->highlightNext(count($this->matches()), true),
            Key::oneOf([Key::HOME, Key::CTRL_A], $key) => $this->highlighted !== null ? $this->highlight(0) : null,
            Key::oneOf([Key::END, Key::CTRL_E], $key) => $this->highlighted !== null ? $this->highlight(count($this->matches()) - 1) : null,
            Key::ENTER => $this->selectHighlighted(),
            Key::oneOf([Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_B, Key::CTRL_F], $key) => $this->highlighted = null,
            default => (function () {
                $this->highlighted = null;
                $this->matches = null;
                $this->firstVisible = 0;
            })(),
        });

        $this->trackTypedValue($default, ignore: fn ($key) => Key::oneOf([Key::HOME, Key::END, Key::CTRL_A, Key::CTRL_E], $key) && $this->highlighted !== null);
    }

    /**
     * Get the value of the highlighted option.
     */
    public function highlightedValue(): ?string
    {
        if ($this->highlighted === null) {
            return null;
        }

        return $this->matches()[$this->highlighted] ?? null;
    }

    /**
     * Get the entered value with a virtual cursor.
     */
    public function valueWithCursor(int $maxWidth): string
    {
        if ($this->highlighted !== null) {
            return $this->value() === ''
                ? $this->dim($this->truncate($this->placeholder, $maxWidth))
                : $this->truncate($this->value(), $maxWidth);
        }

        if ($this->value() === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        return $this->addCursor($this->value(), $this->cursorPosition, $maxWidth);
    }

    /**
     * Get options that match the input.
     *
     * @return array<string>
     */
    public function matches(): array
    {
        if (is_array($this->matches)) {
            return $this->matches;
        }

        if ($this->options instanceof Closure) {
            $matches = ($this->options)($this->value());

            return $this->matches = array_values($matches instanceof Collection ? $matches->all() : $matches);
        }

        return $this->matches = array_values(array_filter($this->options, function ($option) {
            return str_starts_with(strtolower($option), strtolower($this->value()));
        }));
    }

    /**
     * The current visible matches.
     *
     * @return array<string>
     */
    public function visible(): array
    {
        return array_slice($this->matches(), $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Select the highlighted entry.
     */
    protected function selectHighlighted(): void
    {
        if ($this->highlighted === null) {
            return;
        }

        $this->typedValue = $this->matches()[$this->highlighted];
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;

class MultiSelectPrompt extends Prompt
{
    use Concerns\HasInfo;
    use Concerns\Scrolling;

    /**
     * The options for the multi-select prompt.
     *
     * @var array<int|string, string>
     */
    public array $options;

    /**
     * The default values the multi-select prompt.
     *
     * @var array<int|string>
     */
    public array $default;

    /**
     * The selected values.
     *
     * @var array<int|string>
     */
    protected array $values = [];

    /**
     * Create a new MultiSelectPrompt instance.
     *
     * @param  array<int|string, string>|Collection<int|string, string>  $options
     * @param  array<int|string>|Collection<int, int|string>  $default
     */
    public function __construct(
        public string $label,
        array|Collection $options,
        array|Collection $default = [],
        public int $scroll = 5,
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
        public string|Closure $info = '',
    ) {
        $this->options = $options instanceof Collection ? $options->all() : $options;
        $this->default = $default instanceof Collection ? $default->all() : $default;
        $this->values = $this->default;

        $this->initializeScrolling(0);

        $this->on('key', fn ($key) => match ($key) {
            Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, Key::CTRL_P, Key::CTRL_B, 'k', 'h' => $this->highlightPrevious(count($this->options)),
            Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, Key::CTRL_N, Key::CTRL_F, 'j', 'l' => $this->highlightNext(count($this->options)),
            Key::oneOf(Key::HOME, $key) => $this->highlight(0),
            Key::oneOf(Key::END, $key) => $this->highlight(count($this->options) - 1),
            Key::SPACE => $this->toggleHighlighted(),
            Key::CTRL_A => $this->toggleAll(),
            Key::ENTER => $this->submit(),
            default => null,
        });
    }

    /**
     * Get the value of the highlighted option.
     */
    public function highlightedValue(): int|string|null
    {
        if ($this->highlighted === null) {
            return null;
        }

        if (array_is_list($this->options)) {
            return $this->options[$this->highlighted] ?? null;
        }

        return array_keys($this->options)[$this->highlighted] ?? null;
    }

    /**
     * Get the selected values.
     *
     * @return array<int|string>
     */
    public function value(): array
    {
        return array_values($this->values);
    }

    /**
     * Get the selected labels.
     *
     * @return array<string>
     */
    public function labels(): array
    {
        if (array_is_list($this->options)) {
            return array_map(fn ($value) => (string) $value, $this->values);
        }

        return array_values(array_intersect_key($this->options, array_flip($this->values)));
    }

    /**
     * The currently visible options.
     *
     * @return array<int|string, string>
     */
    public function visible(): array
    {
        return array_slice($this->options, $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Check whether the value is currently highlighted.
     */
    public function isHighlighted(string $value): bool
    {
        if (array_is_list($this->options)) {
            return $this->options[$this->highlighted] === $value;
        }

        return array_keys($this->options)[$this->highlighted] === $value;
    }

    /**
     * Check whether the value is currently selected.
     */
    public function isSelected(string $value): bool
    {
        return in_array($value, $this->values);
    }

    /**
     * Toggle all options.
     */
    protected function toggleAll(): void
    {
        if (count($this->values) === count($this->options)) {
            $this->values = [];
        } else {
            $this->values = array_is_list($this->options)
                ? array_values($this->options)
                : array_keys($this->options);
        }
    }

    /**
     * Toggle the highlighted entry.
     */
    protected function toggleHighlighted(): void
    {
        $value = array_is_list($this->options)
            ? $this->options[$this->highlighted]
            : array_keys($this->options)[$this->highlighted];

        if (in_array($value, $this->values)) {
            $this->values = array_filter($this->values, fn ($v) => $v !== $value);
        } else {
            $this->values[] = $value;
        }
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;
use Laravel\Prompts\Exceptions\FormRevertedException;

class FormBuilder
{
    /**
     * Each step that should be executed.
     *
     * @var array<int, FormStep>
     */
    protected array $steps = [];

    /**
     * The responses provided by each step.
     *
     * @var array<mixed>
     */
    protected array $responses = [];

    /**
     * Add a new step.
     */
    public function add(Closure $step, ?string $name = null, bool $ignoreWhenReverting = false): self
    {
        $this->steps[] = new FormStep($step, true, $name, $ignoreWhenReverting);

        return $this;
    }

    /**
     * Add a new conditional step.
     */
    public function addIf(Closure|bool $condition, Closure $step, ?string $name = null, bool $ignoreWhenReverting = false): self
    {
        $this->steps[] = new FormStep($step, $condition, $name, $ignoreWhenReverting);

        return $this;
    }

    /**
     * Run all of the given steps.
     *
     * @return array<mixed>
     */
    public function submit(): array
    {
        $index = 0;
        $wasReverted = false;

        while ($index < count($this->steps)) {
            $step = $this->steps[$index];

            if ($wasReverted && $index > 0 && $step->shouldIgnoreWhenReverting($this->responses)) {
                $index--;

                continue;
            }

            $wasReverted = false;

            $index > 0
                ? Prompt::revertUsing(function () use (&$wasReverted) {
                    $wasReverted = true;
                }) : Prompt::preventReverting();

            try {
                $this->responses[$step->name ?? $index] = $step->run(
                    $this->responses,
                    $this->responses[$step->name ?? $index] ?? null,
                );
            } catch (FormRevertedException) {
                $wasReverted = true;
            }

            $wasReverted ? $index-- : $index++;
        }

        Prompt::preventReverting();

        return $this->responses;
    }

    /**
     * Prompt the user for text input.
     */
    public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(text(...), get_defined_vars());
    }

    /**
     * Prompt the user for multiline text input.
     */
    public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(textarea(...), get_defined_vars());
    }

    /**
     * Prompt the user for input, hiding the value.
     */
    public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(password(...), get_defined_vars());
    }

    /**
     * Prompt the user to select an option.
     *
     * @param  array<int|string, string>|Collection<int|string, string>  $options
     * @param  true|string  $required
     */
    public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(select(...), get_defined_vars());
    }

    /**
     * Prompt the user to select multiple options.
     *
     * @param  array<int|string, string>|Collection<int|string, string>  $options
     * @param  array<int|string>|Collection<int, int|string>  $default
     */
    public function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(multiselect(...), get_defined_vars());
    }

    /**
     * Prompt the user to confirm an action.
     */
    public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(confirm(...), get_defined_vars());
    }

    /**
     * Prompt the user to continue or cancel after pausing.
     */
    public function pause(string $message = 'Press enter to continue...', ?string $name = null): self
    {
        return $this->runPrompt(pause(...), get_defined_vars());
    }

    /**
     * Prompt the user for text input with auto-completion.
     *
     * @param  array<string>|Collection<int, string>|Closure(string): array<string>  $options
     */
    public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(suggest(...), get_defined_vars());
    }

    /**
     * Allow the user to search for an option.
     *
     * @param  Closure(string): array<int|string, string>  $options
     * @param  true|string  $required
     */
    public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(search(...), get_defined_vars());
    }

    /**
     * Allow the user to search for multiple option.
     *
     * @param  Closure(string): array<int|string, string>  $options
     */
    public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self
    {
        return $this->runPrompt(multisearch(...), get_defined_vars());
    }

    /**
     * Render a spinner while the given callback is executing.
     *
     * @param  Closure(): mixed  $callback
     */
    public function spin(Closure $callback, string $message = '', ?string $name = null): self
    {
        return $this->runPrompt(spin(...), get_defined_vars(), true);
    }

    /**
     * Display a note.
     */
    public function note(string $message, ?string $type = null, ?string $name = null): self
    {
        return $this->runPrompt(note(...), get_defined_vars(), true);
    }

    /**
     * Display an error.
     */
    public function error(string $message, ?string $name = null): self
    {
        return $this->runPrompt(error(...), get_defined_vars(), true);
    }

    /**
     * Display a warning.
     */
    public function warning(string $message, ?string $name = null): self
    {
        return $this->runPrompt(warning(...), get_defined_vars(), true);
    }

    /**
     * Display an alert.
     */
    public function alert(string $message, ?string $name = null): self
    {
        return $this->runPrompt(alert(...), get_defined_vars(), true);
    }

    /**
     * Display an informational message.
     */
    public function info(string $message, ?string $name = null): self
    {
        return $this->runPrompt(info(...), get_defined_vars(), true);
    }

    /**
     * Display an introduction.
     */
    public function intro(string $message, ?string $name = null): self
    {
        return $this->runPrompt(intro(...), get_defined_vars(), true);
    }

    /**
     * Display a closing message.
     */
    public function outro(string $message, ?string $name = null): self
    {
        return $this->runPrompt(outro(...), get_defined_vars(), true);
    }

    /**
     * Display a table.
     *
     * @param  array<int, string|array<int, string>>|Collection<int, string|array<int, string>>  $headers
     * @param  array<int, array<int, string>>|Collection<int, array<int, string>>  $rows
     */
    public function table(array|Collection $headers = [], array|Collection|null $rows = null, ?string $name = null): self
    {
        return $this->runPrompt(table(...), get_defined_vars(), true);
    }

    /**
     * Display a progress bar.
     *
     * @template TSteps of iterable<mixed>|int
     * @template TReturn
     *
     * @param  TSteps  $steps
     * @param  ?Closure((TSteps is int ? int : value-of<TSteps>), Progress<TSteps>): TReturn  $callback
     */
    public function progress(string $label, iterable|int $steps, ?Closure $callback = null, string $hint = '', ?string $name = null): self
    {
        return $this->runPrompt(progress(...), get_defined_vars(), true);
    }

    /**
     * Execute the given prompt passing the given arguments.
     *
     * @param  array<mixed>  $arguments
     */
    protected function runPrompt(callable $prompt, array $arguments, bool $ignoreWhenReverting = false): self
    {
        return $this->add(function (array $responses, mixed $previousResponse) use ($prompt, $arguments) {
            unset($arguments['name']);

            if (array_key_exists('default', $arguments) && $previousResponse !== null) {
                $arguments['default'] = $previousResponse;
            }

            return $prompt(...$arguments);
        }, name: $arguments['name'], ignoreWhenReverting: $ignoreWhenReverting);
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use RuntimeException;

class NumberPrompt extends Prompt
{
    use Concerns\TypedValue;

    /**
     * Create a new NumberPrompt instance.
     */
    public function __construct(
        public string $label,
        public string $placeholder = '',
        public string $default = '',
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
        public ?int $min = null,
        public ?int $max = null,
        public ?int $step = null,
    ) {
        $this->trackTypedValue($default);

        $this->step = max(1, $this->step ?? 1);
        $this->min ??= PHP_INT_MIN;
        $this->max ??= PHP_INT_MAX;

        $originalValidate = $this->validate;

        $this->validate = $this->wrapValidation($this->validate);

        $this->on('key', function (string $key) {
            match ($key) {
                Key::UP, Key::UP_ARROW => $this->increaseValue(),
                Key::DOWN, Key::DOWN_ARROW => $this->decreaseValue(),
                default => null,
            };
        });
    }

    protected function wrapValidation(mixed $validate): callable
    {
        return function ($value) use ($validate) {
            if ($value !== '' && ! is_numeric($value)) {
                return 'Must be a number';
            }

            if (is_numeric($value)) {
                if ($value < $this->min) {
                    return 'Must be at least '.$this->min;
                }

                if ($value > $this->max) {
                    return 'Must be less than '.$this->max;
                }
            }

            if (! $validate && ! isset(static::$validateUsing)) {
                return null;
            }

            return match (true) {
                is_callable($validate) => ($validate)($value),
                isset(static::$validateUsing) => (static::$validateUsing)($this),
                default => throw new RuntimeException('The validation logic is missing.'),
            };
        };
    }

    /**
     * Increase the value of the prompt by the step.
     */
    protected function increaseValue(): void
    {
        if ($this->typedValue === '') {
            $this->typedValue = (string) ($this->min === PHP_INT_MIN ? 1 : $this->min);
            $this->cursorPosition++;

            return;
        }

        if (is_numeric($this->typedValue)) {
            $previousValueLength = mb_strlen($this->typedValue);

            $this->typedValue = (string) min($this->max, (int) $this->typedValue + $this->step);

            if (mb_strlen($this->typedValue) > $previousValueLength) {
                $this->cursorPosition++;
            }
        }
    }

    /**
     * Decrease the value of the prompt by the step.
     */
    protected function decreaseValue(): void
    {
        if ($this->typedValue === '') {
            $this->typedValue = (string) ($this->max === PHP_INT_MAX ? 0 : $this->max);
            $this->cursorPosition++;

            return;
        }

        if (is_numeric($this->typedValue)) {
            $previousValueLength = mb_strlen($this->typedValue);

            $this->typedValue = (string) max($this->min, (int) $this->typedValue - $this->step);

            if (mb_strlen($this->typedValue) < $previousValueLength) {
                $this->cursorPosition--;
            }
        }
    }

    public function value(): int|string
    {
        if (is_numeric($this->typedValue)) {
            return (int) $this->typedValue;
        }

        return $this->typedValue;
    }

    /**
     * Get the entered value with a virtual cursor.
     */
    public function valueWithCursor(int $maxWidth): string
    {
        if ($this->value() === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        return $this->addCursor((string) $this->value(), $this->cursorPosition, $maxWidth);
    }
}
<?php

namespace Laravel\Prompts;

class Clear extends Prompt
{
    /**
     * Clear the terminal.
     */
    public function prompt(): bool
    {
        // Fill the previous newline count so subsequent prompts won't add padding.
        static::output()->write(PHP_EOL.PHP_EOL);

        $this->writeDirectly($this->renderTheme());

        return true;
    }

    /**
     * Clear the terminal.
     */
    public function display(): void
    {
        $this->prompt();
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;

class PasswordPrompt extends Prompt
{
    use Concerns\TypedValue;

    /**
     * Create a new PasswordPrompt instance.
     */
    public function __construct(
        public string $label,
        public string $placeholder = '',
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
    ) {
        $this->trackTypedValue();
    }

    /**
     * Get a masked version of the entered value.
     */
    public function masked(): string
    {
        return str_repeat('•', mb_strlen($this->value()));
    }

    /**
     * Get the masked value with a virtual cursor.
     */
    public function maskedWithCursor(int $maxWidth): string
    {
        if ($this->value() === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        return $this->addCursor($this->masked(), $this->cursorPosition, $maxWidth);
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use InvalidArgumentException;
use RuntimeException;
use Throwable;

/**
 * @template TSteps of iterable<mixed>|int
 */
class Progress extends Prompt
{
    /**
     * The current progress bar item count.
     */
    public int $progress = 0;

    /**
     * The total number of steps.
     */
    public int $total = 0;

    /**
     * The original value of pcntl_async_signals
     */
    protected bool $originalAsync;

    /**
     * Create a new ProgressBar instance.
     *
     * @param  TSteps  $steps
     */
    public function __construct(public string $label, public iterable|int $steps, public string $hint = '')
    {
        /** @phpstan-ignore assign.propertyType (PHPStan doesn't parse that we convert from iterable to int in the below match) */
        $this->total = match (true) {
            is_int($this->steps) => $this->steps,
            is_countable($this->steps) => count($this->steps),
            is_iterable($this->steps) => iterator_count($this->steps),
            /** @phpstan-ignore match.unreachable (Technically we shouldn't be able to reach the default as should be int|countable|iterable ) */
            default => throw new InvalidArgumentException('Unable to count steps.'),
        };

        if ($this->total === 0) {
            throw new InvalidArgumentException('Progress bar must have at least one item.');
        }
    }

    /**
     * Map over the steps while rendering the progress bar.
     *
     * @template TReturn
     *
     * @param  Closure((TSteps is int ? int : value-of<TSteps>), $this): TReturn  $callback
     * @return array<TReturn>
     *
     * @throws Throwable
     */
    public function map(Closure $callback): array
    {
        $this->start();

        $result = [];

        try {
            if (is_int($this->steps)) {
                for ($i = 0; $i < $this->steps; $i++) {
                    $result[] = $callback($i, $this);
                    $this->advance();
                }
            } else {
                foreach ($this->steps as $step) {
                    $result[] = $callback($step, $this);
                    $this->advance();
                }
            }
        } catch (Throwable $e) {
            $this->state = 'error';
            $this->render();
            $this->restoreCursor();
            $this->resetSignals();

            throw $e;
        }

        if ($this->hint !== '') {
            // Just pause for one moment to show the final hint
            // so it doesn't look like it was skipped
            usleep(250_000);
        }

        $this->finish();

        return $result;
    }

    /**
     * Start the progress bar.
     */
    public function start(): void
    {
        $this->capturePreviousNewLines();

        if (function_exists('pcntl_signal')) {
            $this->originalAsync = pcntl_async_signals(true);
            pcntl_signal(SIGINT, function () {
                $this->state = 'cancel';
                $this->render();
                exit();
            });
        }

        $this->hideCursor();
        $this->render();
        $this->state = 'active';
    }

    /**
     * Advance the progress bar.
     */
    public function advance(int $step = 1): void
    {
        $this->progress += $step;

        if ($this->progress > $this->total) {
            $this->progress = $this->total;
        }

        $this->render();
    }

    /**
     * Finish the progress bar.
     */
    public function finish(): void
    {
        $this->state = 'submit';
        $this->render();
        $this->restoreCursor();
        $this->resetSignals();
    }

    /**
     * Force the progress bar to re-render.
     */
    public function render(): void
    {
        parent::render();
    }

    /**
     * Update the label.
     */
    public function label(string $label): static
    {
        $this->label = $label;

        return $this;
    }

    /**
     * Update the hint.
     */
    public function hint(string $hint): static
    {
        $this->hint = $hint;

        return $this;
    }

    /**
     * Get the completion percentage.
     */
    public function percentage(): int|float
    {
        return $this->progress / $this->total;
    }

    /**
     * Disable prompting for input.
     *
     * @throws RuntimeException
     */
    public function prompt(): never
    {
        throw new RuntimeException('Progress Bar cannot be prompted.');
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }

    /**
     * Reset the signal handling.
     */
    protected function resetSignals(): void
    {
        if (isset($this->originalAsync)) {
            pcntl_async_signals($this->originalAsync);
            pcntl_signal(SIGINT, SIG_DFL);
        }
    }

    /**
     * Restore the cursor.
     */
    public function __destruct()
    {
        $this->restoreCursor();
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\NumberPrompt;

class NumberPromptRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    protected string $upArrow = '▲';

    protected string $downArrow = '▼';

    /**
     * Render the number prompt.
     */
    public function __invoke(NumberPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate((string) $prompt->value(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->strikethrough($this->dim($this->truncate((string) $prompt->value() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error('Cancelled.'),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth), 'yellow'),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->withArrows($prompt, $prompt->valueWithCursor($maxWidth)),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
        };
    }

    protected function withArrows(NumberPrompt $prompt, int|string $value, ?string $color = null): string
    {
        $arrows = $this->getArrows($prompt, $color);
        $valueLength = mb_strwidth($this->stripEscapeSequences((string) $value));
        $padding = $this->minWidth - $valueLength - mb_strwidth($this->stripEscapeSequences($arrows));

        return $value.str_repeat(' ', $padding).$arrows;
    }

    protected function getArrows(NumberPrompt $prompt, ?string $color = null): string
    {
        $upArrow = $this->upArrow;
        $downArrow = $this->downArrow;

        if ($color) {
            $upArrow = $this->{$color}($upArrow);
            $downArrow = $this->{$color}($downArrow);
        }

        if (is_numeric($prompt->value())) {
            if ((int) $prompt->value() === $prompt->min) {
                $downArrow = $this->dim($downArrow);
            }

            if ((int) $prompt->value() === $prompt->max) {
                $upArrow = $this->dim($upArrow);
            }

            return $upArrow.$downArrow;
        }

        if ($prompt->value() === '') {
            return $upArrow.$downArrow;
        }

        return $this->dim($upArrow).$this->dim($downArrow);
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Output\BufferedConsoleOutput;
use Laravel\Prompts\Table;
use Symfony\Component\Console\Helper\Table as SymfonyTable;
use Symfony\Component\Console\Helper\TableStyle;

class TableRenderer extends Renderer
{
    /**
     * Render the table.
     */
    public function __invoke(Table $table): string
    {
        $tableStyle = (new TableStyle)
            ->setHorizontalBorderChars('─')
            ->setVerticalBorderChars('│', '│')
            ->setCellHeaderFormat($this->dim('<fg=default>%s</>'))
            ->setCellRowFormat('<fg=default>%s</>');

        if (empty($table->headers)) {
            $tableStyle->setCrossingChars('┼', '', '', '', '┤', '┘</>', '┴', '└', '├', '<fg=gray>┌', '┬', '┐');
        } else {
            $tableStyle->setCrossingChars('┼', '<fg=gray>┌', '┬', '┐', '┤', '┘</>', '┴', '└', '├');
        }

        $buffered = new BufferedConsoleOutput;

        (new SymfonyTable($buffered))
            ->setHeaders($table->headers)
            ->setRows($table->rows)
            ->setStyle($tableStyle)
            ->render();

        foreach (explode(PHP_EOL, trim($buffered->content(), PHP_EOL)) as $line) {
            $this->line(' '.$line);
        }

        return $this;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Stream;

class StreamRenderer extends Renderer
{
    /**
     * Render the stream.
     */
    public function __invoke(Stream $stream): string
    {
        foreach ($stream->lines() as $line) {
            $this->line(" {$line}");
        }

        return $this;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\TextPrompt;

class TextPromptRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    /**
     * Render the text prompt.
     */
    public function __invoke(TextPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate($prompt->value(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $prompt->valueWithCursor($maxWidth),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $prompt->valueWithCursor($maxWidth),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
        };
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Concerns\HasSpinner;
use Laravel\Prompts\Task;

class TaskRenderer extends Renderer
{
    use HasSpinner;

    /**
     * Render the task.
     */
    public function __invoke(Task $task): string
    {
        $maxWidth = $task->terminal()->cols() - 6;
        $labelMaxWidth = $maxWidth - 3;
        $leadPadding = str_repeat(' ', 3);
        $stableLineMaxWidth = $maxWidth - strlen($leadPadding) - 2; // symbol + space

        if ($task->static) {
            return $this->line(" {$this->cyan($this->staticFrame)} {$this->truncate($task->label, $maxWidth)}");
        }

        $task->interval = $this->interval;

        $stableMessages = array_slice($task->stableMessages, -$task->maxStableMessages);

        if ($task->finished && $task->keepSummary && count($stableMessages) > 0) {
            $this->line(" {$this->cyan('•')} {$this->truncate($task->label, $labelMaxWidth)}");

            foreach ($stableMessages as $stableMessage) {
                $this->line($leadPadding.$this->stableMessageSymbol($stableMessage['type']).' '.$this->truncate($stableMessage['message'], $stableLineMaxWidth));
            }

            $this->newLine();

            return $this;
        }

        $this->line(" {$this->cyan($this->spinnerFrame($task->count))} {$this->truncate($task->label, $labelMaxWidth)}");

        if ($task->subLabel !== null && $task->subLabel !== '') {
            $this->line($leadPadding.$this->dim($this->truncate($task->subLabel, $stableLineMaxWidth)));
        }

        foreach ($stableMessages as $stableMessage) {
            $this->line($leadPadding.$this->stableMessageSymbol($stableMessage['type']).' '.$this->truncate($stableMessage['message'], $stableLineMaxWidth));
        }

        if (count($task->stableMessages) > 0 || count($task->logs) > 0) {
            $this->line($this->gray(' '.str_repeat('─', $maxWidth)));
        } else {
            $this->newLine();
        }

        $logs = array_slice($task->logs, -$task->limit);

        foreach ($logs as $log) {
            $this->line(' '.$this->dim($log));
        }

        $remaining = $task->limit - count($task->logs);

        while ($remaining > 0) {
            $this->line('');
            $remaining--;
        }

        return $this;
    }

    protected function stableMessageSymbol(string $type): string
    {
        return match ($type) {
            'success' => $this->green('✔'),
            'error' => $this->red('✘'),
            'warning' => $this->yellow('⚠'),
            default => '',
        };
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Concerns\HasSpinner;
use Laravel\Prompts\Spinner;

class SpinnerRenderer extends Renderer
{
    use HasSpinner;

    /**
     * Render the spinner.
     */
    public function __invoke(Spinner $spinner): string
    {
        if ($spinner->static) {
            return $this->line(" {$this->cyan($this->staticFrame)} {$spinner->message}");
        }

        $spinner->interval = $this->interval;

        return $this->line(" {$this->cyan($this->spinnerFrame($spinner->count))} {$spinner->message}");
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\ConfirmPrompt;

class ConfirmPromptRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    /**
     * Render the confirm prompt.
     */
    public function __invoke(ConfirmPrompt $prompt): string
    {
        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate($prompt->label(), $prompt->terminal()->cols() - 6)
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->renderOptions($prompt),
                    color: 'red'
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->renderOptions($prompt),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->renderOptions($prompt),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                ),
        };
    }

    /**
     * Render the confirm prompt options.
     */
    protected function renderOptions(ConfirmPrompt $prompt): string
    {
        $length = (int) floor(($prompt->terminal()->cols() - 14) / 2);
        $yes = $this->truncate($prompt->yes, $length);
        $no = $this->truncate($prompt->no, $length);

        if ($prompt->state === 'cancel') {
            return $this->dim($prompt->confirmed
                ? "● {$this->strikethrough($yes)} / ○ {$this->strikethrough($no)}"
                : "○ {$this->strikethrough($yes)} / ● {$this->strikethrough($no)}");
        }

        return $prompt->confirmed
            ? "{$this->green('●')} {$yes} {$this->dim('/ ○ '.$no)}"
            : "{$this->dim('○ '.$yes.' /')} {$this->green('●')} {$no}";
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

class ClearRenderer extends Renderer
{
    /**
     * Clear the terminal.
     */
    public function __invoke(): string
    {
        return "\033[H\033[J";
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Concerns\Colors;
use Laravel\Prompts\Concerns\Truncation;
use Laravel\Prompts\Prompt;

abstract class Renderer
{
    use Colors;
    use Truncation;

    /**
     * The output to be rendered.
     */
    protected string $output = '';

    /**
     * Create a new renderer instance.
     */
    public function __construct(protected Prompt $prompt)
    {
        //
    }

    /**
     * Render a line of output.
     */
    protected function line(string $message): self
    {
        $this->output .= $message.PHP_EOL;

        return $this;
    }

    /**
     * Render a new line.
     */
    protected function newLine(int $count = 1): self
    {
        $this->output .= str_repeat(PHP_EOL, $count);

        return $this;
    }

    /**
     * Render a warning message.
     */
    protected function warning(string $message): self
    {
        return $this->line($this->yellow("  ⚠ {$message}"));
    }

    /**
     * Render an error message.
     */
    protected function error(string $message): self
    {
        return $this->line($this->red("  ⚠ {$message}"));
    }

    /**
     * Render an hint message.
     */
    protected function hint(string $message): self
    {
        if ($message === '') {
            return $this;
        }

        $message = $this->truncate($message, $this->prompt->terminal()->cols() - 6);

        return $this->line($this->gray("  {$message}"));
    }

    /**
     * Apply the callback if the given "value" is truthy.
     *
     * @return $this
     */
    protected function when(mixed $value, callable $callback, ?callable $default = null): self
    {
        if ($value) {
            $callback($this);
        } elseif ($default) {
            $default($this);
        }

        return $this;
    }

    /**
     * Render the output with a blank line above and below.
     */
    public function __toString()
    {
        return str_repeat(PHP_EOL, max(2 - $this->prompt->newLinesWritten(), 0))
            .$this->output
            .(in_array($this->prompt->state, ['submit', 'cancel']) ? PHP_EOL : '');
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\SuggestPrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;

class SuggestPromptRenderer extends Renderer implements Scrolling
{
    use Concerns\DrawsBoxes;
    use Concerns\DrawsScrollbars;

    /**
     * Render the suggest prompt.
     */
    public function __invoke(SuggestPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate($prompt->value(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->valueWithCursorAndArrow($prompt, $maxWidth),
                    $this->renderOptions($prompt),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->valueWithCursorAndArrow($prompt, $maxWidth),
                    $this->renderOptions($prompt),
                    info: $prompt->infoText(),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
                ->spaceForDropdown($prompt),
        };
    }

    /**
     * Render the value with the cursor and an arrow.
     */
    protected function valueWithCursorAndArrow(SuggestPrompt $prompt, int $maxWidth): string
    {
        if ($prompt->highlighted !== null || $prompt->value() !== '' || count($prompt->matches()) === 0) {
            return $prompt->valueWithCursor($maxWidth);
        }

        return preg_replace(
            '/\s$/',
            $this->cyan('⌄'),
            $this->pad($prompt->valueWithCursor($maxWidth - 1).'  ', min($this->longest($prompt->matches(), padding: 2), $maxWidth))
        );
    }

    /**
     * Render a spacer to prevent jumping when the suggestions are displayed.
     */
    protected function spaceForDropdown(SuggestPrompt $prompt): self
    {
        if ($prompt->value() === '' && $prompt->highlighted === null) {
            $this->newLine(min(
                count($prompt->matches()),
                $prompt->scroll,
                $prompt->terminal()->lines() - 7
            ) + 1);
        }

        return $this;
    }

    /**
     * Render the options.
     */
    protected function renderOptions(SuggestPrompt $prompt): string
    {
        if (empty($prompt->matches()) || ($prompt->value() === '' && $prompt->highlighted === null)) {
            return '';
        }

        return implode(PHP_EOL, $this->scrollbar(
            array_map(function ($label, $key) use ($prompt) {
                $label = $this->truncate($label, $prompt->terminal()->cols() - 12);

                return $prompt->highlighted === $key
                    ? "{$this->cyan('›')} {$label}  "
                    : "  {$this->dim($label)}  ";
            }, $visible = $prompt->visible(), array_keys($visible)),
            $prompt->firstVisible,
            $prompt->scroll,
            count($prompt->matches()),
            min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6),
            $prompt->state === 'cancel' ? 'dim' : 'cyan'
        ));
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 7;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\AutoCompletePrompt;

class AutoCompletePromptRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    /**
     * Render the text prompt.
     */
    public function __invoke(AutoCompletePrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate($prompt->value(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->strikethrough($this->dim($this->truncate($prompt->value() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $prompt->valueWithCursor($maxWidth),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $prompt->valueWithCursor($maxWidth),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
        };
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\TextareaPrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;

class TextareaPromptRenderer extends Renderer implements Scrolling
{
    use Concerns\DrawsBoxes;
    use Concerns\DrawsScrollbars;

    /**
     * Render the textarea prompt.
     */
    public function __invoke(TextareaPrompt $prompt): string
    {
        $prompt->width = $prompt->terminal()->cols() - 8;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->width)),
                    implode(PHP_EOL, $prompt->lines()),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->width),
                    implode(PHP_EOL, array_map(fn ($line) => $this->strikethrough($this->dim($line)), $prompt->lines())),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->width),
                    $this->renderText($prompt),
                    color: 'yellow',
                    info: 'Ctrl+D to submit'
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->width)),
                    $this->renderText($prompt),
                    info: 'Ctrl+D to submit'
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
        };
    }

    /**
     * Render the text in the prompt.
     */
    protected function renderText(TextareaPrompt $prompt): string
    {
        $visible = $prompt->visible();

        while (count($visible) < $prompt->scroll) {
            $visible[] = '';
        }

        $longest = $this->longest($prompt->lines()) + 2;

        return implode(PHP_EOL, $this->scrollbar(
            $visible,
            $prompt->firstVisible,
            $prompt->scroll,
            count($prompt->lines()),
            min($longest, $prompt->width + 2),
        ));
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 5;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\MultiSearchPrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;

class MultiSearchPromptRenderer extends Renderer implements Scrolling
{
    use Concerns\DrawsBoxes;
    use Concerns\DrawsScrollbars;

    /**
     * Render the suggest prompt.
     */
    public function __invoke(MultiSearchPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->renderSelectedOptions($prompt),
                ),

            'cancel' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $prompt->valueWithCursor($maxWidth),
                    $this->renderOptions($prompt),
                    color: 'yellow',
                    info: $this->getInfoText($prompt),
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            'searching' => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->valueWithCursorAndSearchIcon($prompt, $maxWidth),
                    $this->renderOptions($prompt),
                    info: $this->getInfoText($prompt),
                )
                ->hint($prompt->hint),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $prompt->valueWithCursor($maxWidth),
                    $this->renderOptions($prompt),
                    info: $this->getInfoText($prompt),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
                ->spaceForDropdown($prompt)
        };
    }

    /**
     * Render the value with the cursor and a search icon.
     */
    protected function valueWithCursorAndSearchIcon(MultiSearchPrompt $prompt, int $maxWidth): string
    {
        return preg_replace(
            '/\s$/',
            $this->cyan('…'),
            $this->pad($prompt->valueWithCursor($maxWidth - 1).'  ', min($this->longest($prompt->matches(), padding: 2), $maxWidth))
        );
    }

    /**
     * Render a spacer to prevent jumping when the suggestions are displayed.
     */
    protected function spaceForDropdown(MultiSearchPrompt $prompt): self
    {
        if ($prompt->searchValue() !== '') {
            return $this;
        }

        $this->newLine(max(
            0,
            min($prompt->scroll, $prompt->terminal()->lines() - 7) - count($prompt->matches()),
        ));

        if ($prompt->matches() === []) {
            $this->newLine();
        }

        return $this;
    }

    /**
     * Render the options.
     */
    protected function renderOptions(MultiSearchPrompt $prompt): string
    {
        if ($prompt->searchValue() !== '' && empty($prompt->matches())) {
            return $this->gray('  '.($prompt->state === 'searching' ? 'Searching...' : 'No results.'));
        }

        return implode(PHP_EOL, $this->scrollbar(
            array_map(function ($label, $key) use ($prompt) {
                $label = $this->truncate($label, $prompt->terminal()->cols() - 12);

                $index = array_search($key, array_keys($prompt->matches()));
                $active = $index === $prompt->highlighted;
                $selected = $prompt->isList()
                    ? in_array($label, $prompt->value())
                    : in_array($key, $prompt->value());

                return match (true) {
                    $active && $selected => "{$this->cyan('› ◼')} {$label}  ",
                    $active => "{$this->cyan('›')} ◻ {$label}  ",
                    $selected => "  {$this->cyan('◼')} {$this->dim($label)}  ",
                    default => "  {$this->dim('◻')} {$this->dim($label)}  ",
                };
            }, $prompt->visible(), array_keys($prompt->visible())),
            $prompt->firstVisible,
            $prompt->scroll,
            count($prompt->matches()),
            min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6)
        ));
    }

    /**
     * Render the selected options.
     */
    protected function renderSelectedOptions(MultiSearchPrompt $prompt): string
    {
        if (count($prompt->labels()) === 0) {
            return $this->gray('None');
        }

        return implode("\n", array_map(
            fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 6),
            $prompt->labels()
        ));
    }

    /**
     * Render the info text.
     */
    protected function getInfoText(MultiSearchPrompt $prompt): string
    {
        $selected = count($prompt->value()).' selected';

        $hiddenCount = count($prompt->value()) - count(array_filter(
            $prompt->matches(),
            fn ($label, $key) => in_array($prompt->isList() ? $label : $key, $prompt->value()),
            ARRAY_FILTER_USE_BOTH
        ));

        if ($hiddenCount > 0) {
            $selected .= " ($hiddenCount hidden)";
        }

        $parts = array_filter([$prompt->infoText(), $selected]);

        return implode(' · ', $parts);
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 7;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Note;

class NoteRenderer extends Renderer
{
    /**
     * Render the note.
     */
    public function __invoke(Note $note): string
    {
        $lines = explode(PHP_EOL, $note->message);

        switch ($note->type) {
            case 'intro':
            case 'outro':
                $lines = array_map(fn ($line) => " {$line} ", $lines);
                $longest = max(array_map(fn ($line) => mb_strlen($line), $lines));

                foreach ($lines as $line) {
                    $line = mb_str_pad($line, $longest, ' ');
                    $this->line(" {$this->bgCyan($this->black($line))}");
                }

                return $this;

            case 'warning':
                foreach ($lines as $line) {
                    $this->line($this->yellow(" {$line}"));
                }

                return $this;

            case 'error':
                foreach ($lines as $line) {
                    $this->line($this->red(" {$line}"));
                }

                return $this;

            case 'alert':
                foreach ($lines as $line) {
                    $this->line(" {$this->bgRed($this->white(" {$line} "))}");
                }

                return $this;

            case 'info':
                foreach ($lines as $line) {
                    $this->line($this->green(" {$line}"));
                }

                return $this;

            default:
                foreach ($lines as $line) {
                    $this->line(" {$line}");
                }

                return $this;
        }
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\SearchPrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;

class SearchPromptRenderer extends Renderer implements Scrolling
{
    use Concerns\DrawsBoxes;
    use Concerns\DrawsScrollbars;

    /**
     * Render the suggest prompt.
     */
    public function __invoke(SearchPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate($prompt->label(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->strikethrough($this->dim($this->truncate($prompt->searchValue() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $prompt->valueWithCursor($maxWidth),
                    $this->renderOptions($prompt),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            'searching' => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->valueWithCursorAndSearchIcon($prompt, $maxWidth),
                    $this->renderOptions($prompt),
                    info: $prompt->infoText(),
                )
                ->hint($prompt->hint),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $prompt->valueWithCursor($maxWidth),
                    $this->renderOptions($prompt),
                    info: $prompt->infoText(),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                )
                ->spaceForDropdown($prompt)
        };
    }

    /**
     * Render the value with the cursor and a search icon.
     */
    protected function valueWithCursorAndSearchIcon(SearchPrompt $prompt, int $maxWidth): string
    {
        return preg_replace(
            '/\s$/',
            $this->cyan('…'),
            $this->pad($prompt->valueWithCursor($maxWidth - 1).'  ', min($this->longest($prompt->matches(), padding: 2), $maxWidth))
        );
    }

    /**
     * Render a spacer to prevent jumping when the suggestions are displayed.
     */
    protected function spaceForDropdown(SearchPrompt $prompt): self
    {
        if ($prompt->searchValue() !== '') {
            return $this;
        }

        $this->newLine(max(
            0,
            min($prompt->scroll, $prompt->terminal()->lines() - 7) - count($prompt->matches()),
        ));

        if ($prompt->matches() === []) {
            $this->newLine();
        }

        return $this;
    }

    /**
     * Render the options.
     */
    protected function renderOptions(SearchPrompt $prompt): string
    {
        if ($prompt->searchValue() !== '' && empty($prompt->matches())) {
            return $this->gray('  '.($prompt->state === 'searching' ? 'Searching...' : 'No results.'));
        }

        return implode(PHP_EOL, $this->scrollbar(
            array_values(array_map(function ($label, $key) use ($prompt) {
                $label = $this->truncate($label, $prompt->terminal()->cols() - 10);

                $index = array_search($key, array_keys($prompt->matches()));

                return $prompt->highlighted === $index
                    ? "{$this->cyan('›')} {$label}  "
                    : "  {$this->dim($label)}  ";
            }, $visible = $prompt->visible(), array_keys($visible))),
            $prompt->firstVisible,
            $prompt->scroll,
            count($prompt->matches()),
            min($this->longest($prompt->matches(), padding: 4), $prompt->terminal()->cols() - 6)
        ));
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 7;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Progress;

class ProgressRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    /**
     * The character to use for the progress bar.
     */
    protected string $barCharacter = '█';

    /**
     * Render the progress bar.
     *
     * @param  Progress<int|iterable<mixed>>  $progress
     */
    public function __invoke(Progress $progress): string
    {
        $filled = str_repeat($this->barCharacter, (int) ceil($progress->percentage() * min($this->minWidth, $progress->terminal()->cols() - 6)));

        return match ($progress->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($progress->label, $progress->terminal()->cols() - 6)),
                    $this->dim($filled),
                    info: $this->fractionCompleted($progress),
                ),

            'error' => $this
                ->box(
                    $this->truncate($progress->label, $progress->terminal()->cols() - 6),
                    $this->dim($filled),
                    color: 'red',
                    info: $this->fractionCompleted($progress),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($progress->label, $progress->terminal()->cols() - 6),
                    $this->dim($filled),
                    color: 'red',
                    info: $this->fractionCompleted($progress),
                )
                ->error($progress->cancelMessage),

            default => $this
                ->box(
                    $this->cyan($this->truncate($progress->label, $progress->terminal()->cols() - 6)),
                    $this->dim($filled),
                    info: $this->fractionCompleted($progress),
                )
                ->when(
                    $progress->hint,
                    fn () => $this->hint($progress->hint),
                    fn () => $this->newLine() // Space for errors
                )
        };
    }

    /**
     * @param  Progress<int|iterable<mixed>>  $progress
     */
    protected function fractionCompleted(Progress $progress): string
    {
        return number_format($progress->progress).' / '.number_format($progress->total);
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\PausePrompt;

class PausePromptRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    /**
     * Render the pause prompt.
     */
    public function __invoke(PausePrompt $prompt): string
    {
        $lines = explode(PHP_EOL, $prompt->message);

        $color = $prompt->state === 'submit' ? 'green' : 'gray';

        foreach ($lines as $line) {
            $this->line(" {$this->{$color}($line)}");
        }

        return $this;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Grid;
use Laravel\Prompts\Output\BufferedConsoleOutput;
use Symfony\Component\Console\Helper\Table as SymfonyTable;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Helper\TableStyle;

class GridRenderer extends Renderer
{
    use Concerns\InteractsWithStrings;

    protected int $minWidth = 60;

    /**
     * Render the grid.
     */
    public function __invoke(Grid $grid): string
    {
        if (empty($grid->items)) {
            return $this;
        }

        $maxWidth = $grid->maxWidth - 2;
        $cellWidth = max(array_map(fn ($item) => mb_strwidth($this->stripEscapeSequences($item)), $grid->items)) + 4;
        $maxColumns = max(1, (int) floor(($maxWidth - 1) / ($cellWidth + 1)));
        $columnCount = max(1, $this->balancedColumnCount(count($grid->items), $maxColumns));

        $rows = $this->buildRowsWithSeparators($grid->items, $columnCount);

        $tableStyle = (new TableStyle)
            ->setHorizontalBorderChars('─')
            ->setVerticalBorderChars('│', '│')
            ->setCellRowFormat('<fg=default>%s</>')
            ->setCrossingChars('┼', '', '', '', '┤', '┘', '┴', '└', '├', '┌', '┬', '┐');

        $buffered = new BufferedConsoleOutput;

        (new SymfonyTable($buffered))
            ->setRows($rows)
            ->setStyle($tableStyle)
            ->render();

        foreach (explode(PHP_EOL, trim($buffered->content(), PHP_EOL)) as $line) {
            $this->line(' '.$line);
        }

        return $this;
    }

    /**
     * Calculate a balanced column count for even row distribution.
     */
    protected function balancedColumnCount(int $itemCount, int $maxColumns): int
    {
        if ($itemCount <= $maxColumns) {
            return $itemCount;
        }

        for ($cols = $maxColumns; $cols >= 1; $cols--) {
            $remainder = $itemCount % $cols;

            if ($remainder === 0 || $remainder >= (int) ceil($cols / 2)) {
                return $cols;
            }
        }

        return $maxColumns;
    }

    /**
     * Build rows with separators between them.
     *
     * @param  array<int, string>  $items
     * @param  int<1, max>  $columnCount
     * @return array<int, array<int, string>|TableSeparator>
     */
    protected function buildRowsWithSeparators(array $items, int $columnCount): array
    {
        $chunks = array_chunk($items, $columnCount);
        $rows = [];

        foreach ($chunks as $index => $chunk) {
            if ($index > 0) {
                $rows[] = new TableSeparator;
            }

            $rows[] = array_pad($chunk, $columnCount, '');
        }

        return $rows;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\SelectPrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;

class SelectPromptRenderer extends Renderer implements Scrolling
{
    use Concerns\DrawsBoxes;
    use Concerns\DrawsScrollbars;

    /**
     * Render the select prompt.
     */
    public function __invoke(SelectPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->truncate($prompt->label(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->renderOptions($prompt),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->renderOptions($prompt),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->renderOptions($prompt),
                    info: $prompt->infoText(),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                ),
        };
    }

    /**
     * Render the options.
     */
    protected function renderOptions(SelectPrompt $prompt): string
    {
        return implode(PHP_EOL, $this->scrollbar(
            array_values(array_map(function ($label, $key) use ($prompt) {
                $label = $this->truncate($label, $prompt->terminal()->cols() - 12);

                $index = array_search($key, array_keys($prompt->options));

                if ($prompt->state === 'cancel') {
                    return $this->dim($prompt->highlighted === $index
                        ? "› ● {$this->strikethrough($label)}  "
                        : "  ○ {$this->strikethrough($label)}  "
                    );
                }

                return $prompt->highlighted === $index
                    ? "{$this->cyan('›')} {$this->cyan('●')} {$label}  "
                    : "  {$this->dim('○')} {$this->dim($label)}  ";
            }, $visible = $prompt->visible(), array_keys($visible))),
            $prompt->firstVisible,
            $prompt->scroll,
            count($prompt->options),
            min($this->longest($prompt->options, padding: 6), $prompt->terminal()->cols() - 6),
            $prompt->state === 'cancel' ? 'dim' : 'cyan'
        ));
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 5;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default\Concerns;

use Laravel\Prompts\Prompt;

trait DrawsBoxes
{
    use InteractsWithStrings;

    protected int $minWidth = 60;

    /**
     * Draw a box.
     *
     * @return $this
     */
    protected function box(
        string $title,
        string $body,
        string $footer = '',
        string $color = 'gray',
        string $info = '',
    ): self {
        $this->minWidth = min($this->minWidth, Prompt::terminal()->cols() - 6);

        $bodyLines = explode(PHP_EOL, $body);
        $footerLines = array_filter(explode(PHP_EOL, $footer));

        $width = $this->longest(array_merge($bodyLines, $footerLines, [$title]));

        $titleLength = mb_strwidth($this->stripEscapeSequences($title));
        $titleLabel = $titleLength > 0 ? " {$title} " : '';
        $topBorder = str_repeat('─', $width - $titleLength + ($titleLength > 0 ? 0 : 2));

        $this->line("{$this->{$color}(' ┌')}{$titleLabel}{$this->{$color}($topBorder.'┐')}");

        foreach ($bodyLines as $line) {
            $this->line("{$this->{$color}(' │')} {$this->pad($line, $width)} {$this->{$color}('│')}");
        }

        if (count($footerLines) > 0) {
            $this->line($this->{$color}(' ├'.str_repeat('─', $width + 2).'┤'));

            foreach ($footerLines as $line) {
                $this->line("{$this->{$color}(' │')} {$this->pad($line, $width)} {$this->{$color}('│')}");
            }
        }

        if ($info) {
            $info = $this->truncate($info, $width - 1);
        }

        $this->line($this->{$color}(' └'.str_repeat(
            '─', $info ? ($width - mb_strwidth($this->stripEscapeSequences($info))) : ($width + 2)
        ).($info ? " {$info} " : '').'┘'));

        return $this;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default\Concerns;

trait InteractsWithStrings
{
    /**
     * Get the length of the longest line.
     *
     * @param  array<string>  $lines
     */
    protected function longest(array $lines, int $padding = 0): int
    {
        return max(
            $this->minWidth,
            count($lines) > 0 ? max(array_map(fn ($line) => mb_strwidth($this->stripEscapeSequences($line)) + $padding, $lines)) : null
        );
    }

    /**
     * Pad text ignoring ANSI escape sequences.
     */
    protected function pad(string $text, int $length, string $char = ' '): string
    {
        $rightPadding = str_repeat($char, max(0, $length - mb_strwidth($this->stripEscapeSequences($text))));

        return "{$text}{$rightPadding}";
    }

    /**
     * Strip ANSI escape sequences from the given text.
     */
    protected function stripEscapeSequences(string $text): string
    {
        // Strip ANSI escape sequences.
        $text = preg_replace("/\e[^m]*m/", '', $text);

        // Strip Symfony named style tags.
        $text = preg_replace("/<(info|comment|question|error)>(.*?)<\/\\1>/", '$2', $text);

        // Strip Symfony inline style tags.
        return preg_replace("/<(?:(?:[fb]g|options)=[a-z,;]+)+>(.*?)<\/>/i", '$1', $text);
    }

    /**
     * Multi-byte version of wordwrap.
     *
     * @param  non-empty-string  $break
     */
    protected function mbWordwrap(
        string $string,
        int $width = 75,
        string $break = "\n",
        bool $cut_long_words = false
    ): string {
        $lines = explode($break, $string);
        $result = [];

        foreach ($lines as $originalLine) {
            if (mb_strwidth($originalLine) <= $width) {
                $result[] = $originalLine;

                continue;
            }

            $words = explode(' ', $originalLine);
            $line = null;
            $lineWidth = 0;

            if ($cut_long_words) {
                foreach ($words as $index => $word) {
                    $characters = mb_str_split($word);
                    $strings = [];
                    $str = '';

                    foreach ($characters as $character) {
                        $tmp = $str.$character;

                        if (mb_strwidth($tmp) > $width) {
                            $strings[] = $str;
                            $str = $character;
                        } else {
                            $str = $tmp;
                        }
                    }

                    if ($str !== '') {
                        $strings[] = $str;
                    }

                    $words[$index] = implode(' ', $strings);
                }

                $words = explode(' ', implode(' ', $words));
            }

            foreach ($words as $word) {
                $tmp = ($line === null) ? $word : $line.' '.$word;

                // Look for zero-width joiner characters (combined emojis)
                preg_match('/\p{Cf}/u', $word, $joinerMatches);

                $wordWidth = count($joinerMatches) > 0 ? 2 : mb_strwidth($word);

                $lineWidth += $wordWidth;

                if ($line !== null) {
                    // Space between words
                    $lineWidth += 1;
                }

                if ($lineWidth <= $width) {
                    $line = $tmp;
                } else {
                    $result[] = $line;
                    $line = $word;
                    $lineWidth = $wordWidth;
                }
            }

            if ($line !== '') {
                $result[] = $line;
            }

            $line = null;
        }

        return implode($break, $result);
    }

    /**
     * Word wrap text while preserving ANSI escape sequences.
     *
     * @return array<int, string>
     */
    protected function ansiWordwrap(string $text, int $width): array
    {
        // Parse segments and build character array with codes
        $segments = $this->parseAnsiText($text);
        $plainText = $this->stripEscapeSequences($text);
        $chars = [];

        foreach ($segments as $segment) {
            $segmentChars = mb_str_split($segment['text']);

            foreach ($segmentChars as $char) {
                $chars[] = ['char' => $char, 'codes' => $segment['codes']];
            }
        }

        // Word wrap the plain text
        $wrappedLines = $this->mbWordwrap($plainText, $width, "\n", false);
        $plainLines = explode("\n", $wrappedLines);

        // Rebuild each wrapped line with ANSI codes
        $result = [];
        $charIndex = 0;

        foreach ($plainLines as $plainLine) {
            $line = '';
            $lastCodes = '';
            $lineChars = mb_str_split($plainLine);

            foreach ($lineChars as $lineChar) {
                // Find matching character in original (handling spaces removed by wordwrap)
                while ($charIndex < count($chars) && $chars[$charIndex]['char'] !== $lineChar) {
                    // Skip spaces that wordwrap removed
                    if ($chars[$charIndex]['char'] === ' ') {
                        $charIndex++;
                    } else {
                        break;
                    }
                }

                if ($charIndex < count($chars)) {
                    $codes = $chars[$charIndex]['codes'];

                    if ($codes !== $lastCodes) {
                        if ($lastCodes !== '') {
                            $line .= "\e[0m";
                        }

                        if ($codes !== '') {
                            $line .= $codes;
                        }

                        $lastCodes = $codes;
                    }

                    $line .= $lineChar;
                    $charIndex++;
                } else {
                    $line .= $lineChar;
                }
            }

            // Close any open ANSI codes
            if ($lastCodes !== '' && ! str_ends_with($line, "\e[0m")) {
                $line .= "\e[0m";
            }

            $result[] = $line;
        }

        return $result;
    }

    /**
     * Parse text into segments with their associated ANSI codes.
     *
     * @return array<int, array{text: string, codes: string}>
     */
    protected function parseAnsiText(string $text): array
    {
        $segments = [];
        $currentCodes = '';
        $currentText = '';
        $i = 0;
        $textLength = strlen($text);

        while ($i < $textLength) {
            if ($text[$i] === "\e" && ($i + 1 < $textLength) && $text[$i + 1] === '[') {
                // Save current segment if it has text
                if ($currentText !== '') {
                    $segments[] = ['text' => $currentText, 'codes' => $currentCodes];
                    $currentText = '';
                }

                // Extract ANSI escape sequence
                $escapeSequence = '';
                while ($i < $textLength) {
                    $escapeSequence .= $text[$i];
                    $i++;

                    if (preg_match('/^\\e\\[[0-9;]*m$/', $escapeSequence)) {
                        // Update current codes
                        if ($escapeSequence === "\e[0m") {
                            $currentCodes = '';
                        } else {
                            $currentCodes = $escapeSequence;
                        }
                        break;
                    }
                }

                continue;
            }

            $currentText .= $text[$i];
            $i++;
        }

        // Add final segment
        if ($currentText !== '') {
            $segments[] = ['text' => $currentText, 'codes' => $currentCodes];
        }

        return $segments;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default\Concerns;

use Illuminate\Support\Collection;

trait DrawsScrollbars
{
    /**
     * Render a scrollbar beside the visible items.
     *
     * @template T of array<int, string>|\Illuminate\Support\Collection<int, string>
     *
     * @param  T  $visible
     * @return T
     */
    protected function scrollbar(array|Collection $visible, int $firstVisible, int $height, int $total, int $width, string $color = 'cyan'): array|Collection
    {
        if ($height >= $total) {
            return $visible;
        }

        $scrollPosition = $this->scrollPosition($firstVisible, $height, $total);

        $lines = $visible instanceof Collection ? $visible->all() : $visible;

        $result = array_map(fn ($line, $index) => match ($index) {
            $scrollPosition => preg_replace('/.$/', $this->{$color}('┃'), $this->pad($line, $width)) ?? '',
            default => preg_replace('/.$/', $this->gray('│'), $this->pad($line, $width)) ?? '',
        }, array_values($lines), range(0, count($lines) - 1));

        return $visible instanceof Collection ? new Collection($result) : $result; // @phpstan-ignore return.type (https://github.com/phpstan/phpstan/issues/11663)
    }

    /**
     * Return the position where the scrollbar "handle" should be rendered.
     */
    protected function scrollPosition(int $firstVisible, int $height, int $total): int
    {
        if ($firstVisible === 0) {
            return 0;
        }

        $maxPosition = $total - $height;

        if ($firstVisible === $maxPosition) {
            return $height - 1;
        }

        if ($height <= 2) {
            return -1;
        }

        $percent = $firstVisible / $maxPosition;

        return (int) round($percent * ($height - 3)) + 1;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\MultiSelectPrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;

class MultiSelectPromptRenderer extends Renderer implements Scrolling
{
    use Concerns\DrawsBoxes;
    use Concerns\DrawsScrollbars;

    /**
     * Render the multiselect prompt.
     */
    public function __invoke(MultiSelectPrompt $prompt): string
    {
        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->renderSelectedOptions($prompt)
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->renderOptions($prompt),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->renderOptions($prompt),
                    color: 'yellow',
                    info: count($prompt->options) > $prompt->scroll ? (count($prompt->value()).' selected') : '',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $this->renderOptions($prompt),
                    info: $this->getInfoText($prompt),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                ),
        };
    }

    /**
     * Render the options.
     */
    protected function renderOptions(MultiSelectPrompt $prompt): string
    {
        return implode(PHP_EOL, $this->scrollbar(
            array_values(array_map(function ($label, $key) use ($prompt) {
                $label = $this->truncate($label, $prompt->terminal()->cols() - 12);

                $index = array_search($key, array_keys($prompt->options));
                $active = $index === $prompt->highlighted;
                if (array_is_list($prompt->options)) {
                    $value = $prompt->options[$index];
                } else {
                    $value = array_keys($prompt->options)[$index];
                }
                $selected = in_array($value, $prompt->value());

                if ($prompt->state === 'cancel') {
                    return $this->dim(match (true) {
                        $active && $selected => "› ◼ {$this->strikethrough($label)}  ",
                        $active => "› ◻ {$this->strikethrough($label)}  ",
                        $selected => "  ◼ {$this->strikethrough($label)}  ",
                        default => "  ◻ {$this->strikethrough($label)}  ",
                    });
                }

                return match (true) {
                    $active && $selected => "{$this->cyan('› ◼')} {$label}  ",
                    $active => "{$this->cyan('›')} ◻ {$label}  ",
                    $selected => "  {$this->cyan('◼')} {$this->dim($label)}  ",
                    default => "  {$this->dim('◻')} {$this->dim($label)}  ",
                };
            }, $visible = $prompt->visible(), array_keys($visible))),
            $prompt->firstVisible,
            $prompt->scroll,
            count($prompt->options),
            min($this->longest($prompt->options, padding: 6), $prompt->terminal()->cols() - 6),
            $prompt->state === 'cancel' ? 'dim' : 'cyan'
        ));
    }

    /**
     * Render the selected options.
     */
    protected function renderSelectedOptions(MultiSelectPrompt $prompt): string
    {
        if (count($prompt->labels()) === 0) {
            return $this->gray('None');
        }

        return implode("\n", array_map(
            fn ($label) => $this->truncate($label, $prompt->terminal()->cols() - 6),
            $prompt->labels()
        ));
    }

    /**
     * Render the info text.
     */
    protected function getInfoText(MultiSelectPrompt $prompt): string
    {
        $parts = array_filter([
            $prompt->infoText(),
            count($prompt->options) > $prompt->scroll ? (count($prompt->value()).' selected') : '',
        ]);

        return implode(' · ', $parts);
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 5;
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\PasswordPrompt;

class PasswordPromptRenderer extends Renderer
{
    use Concerns\DrawsBoxes;

    /**
     * Render the password prompt.
     */
    public function __invoke(PasswordPrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this
                ->box(
                    $this->dim($prompt->label),
                    $this->truncate($prompt->masked(), $maxWidth),
                ),

            'cancel' => $this
                ->box(
                    $this->truncate($prompt->label, $prompt->terminal()->cols() - 6),
                    $this->strikethrough($this->dim($this->truncate($prompt->masked() ?: $prompt->placeholder, $maxWidth))),
                    color: 'red',
                )
                ->error($prompt->cancelMessage),

            'error' => $this
                ->box(
                    $this->dim($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $prompt->maskedWithCursor($maxWidth),
                    color: 'yellow',
                )
                ->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),

            default => $this
                ->box(
                    $this->cyan($this->truncate($prompt->label, $prompt->terminal()->cols() - 6)),
                    $prompt->maskedWithCursor($maxWidth),
                )
                ->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine() // Space for errors
                ),
        };
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\Title;

class TitleRenderer extends Renderer
{
    /**
     * Render the title.
     */
    public function __invoke(Title $title): string
    {
        return "\033]0;{$title->title}\007";
    }
}
<?php

namespace Laravel\Prompts\Themes\Default;

use Laravel\Prompts\DataTablePrompt;
use Laravel\Prompts\Themes\Contracts\Scrolling;
use Laravel\Prompts\Themes\Default\Concerns\DrawsBoxes;
use Laravel\Prompts\Themes\Default\Concerns\DrawsScrollbars;

class DataTableRenderer extends Renderer implements Scrolling
{
    use DrawsBoxes;
    use DrawsScrollbars;

    /**
     * Render the data table.
     */
    public function __invoke(DataTablePrompt $prompt): string
    {
        $maxWidth = $prompt->terminal()->cols() - 6;

        return match ($prompt->state) {
            'submit' => $this->renderSubmit($prompt, $maxWidth),
            'cancel' => $this->renderCancel($prompt, $maxWidth),
            default => $this->renderActive($prompt, $maxWidth),
        };
    }

    /**
     * Render the submit state.
     */
    protected function renderSubmit(DataTablePrompt $prompt, int $maxWidth): string
    {
        $row = $prompt->selectedRow();
        $display = $row ? $this->truncate(implode(', ', $row), $maxWidth) : '';

        return $this
            ->box(
                $this->dim($this->truncate($prompt->label, $maxWidth)),
                $display,
            );
    }

    /**
     * Render the cancel state.
     */
    protected function renderCancel(DataTablePrompt $prompt, int $maxWidth): string
    {
        $filtered = $prompt->filteredRows();
        $visible = $prompt->visible();

        $numCols = ! empty($prompt->headers)
            ? count($prompt->headers)
            : max(array_map('count', $prompt->rows));

        $widths = $this->computeColumnWidths($prompt->headers, $prompt->rows, $numCols, $maxWidth);
        $innerWidth = array_sum($widths) + ($numCols * 2) + ($numCols - 1) + 2;

        // Top border (red)
        $titleText = $this->truncate($prompt->label, $maxWidth);
        $titleLength = mb_strwidth($this->stripEscapeSequences($titleText));
        $topBorderFill = max(0, $innerWidth - $titleLength - 2);
        $this->line($this->red(' ┌')." {$titleText} ".$this->red(str_repeat('─', $topBorderFill).'┐'));

        // Search line (dimmed, to prevent layout shift)
        $searchContent = $this->renderSearchLine($prompt, $innerWidth - 2);
        $this->line($this->red(' │').' '.$this->dim($this->pad($searchContent, $innerWidth - 2)).' '.$this->red('│'));

        // Column separator
        $this->line(' '.$this->renderBorder('├', '┬', '┤', $widths, 'red'));

        // Header cells (strikethrough + dim)
        if (! empty($prompt->headers)) {
            $headerCells = [];

            foreach ($widths as $i => $w) {
                $header = $prompt->headers[$i] ?? '';
                $text = is_array($header) ? implode(' ', $header) : $header;
                $headerCells[] = $this->dim(' '.$this->pad($this->strikethrough($this->truncate($text, $w)), $w).' ');
            }

            $headerLine = implode($this->red('│'), $headerCells).'  ';
            $this->line($this->red(' │').$this->pad($headerLine, $innerWidth).$this->red('│'));

            $this->line(' '.$this->renderBorder('├', '┼', '┤', $widths, 'red'));
        }

        // Data rows (strikethrough + dim)
        $dataLines = $this->renderDataRows($prompt, $filtered, $visible, $widths, $numCols, $innerWidth, strikethrough: true);

        foreach ($dataLines as $dataLine) {
            $this->line($this->red(' │').$this->pad($dataLine, $innerWidth).$this->red('│'));
        }

        // Bottom border (red)
        $this->line(' '.$this->renderBorder('└', '┴', '┘', $widths, 'red'));

        return $this->error($prompt->cancelMessage);
    }

    /**
     * Render the active/browse/search state.
     */
    protected function renderActive(DataTablePrompt $prompt, int $maxWidth): string
    {
        $filtered = $prompt->filteredRows();
        $total = count($filtered);
        $visible = $prompt->visible();

        $numCols = ! empty($prompt->headers)
            ? count($prompt->headers)
            : max(array_map('count', $prompt->rows));

        // Compute column widths from ALL rows (not filtered) to prevent layout shift when searching
        $widths = $this->computeColumnWidths($prompt->headers, $prompt->rows, $numCols, $maxWidth);

        // Inner width between the outer │ chars:
        // cells (sum of w+2 padding each) + separators (numCols-1) + 2 (scrollbar area)
        $innerWidth = array_sum($widths) + ($numCols * 2) + ($numCols - 1) + 2;

        // Top border: ┌ Title ───┐
        $titleText = $this->cyan($this->truncate($prompt->label, $maxWidth));
        $titleLength = mb_strwidth($this->stripEscapeSequences($titleText));
        $topBorderFill = max(0, $innerWidth - $titleLength - 2);
        $this->line($this->gray(' ┌')." {$titleText} ".$this->gray(str_repeat('─', $topBorderFill).'┐'));

        // Search line: │ / Search              │
        $searchContent = $this->renderSearchLine($prompt, $innerWidth - 2);
        $this->line($this->gray(' │').' '.$this->pad($searchContent, $innerWidth - 2).' '.$this->gray('│'));

        if ($total === 0) {
            // No results: simple box without column separators
            $this->line(' '.$this->renderSimpleBorder('├', '┤', $innerWidth));

            $message = $prompt->searchValue() !== '' ? 'No results found.' : 'No rows.';
            $emptyLine = $this->pad(' '.$this->dim($message), $innerWidth);
            $this->line($this->gray(' │').$this->pad($emptyLine, $innerWidth).$this->gray('│'));

            $this->line(' '.$this->renderSimpleBorder('└', '┘', $innerWidth));
        } else {
            // Column separator: ├──────┬────────┤
            $this->line(' '.$this->renderBorder('├', '┬', '┤', $widths));

            // Header cells: │ Header │ Header   │
            if (! empty($prompt->headers)) {
                $headerCells = [];

                foreach ($widths as $i => $w) {
                    $header = $prompt->headers[$i] ?? '';
                    $text = is_array($header) ? implode(' ', $header) : $header;
                    $headerCells[] = $this->dim(' '.$this->pad($this->truncate($text, $w), $w).' ');
                }

                $headerLine = implode($this->gray('│'), $headerCells).'  ';
                $this->line($this->gray(' │').$this->pad($headerLine, $innerWidth).$this->gray('│'));

                // Header separator: ├──────┼────────┤
                $this->line(' '.$this->renderBorder('├', '┼', '┤', $widths));
            }

            // Data rows
            $dataLines = $this->renderDataRows($prompt, $filtered, $visible, $widths, $numCols, $innerWidth);

            foreach ($dataLines as $dataLine) {
                $this->line($this->gray(' │').$this->pad($dataLine, $innerWidth).$this->gray('│'));
            }

            // Bottom border: └──────┴────────┘
            $this->line(' '.$this->renderBorder('└', '┴', '┘', $widths));

            // Info line below the box (only when not all rows are visible)
            if ($total > $prompt->scroll) {
                $firstRow = $prompt->firstVisible + 1;
                $lastRow = min($prompt->firstVisible + $prompt->scroll, $total);
                $suffix = $prompt->searchValue() !== '' ? ' results' : '';
                $info = $this->dim('  Viewing ').$firstRow.'-'.$lastRow.$this->dim(' of ').$total.$suffix;
                $this->line($info);
            }
        }

        return $this
            ->when(
                $prompt->state === 'error',
                fn () => $this->warning($this->truncate($prompt->error, $prompt->terminal()->cols() - 5)),
                fn () => $this->when(
                    $prompt->hint,
                    fn () => $this->hint($prompt->hint),
                    fn () => $this->newLine(),
                ),
            );
    }

    /**
     * Render a column-aware border line.
     *
     * @param  array<int, int>  $widths
     */
    protected function renderBorder(string $left, string $mid, string $right, array $widths, string $color = 'gray'): string
    {
        $segments = array_map(fn ($w) => str_repeat('─', $w + 2), $widths);

        return $this->{$color}($left.implode($mid, $segments).'──'.$right);
    }

    /**
     * Render a simple border line without column separators.
     */
    protected function renderSimpleBorder(string $left, string $right, int $innerWidth, string $color = 'gray'): string
    {
        return $this->{$color}($left.str_repeat('─', $innerWidth).$right);
    }

    /**
     * Render the search line content.
     */
    protected function renderSearchLine(DataTablePrompt $prompt, int $maxWidth): string
    {
        if ($prompt->state === 'search') {
            return $this->cyan('/').' '.$prompt->searchWithCursor($maxWidth - 4);
        }

        if ($prompt->searchValue() !== '') {
            return $this->dim('/').' '.$prompt->searchValue();
        }

        return $this->dim('/ Search');
    }

    /**
     * Render data rows with scrollbar support.
     *
     * @param  array<int|string, array<int, string>>  $filtered
     * @param  array<int|string, array<int, string>>  $visible
     * @param  array<int, int>  $widths
     * @return array<int, string>
     */
    protected function renderDataRows(DataTablePrompt $prompt, array $filtered, array $visible, array $widths, int $numCols, int $innerWidth, bool $strikethrough = false): array
    {
        $total = count($filtered);

        // Build an empty row template for padding
        $emptyRow = implode($this->gray('│'), array_map(
            fn ($w) => str_repeat(' ', $w + 2),
            $widths,
        )).'  ';

        $highlightedKey = array_keys($filtered)[$prompt->highlighted] ?? null;
        $isSearching = $prompt->state === 'search';
        $fixedHeight = $prompt->scroll;

        // Render all visible logical rows into visual lines, tracking which
        // logical row each visual line belongs to so we can clip intelligently.
        $taggedLines = [];

        foreach ($visible as $key => $row) {
            $isHighlighted = ! $isSearching && ! $strikethrough && $key === $highlightedKey;

            // Split each cell by newlines
            $cellLines = [];
            $maxSubRows = 1;

            foreach ($widths as $i => $w) {
                $text = $row[$i] ?? '';
                $subLines = explode(PHP_EOL, $text);
                $cellLines[$i] = $subLines;
                $maxSubRows = max($maxSubRows, count($subLines));
            }

            // Render each sub-row
            for ($subRow = 0; $subRow < $maxSubRows; $subRow++) {
                $cells = [];

                foreach ($widths as $i => $w) {
                    $text = $cellLines[$i][$subRow] ?? '';
                    $content = ' '.$this->pad($this->truncate($text, $w), $w).' ';

                    if ($strikethrough) {
                        $content = ' '.$this->pad($this->dim($this->strikethrough($this->truncate($text, $w))), $w).' ';
                    } elseif ($isHighlighted) {
                        $content = $this->inverse($content);
                    } elseif ($isSearching) {
                        $content = $this->dim($content);
                    }

                    $cells[] = $content;
                }

                $separator = $isHighlighted ? $this->inverse('│') : $this->gray('│');
                $taggedLines[] = [
                    'line' => implode($separator, $cells).'  ',
                    'highlighted' => $isHighlighted,
                ];
            }
        }

        // Fixed visual height: always exactly `scroll` lines.
        // The highlighted row must be fully visible. If multiline rows cause
        // overflow, clip partial rows at the top or bottom edge.
        $totalVisual = count($taggedLines);

        if ($totalVisual <= $fixedHeight) {
            $dataLines = array_column($taggedLines, 'line');
        } else {
            // Find the highlighted row's visual line range
            $hlStart = null;
            $hlEnd = null;

            foreach ($taggedLines as $i => $tagged) {
                if ($tagged['highlighted']) {
                    $hlStart ??= $i;
                    $hlEnd = $i;
                }
            }

            // Pick a window of fixedHeight lines that includes the full highlighted row.
            // Prefer keeping the highlighted row near the bottom (natural scroll feel).
            if ($hlStart !== null) {
                $startLine = max(0, $hlEnd - $fixedHeight + 1);
                $startLine = min($startLine, $hlStart);
            } else {
                $startLine = 0;
            }

            $startLine = min($startLine, $totalVisual - $fixedHeight);
            $startLine = max(0, $startLine);

            $dataLines = array_column(array_slice($taggedLines, $startLine, $fixedHeight), 'line');
        }

        while (count($dataLines) < $fixedHeight) {
            $dataLines[] = $emptyRow;
        }

        // Apply scrollbar to data lines.
        // We can't use the trait's scrollbar() directly because it compares visual
        // line count against logical row count — multiline rows inflate visual lines
        // beyond $total, causing the scrollbar to disappear. Instead, determine
        // scrollability from logical counts and map the indicator to visual space.
        $shouldScroll = $total > $prompt->scroll;

        if ($shouldScroll) {
            $numVisual = count($dataLines);
            $maxFirst = $total - $prompt->scroll;

            if ($prompt->firstVisible === 0) {
                $visualPos = 0;
            } elseif ($prompt->firstVisible >= $maxFirst) {
                $visualPos = $numVisual - 1;
            } elseif ($numVisual <= 2) {
                $visualPos = -1;
            } else {
                $percent = $prompt->firstVisible / $maxFirst;
                $visualPos = (int) round($percent * ($numVisual - 3)) + 1;
            }

            $dataLines = array_map(fn ($line, $index) => match ($index) {
                $visualPos => preg_replace('/.$/', $this->cyan('┃'), $this->pad($line, $innerWidth)) ?? '',
                default => preg_replace('/.$/', $this->gray('│'), $this->pad($line, $innerWidth)) ?? '',
            }, array_values($dataLines), range(0, $numVisual - 1));
        }

        return $dataLines;
    }

    /**
     * Compute column widths that fit within maxWidth.
     *
     * Columns get their natural (P85) width. Only shrink proportionally
     * if the total exceeds available terminal space.
     *
     * @param  array<int, string|array<int, string>>  $headers
     * @param  array<int|string, array<int, string>>  $allRows
     * @return array<int, int>
     */
    protected function computeColumnWidths(array $headers, array $allRows, int $numCols, int $maxWidth): array
    {
        // Header widths serve as the floor for each column
        $headerWidths = array_fill(0, $numCols, 0);

        foreach ($headers as $i => $header) {
            $headerText = is_array($header) ? implode(' ', $header) : $header;
            $headerWidths[$i] = mb_strwidth($headerText);
        }

        // Collect all cell widths per column (excluding blank cells)
        $columnWidths = array_fill(0, $numCols, []);

        foreach ($allRows as $row) {
            foreach ($row as $i => $cell) {
                $cellMax = 0;
                foreach (explode(PHP_EOL, $cell) as $line) {
                    $cellMax = max($cellMax, mb_strwidth($line));
                }
                if ($cellMax > 0) {
                    $columnWidths[$i][] = $cellMax;
                }
            }
        }

        // Per-column width strategy:
        // - Uniform columns (max <= P90 * 2): use max — all values are reasonable
        // - Outlier columns (max > P90 * 2): use P90 — ignore extreme values
        $natural = array_fill(0, $numCols, 0);

        foreach ($columnWidths as $i => $widths) {
            if (empty($widths)) {
                $natural[$i] = $headerWidths[$i];

                continue;
            }

            sort($widths);
            $p90Index = (int) ceil(count($widths) * 0.90) - 1;
            $p90 = $widths[max(0, $p90Index)];
            $colMax = end($widths);

            $natural[$i] = max($headerWidths[$i], $colMax <= $p90 * 2 ? $colMax : $p90);
        }

        // Available width for cell content:
        // Each column has 1 space padding on each side = 2 per column
        // Columns separated by │ = numCols - 1 separators
        // Scrollbar area = 2 chars on the right
        // Outer frame = 4 chars (` │` left + ` │` right)
        $overhead = ($numCols * 2) + ($numCols - 1) + 2 + 4;
        $available = $maxWidth - $overhead;

        if ($available <= 0) {
            return array_fill(0, $numCols, 1);
        }

        $totalNatural = array_sum($natural);

        // If natural widths fit, use them directly (comfortable width)
        if ($totalNatural <= $available) {
            return $natural;
        }

        // Otherwise, shrink proportionally
        $widths = array_fill(0, $numCols, 0);

        foreach ($natural as $i => $w) {
            $widths[$i] = max($headerWidths[$i], (int) floor($available * $w / $totalNatural));
        }

        // Distribute any remaining pixels from rounding
        $remainder = $available - array_sum($widths);

        if ($remainder > 0) {
            $order = range(0, $numCols - 1);
            usort($order, fn ($a, $b) => $natural[$b] <=> $natural[$a]);

            foreach ($order as $i) {
                if ($remainder <= 0) {
                    break;
                }
                $widths[$i]++;
                $remainder--;
            }
        }

        return $widths;
    }

    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int
    {
        return 10;
    }
}
<?php

namespace Laravel\Prompts\Themes\Contracts;

interface Scrolling
{
    /**
     * The number of lines to reserve outside of the scrollable area.
     */
    public function reservedLines(): int;
}
<?php

namespace Laravel\Prompts;

use Closure;
use Laravel\Prompts\Support\Utils;
use Laravel\Prompts\Themes\Default\Concerns\InteractsWithStrings;

class TextareaPrompt extends Prompt
{
    use Concerns\Scrolling;
    use Concerns\TypedValue;
    use InteractsWithStrings;

    protected int $minWidth = 0;

    /**
     * The width of the textarea.
     */
    public int $width = 60;

    /**
     * Create a new TextareaPrompt instance.
     */
    public function __construct(
        public string $label,
        public string $placeholder = '',
        public string $default = '',
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        int $rows = 5,
        public ?Closure $transform = null,
    ) {
        $this->scroll = $rows;

        $this->initializeScrolling();

        $this->trackTypedValue(
            default: $default,
            submit: false,
            allowNewLine: true,
        );

        $this->on('key', function ($key) {
            if ($key[0] === "\e") {
                match ($key) {
                    Key::UP, Key::UP_ARROW, Key::CTRL_P => $this->handleUpKey(),
                    Key::DOWN, Key::DOWN_ARROW, Key::CTRL_N => $this->handleDownKey(),
                    default => null,
                };

                return;
            }

            // Keys may be buffered.
            foreach (mb_str_split($key) as $key) {
                if ($key === Key::CTRL_D) {
                    $this->submit();

                    return;
                }
            }
        });
    }

    /**
     * Get the formatted value with a virtual cursor.
     */
    public function valueWithCursor(): string
    {
        if ($this->value() === '') {
            return $this->wrappedPlaceholderWithCursor();
        }

        return $this->addCursor($this->wrappedValue(), $this->cursorPosition + $this->cursorOffset(), -1);
    }

    /**
     * The word-wrapped version of the typed value.
     */
    public function wrappedValue(): string
    {
        return $this->mbWordwrap($this->value(), $this->width, PHP_EOL, true);
    }

    /**
     * The formatted lines.
     *
     * @return array<int, string>
     */
    public function lines(): array
    {
        return explode(PHP_EOL, $this->wrappedValue());
    }

    /**
     * The currently visible lines.
     *
     * @return array<int, string>
     */
    public function visible(): array
    {
        $this->adjustVisibleWindow();

        $withCursor = $this->valueWithCursor();

        return array_slice(explode(PHP_EOL, $withCursor), $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Handle the up key press.
     */
    protected function handleUpKey(): void
    {
        if ($this->cursorPosition === 0) {
            return;
        }

        $lines = $this->lines();

        // Line length + 1 for the newline character
        $lineLengths = array_map(fn ($line, $index) => mb_strlen($line) + ($index === count($lines) - 1 ? 0 : 1), $lines, range(0, count($lines) - 1));

        $currentLineIndex = $this->currentLineIndex();

        if ($currentLineIndex === 0) {
            // They're already at the first line, jump them to the first position
            $this->cursorPosition = 0;

            return;
        }

        $currentLines = array_slice($lineLengths, 0, $currentLineIndex + 1);

        $currentColumn = Utils::last($currentLines) - (array_sum($currentLines) - $this->cursorPosition);

        $destinationLineLength = ($lineLengths[$currentLineIndex - 1] ?? $currentLines[0]) - 1;

        $newColumn = min($destinationLineLength, $currentColumn);

        $fullLines = array_slice($currentLines, 0, -2);

        $this->cursorPosition = array_sum($fullLines) + $newColumn;
    }

    /**
     * Handle the down key press.
     */
    protected function handleDownKey(): void
    {
        $lines = $this->lines();

        // Line length + 1 for the newline character
        $lineLengths = array_map(fn ($line, $index) => mb_strlen($line) + ($index === count($lines) - 1 ? 0 : 1), $lines, range(0, count($lines) - 1));

        $currentLineIndex = $this->currentLineIndex();

        if ($currentLineIndex === count($lines) - 1) {
            // They're already at the last line, jump them to the last position
            $this->cursorPosition = mb_strlen(implode(PHP_EOL, $lines));

            return;
        }

        // Lines up to and including the current line
        $currentLines = array_slice($lineLengths, 0, $currentLineIndex + 1);

        $currentColumn = Utils::last($currentLines) - (array_sum($currentLines) - $this->cursorPosition);

        $destinationLineLength = $lineLengths[$currentLineIndex + 1] ?? Utils::last($currentLines);

        if ($currentLineIndex + 1 !== count($lines) - 1) {
            $destinationLineLength--;
        }

        $newColumn = min(max(0, $destinationLineLength), $currentColumn);

        $this->cursorPosition = array_sum($currentLines) + $newColumn;
    }

    /**
     * Adjust the visible window to ensure the cursor is always visible.
     */
    protected function adjustVisibleWindow(): void
    {
        if (count($this->lines()) < $this->scroll) {
            return;
        }

        $currentLineIndex = $this->currentLineIndex();

        while ($this->firstVisible + $this->scroll <= $currentLineIndex) {
            $this->firstVisible++;
        }

        if ($currentLineIndex === $this->firstVisible - 1) {
            $this->firstVisible = max(0, $this->firstVisible - 1);
        }

        // Make sure there are always the scroll amount visible
        if ($this->firstVisible + $this->scroll > count($this->lines())) {
            $this->firstVisible = count($this->lines()) - $this->scroll;
        }
    }

    /**
     * Get the index of the current line that the cursor is on.
     */
    protected function currentLineIndex(): int
    {
        $totalLineLength = 0;

        return (int) Utils::search($this->lines(), function ($line) use (&$totalLineLength) {
            $totalLineLength += mb_strlen($line) + 1;

            return $totalLineLength > $this->cursorPosition;
        }) ?: 0;
    }

    /**
     * Calculate the cursor offset considering wrapped words.
     */
    protected function cursorOffset(): int
    {
        $cursorOffset = 0;

        preg_match_all('/\S{'.$this->width.',}/u', $this->value(), $matches, PREG_OFFSET_CAPTURE);

        foreach ($matches[0] as $match) {
            if ($this->cursorPosition + $cursorOffset >= $match[1] + mb_strwidth($match[0])) {
                $cursorOffset += (int) floor(mb_strwidth($match[0]) / $this->width);
            }
        }

        return $cursorOffset;
    }

    /**
     * A wrapped version of the placeholder with the virtual cursor.
     */
    protected function wrappedPlaceholderWithCursor(): string
    {
        return implode(PHP_EOL, array_map(
            $this->dim(...),
            explode(PHP_EOL, $this->addCursor(
                $this->mbWordwrap($this->placeholder, $this->width, PHP_EOL, true),
                cursorPosition: 0,
            ))
        ));
    }
}
<?php

namespace Laravel\Prompts;

use Illuminate\Support\Collection;

class Grid extends Prompt
{
    /**
     * The grid items.
     *
     * @var array<int, string>
     */
    public array $items;

    /**
     * The maximum width of the grid.
     */
    public int $maxWidth;

    /**
     * Create a new Grid instance.
     *
     * @param  array<int, string>|Collection<int, string>  $items
     */
    public function __construct(array|Collection $items = [], ?int $maxWidth = null)
    {
        $this->items = $items instanceof Collection ? $items->all() : $items;
        $this->maxWidth = $maxWidth ?? static::terminal()->cols() ?: 80;
    }

    /**
     * Display the grid.
     */
    public function display(): void
    {
        $this->prompt();
    }

    /**
     * Display the grid.
     */
    public function prompt(): bool
    {
        if ($this->items === []) {
            return true;
        }

        $this->capturePreviousNewLines();

        $this->state = 'submit';

        static::output()->write($this->renderTheme());

        return true;
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Laravel\Prompts\Exceptions\FormRevertedException;
use Laravel\Prompts\Output\ConsoleOutput;
use Laravel\Prompts\Support\Result;
use RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;

abstract class Prompt
{
    use Concerns\Colors;
    use Concerns\Cursor;
    use Concerns\Erase;
    use Concerns\Events;
    use Concerns\FakesInputOutput;
    use Concerns\Fallback;
    use Concerns\Interactivity;
    use Concerns\Themes;

    /**
     * The current state of the prompt.
     */
    public string $state = 'initial';

    /**
     * The error message from the validator.
     */
    public string $error = '';

    /**
     * The cancel message displayed when this prompt is cancelled.
     */
    public string $cancelMessage = 'Cancelled.';

    /**
     * The previously rendered frame.
     */
    protected string $prevFrame = '';

    /**
     * How many new lines were written by the last output.
     */
    protected int $newLinesWritten = 1;

    /**
     * Whether user input is required.
     */
    public bool|string $required;

    /**
     * The transformation callback.
     */
    public ?Closure $transform = null;

    /**
     * The validator callback or rules.
     */
    public mixed $validate;

    /**
     * The cancellation callback.
     */
    protected static ?Closure $cancelUsing;

    /**
     * Indicates if the prompt has been validated.
     */
    protected bool $validated = false;

    /**
     * The custom validation callback.
     */
    protected static ?Closure $validateUsing;

    /**
     * The revert handler from the StepBuilder.
     */
    protected static ?Closure $revertUsing = null;

    /**
     * The output instance.
     */
    protected static OutputInterface $output;

    /**
     * The terminal instance.
     */
    protected static Terminal $terminal;

    /**
     * Get the value of the prompt.
     */
    abstract public function value(): mixed;

    /**
     * Render the prompt and listen for input.
     */
    public function prompt(): mixed
    {
        try {
            $this->capturePreviousNewLines();

            if (static::shouldFallback()) {
                return $this->fallback();
            }

            static::$interactive ??= stream_isatty(STDIN);

            if (! static::$interactive) {
                return $this->default();
            }

            $this->checkEnvironment();

            try {
                static::terminal()->setTty('-icanon -isig -echo');
            } catch (Throwable $e) {
                static::output()->writeln("<comment>{$e->getMessage()}</comment>");
                static::fallbackWhen(true);

                return $this->fallback();
            }

            $this->hideCursor();
            $this->render();

            $result = $this->runLoop(function (string $key): ?Result {
                $continue = $this->handleKeyPress($key);

                $this->render();

                if ($continue === false || $key === Key::CTRL_C) {
                    if ($key === Key::CTRL_C) {
                        if (isset(static::$cancelUsing)) {
                            return Result::from((static::$cancelUsing)());
                        } else {
                            static::terminal()->exit();
                        }
                    }

                    if ($key === Key::CTRL_U && self::$revertUsing) {
                        throw new FormRevertedException;
                    }

                    return Result::from($this->transformedValue());
                }

                // Continue looping.
                return null;
            });

            return $result;
        } finally {
            $this->clearListeners();
        }
    }

    /**
     * Implementation of the prompt looping mechanism.
     *
     * @param  callable(string $key): ?Result  $callable
     */
    public function runLoop(callable $callable): mixed
    {
        while (($key = static::terminal()->read()) !== null) {
            /**
             * If $key is an empty string, Terminal::read
             * has failed. We can continue to the next
             * iteration of the loop, and try again.
             */
            if ($key === '') {
                continue;
            }

            $result = $callable($key);

            if ($result instanceof Result) {
                return $result->value;
            }
        }
    }

    /**
     * Register a callback to be invoked when a user cancels a prompt.
     */
    public static function cancelUsing(?Closure $callback): void
    {
        static::$cancelUsing = $callback;
    }

    /**
     * How many new lines were written by the last output.
     */
    public function newLinesWritten(): int
    {
        return $this->newLinesWritten;
    }

    /**
     * Capture the number of new lines written by the last output.
     */
    protected function capturePreviousNewLines(): void
    {
        $this->newLinesWritten = method_exists(static::output(), 'newLinesWritten')
            ? static::output()->newLinesWritten()
            : 1;
    }

    /**
     * Set the output instance.
     */
    public static function setOutput(OutputInterface $output): void
    {
        self::$output = $output;
    }

    /**
     * Get the current output instance.
     */
    protected static function output(): OutputInterface
    {
        return self::$output ??= new ConsoleOutput;
    }

    /**
     * Write output directly, bypassing newline capture.
     */
    protected static function writeDirectly(string $message): void
    {
        match (true) {
            method_exists(static::output(), 'writeDirectly') => static::output()->writeDirectly($message),
            method_exists(static::output(), 'getOutput') => static::output()->getOutput()->write($message),
            default => static::output()->write($message),
        };
    }

    /**
     * Get the terminal instance.
     */
    public static function terminal(): Terminal
    {
        return static::$terminal ??= new Terminal;
    }

    /**
     * Set the custom validation callback.
     */
    public static function validateUsing(Closure $callback): void
    {
        static::$validateUsing = $callback;
    }

    /**
     * Revert the prompt using the given callback.
     *
     * @internal
     */
    public static function revertUsing(Closure $callback): void
    {
        static::$revertUsing = $callback;
    }

    /**
     * Clear any previous revert callback.
     *
     * @internal
     */
    public static function preventReverting(): void
    {
        static::$revertUsing = null;
    }

    /**
     * Render the prompt.
     */
    protected function render(): void
    {
        $this->terminal()->initDimensions();

        $frame = $this->renderTheme();

        if ($frame === $this->prevFrame) {
            return;
        }

        if ($this->state === 'initial') {
            static::output()->write($frame);

            $this->state = 'active';
            $this->prevFrame = $frame;

            return;
        }

        $terminalHeight = $this->terminal()->lines();
        $previousFrameHeight = count(explode(PHP_EOL, $this->prevFrame));
        $renderableLines = array_slice(explode(PHP_EOL, $frame), abs(min(0, $terminalHeight - $previousFrameHeight)));

        $this->moveCursorToColumn(1);
        $this->moveCursorUp(min($terminalHeight, $previousFrameHeight) - 1);
        $this->eraseDown();
        $this->output()->write(implode(PHP_EOL, $renderableLines));

        $this->prevFrame = $frame;
    }

    /**
     * Submit the prompt.
     */
    protected function submit(): void
    {
        $this->validate($this->transformedValue());

        if ($this->state !== 'error') {
            $this->state = 'submit';
        }
    }

    /**
     * Handle a key press and determine whether to continue.
     */
    private function handleKeyPress(string $key): bool
    {
        if ($this->state === 'error') {
            $this->state = 'active';
        }

        $this->emit('key', $key);

        if ($this->state === 'submit') {
            return false;
        }

        if ($key === Key::CTRL_U) {
            if (! self::$revertUsing) {
                $this->state = 'error';
                $this->error = 'This cannot be reverted.';

                return true;
            }

            $this->state = 'cancel';
            $this->cancelMessage = 'Reverted.';

            call_user_func(self::$revertUsing);

            return false;
        }

        if ($key === Key::CTRL_C) {
            $this->state = 'cancel';

            return false;
        }

        if ($this->validated) {
            $this->validate($this->transformedValue());
        }

        return true;
    }

    /**
     * Transform the input.
     */
    private function transform(mixed $value): mixed
    {
        if (is_null($this->transform)) {
            return $value;
        }

        return call_user_func($this->transform, $value);
    }

    /**
     * Get the transformed value of the prompt.
     */
    protected function transformedValue(): mixed
    {
        return $this->transform($this->value());
    }

    /**
     * Validate the input.
     */
    private function validate(mixed $value): void
    {
        $this->validated = true;

        if ($this->required !== false && $this->isInvalidWhenRequired($value)) {
            $this->state = 'error';
            $this->error = is_string($this->required) && strlen($this->required) > 0 ? $this->required : 'Required.';

            return;
        }

        if (! isset($this->validate) && ! isset(static::$validateUsing)) {
            return;
        }

        $error = match (true) {
            is_callable($this->validate) => ($this->validate)($value),
            isset(static::$validateUsing) => (static::$validateUsing)($this),
            default => throw new RuntimeException('The validation logic is missing.'),
        };

        if (! is_string($error) && ! is_null($error)) {
            throw new RuntimeException('The validator must return a string or null.');
        }

        if (is_string($error) && strlen($error) > 0) {
            $this->state = 'error';
            $this->error = $error;
        }
    }

    /**
     * Determine whether the given value is invalid when the prompt is required.
     */
    protected function isInvalidWhenRequired(mixed $value): bool
    {
        return $value === '' || $value === [] || $value === false || $value === null;
    }

    /**
     * Check whether the environment can support the prompt.
     */
    private function checkEnvironment(): void
    {
        if (PHP_OS_FAMILY === 'Windows') {
            throw new RuntimeException('Prompts is not currently supported on Windows. Please use WSL or configure a fallback.');
        }
    }

    /**
     * Restore the cursor and terminal state.
     */
    public function __destruct()
    {
        $this->restoreCursor();

        static::terminal()->restoreTty();
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Laravel\Prompts\Support\Utils;

class MultiSearchPrompt extends Prompt
{
    use Concerns\HasInfo;
    use Concerns\Scrolling;
    use Concerns\Truncation;
    use Concerns\TypedValue;

    /**
     * The cached matches.
     *
     * @var array<int|string, string>|null
     */
    protected ?array $matches = null;

    /**
     * Whether the matches are initially a list.
     */
    protected bool $isList;

    /**
     * The selected values.
     *
     * @var array<int|string, string>
     */
    public array $values = [];

    /**
     * Create a new MultiSearchPrompt instance.
     *
     * @param  Closure(string): array<int|string, string>  $options
     */
    public function __construct(
        public string $label,
        public Closure $options,
        public string $placeholder = '',
        public int $scroll = 5,
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
        public string|Closure $info = '',
    ) {
        $this->trackTypedValue(submit: false, ignore: fn ($key) => Key::oneOf([Key::SPACE, Key::HOME, Key::END, Key::CTRL_A, Key::CTRL_E], $key) && $this->highlighted !== null);

        $this->initializeScrolling(null);

        $this->on('key', fn ($key) => match ($key) {
            Key::UP, Key::UP_ARROW, Key::SHIFT_TAB => $this->highlightPrevious(count($this->matches), true),
            Key::DOWN, Key::DOWN_ARROW, Key::TAB => $this->highlightNext(count($this->matches), true),
            Key::oneOf(Key::HOME, $key) => $this->highlighted !== null ? $this->highlight(0) : null,
            Key::oneOf(Key::END, $key) => $this->highlighted !== null ? $this->highlight(count($this->matches()) - 1) : null,
            Key::SPACE => $this->highlighted !== null ? $this->toggleHighlighted() : null,
            Key::CTRL_A => $this->highlighted !== null ? $this->toggleAll() : null,
            Key::CTRL_E => null,
            Key::ENTER => $this->submit(),
            Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW => $this->highlighted = null,
            default => $this->search(),
        });
    }

    /**
     * Get the value of the highlighted option.
     */
    public function highlightedValue(): int|string|null
    {
        if ($this->highlighted === null || ! is_array($this->matches)) {
            return null;
        }

        if ($this->isList()) {
            return $this->matches[$this->highlighted] ?? null;
        }

        return array_keys($this->matches)[$this->highlighted] ?? null;
    }

    /**
     * Perform the search.
     */
    protected function search(): void
    {
        $this->state = 'searching';
        $this->highlighted = null;
        $this->render();
        $this->matches = null;
        $this->firstVisible = 0;
        $this->state = 'active';
    }

    /**
     * Get the entered value with a virtual cursor.
     */
    public function valueWithCursor(int $maxWidth): string
    {
        if ($this->highlighted !== null) {
            return $this->typedValue === ''
                ? $this->dim($this->truncate($this->placeholder, $maxWidth))
                : $this->truncate($this->typedValue, $maxWidth);
        }

        if ($this->typedValue === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        return $this->addCursor($this->typedValue, $this->cursorPosition, $maxWidth);
    }

    /**
     * Get options that match the input.
     *
     * @return array<string>
     */
    public function matches(): array
    {
        if (is_array($this->matches)) {
            return $this->matches;
        }

        $matches = ($this->options)($this->typedValue);

        if (! isset($this->isList) && count($matches) > 0) {
            // This needs to be captured the first time we receive matches so
            // we know what we're dealing with later if matches is empty.
            $this->isList = array_is_list($matches);
        }

        if (! isset($this->isList)) {
            return $this->matches = [];
        }

        if (strlen($this->typedValue) > 0) {
            return $this->matches = $matches;
        }

        return $this->matches = $this->isList
            ? [...array_diff(array_values($this->values), $matches), ...$matches]
            : array_diff($this->values, $matches) + $matches;
    }

    /**
     * The currently visible matches
     *
     * @return array<string>
     */
    public function visible(): array
    {
        return array_slice($this->matches(), $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Toggle all options.
     */
    protected function toggleAll(): void
    {
        $allMatchesSelected = Utils::allMatch($this->matches, fn ($label, $key) => $this->isList()
            ? array_key_exists($label, $this->values)
            : array_key_exists($key, $this->values));

        if ($allMatchesSelected) {
            $this->values = array_filter($this->values, fn ($value) => $this->isList()
                ? ! in_array($value, $this->matches)
                : ! array_key_exists(array_search($value, $this->matches), $this->matches)
            );
        } else {
            $this->values = $this->isList()
                ? array_merge($this->values, array_combine(array_values($this->matches), array_values($this->matches)))
                : array_merge($this->values, array_combine(array_keys($this->matches), array_values($this->matches)));
        }
    }

    /**
     * Toggle the highlighted entry.
     */
    protected function toggleHighlighted(): void
    {
        if ($this->isList()) {
            $label = $this->matches[$this->highlighted];
            $key = $label;
        } else {
            $key = array_keys($this->matches)[$this->highlighted];
            $label = $this->matches[$key];
        }

        if (array_key_exists($key, $this->values)) {
            unset($this->values[$key]);
        } else {
            $this->values[$key] = $label;
        }
    }

    /**
     * Get the current search query.
     */
    public function searchValue(): string
    {
        return $this->typedValue;
    }

    /**
     * Get the selected value.
     *
     * @return array<int|string>
     */
    public function value(): array
    {
        return array_keys($this->values);
    }

    /**
     * Get the selected labels.
     *
     * @return array<string>
     */
    public function labels(): array
    {
        return array_values($this->values);
    }

    /**
     * Whether the matches are initially a list.
     */
    public function isList(): bool
    {
        return $this->isList;
    }
}
<?php

namespace Laravel\Prompts;

class Title extends Prompt
{
    public function __construct(public string $title)
    {
        //
    }

    /**
     * Update the title of the terminal.
     */
    public function prompt(): bool
    {
        $this->writeDirectly($this->renderTheme());

        return true;
    }

    /**
     * Update the title of the terminal.
     */
    public function display(): void
    {
        $this->prompt();
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }
}
<?php

namespace Laravel\Prompts;

use ReflectionClass;
use RuntimeException;
use Symfony\Component\Console\Terminal as SymfonyTerminal;

class Terminal
{
    /**
     * The initial TTY mode.
     */
    protected ?string $initialTtyMode;

    /**
     * Whether the terminal supports true color.
     */
    protected static ?bool $trueColorSupport = null;

    /**
     * The terminal's foreground color as an RGB array.
     *
     * @var array{int, int, int}|null
     */
    protected static ?array $foregroundColor = null;

    /**
     * The terminal's background color as an RGB array.
     *
     * @var array{int, int, int}|null
     */
    protected static ?array $backgroundColor = null;

    /**
     * The Symfony Terminal instance.
     */
    protected SymfonyTerminal $terminal;

    /**
     * Create a new Terminal instance.
     */
    public function __construct()
    {
        $this->terminal = new SymfonyTerminal;
    }

    /**
     * Read a line from the terminal.
     */
    public function read(): string
    {
        $input = fread(STDIN, 1024);

        return $input !== false ? $input : '';
    }

    /**
     * Set the TTY mode.
     */
    public function setTty(string $mode): void
    {
        $this->initialTtyMode ??= $this->exec('stty -g');

        $this->exec("stty $mode");
    }

    /**
     * Restore the initial TTY mode.
     */
    public function restoreTty(): void
    {
        if (isset($this->initialTtyMode)) {
            $this->exec("stty {$this->initialTtyMode}");

            $this->initialTtyMode = null;
        }
    }

    /**
     * Get the number of columns in the terminal.
     */
    public function cols(): int
    {
        return $this->terminal->getWidth();
    }

    /**
     * Get the number of lines in the terminal.
     */
    public function lines(): int
    {
        return $this->terminal->getHeight();
    }

    /**
     * (Re)initialize the terminal dimensions.
     */
    public function initDimensions(): void
    {
        (new ReflectionClass($this->terminal))
            ->getMethod('initDimensions')
            ->invoke($this->terminal);
    }

    /**
     * Exit the interactive session.
     */
    public function exit(): void
    {
        exit(1);
    }

    /**
     * Execute the given command and return the output.
     */
    protected function exec(string $command): string
    {
        $process = proc_open($command, [
            1 => ['pipe', 'w'],
            2 => ['pipe', 'w'],
        ], $pipes);

        if (! $process) {
            throw new RuntimeException('Failed to create process.');
        }

        $stdout = stream_get_contents($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        $code = proc_close($process);

        if ($code !== 0 || $stdout === false) {
            throw new RuntimeException(trim($stderr ?: "Unknown error (code: $code)"), $code);
        }

        return $stdout;
    }

    /**
     * Determine if the terminal supports true color (24-bit).
     */
    public function supportsTrueColor(): bool
    {
        return static::$trueColorSupport ??= in_array(getenv('COLORTERM'), ['truecolor', '24bit']);
    }

    /**
     * Get the terminal's foreground color as an RGB array.
     *
     * @return array{int, int, int}
     */
    public function foregroundColor(): array
    {
        if (static::$foregroundColor === null) {
            $this->queryColors();
        }

        return static::$foregroundColor;
    }

    /**
     * Get the terminal's background color as an RGB array.
     *
     * @return array{int, int, int}
     */
    public function backgroundColor(): array
    {
        if (static::$backgroundColor === null) {
            $this->queryColors();
        }

        return static::$backgroundColor;
    }

    /**
     * Query the terminal for foreground and background colors in a single shot.
     */
    protected function queryColors(): void
    {
        $savedStty = trim((string) shell_exec('stty -g < /dev/tty'));

        shell_exec('stty raw -echo min 0 time 1 < /dev/tty');

        fwrite(STDOUT, "\e]10;?\e\\\e]11;?\e\\");
        fflush(STDOUT);

        $ttyIn = fopen('/dev/tty', 'r');

        if ($ttyIn === false) {
            static::$foregroundColor = [204, 204, 204];
            static::$backgroundColor = [0, 0, 0];

            return;
        }

        $response = fread($ttyIn, 200);
        fclose($ttyIn);

        shell_exec("stty {$savedStty} < /dev/tty");

        preg_match_all('/rgb:([0-9a-f]+)\/([0-9a-f]+)\/([0-9a-f]+)/i', $response ?: '', $matches, PREG_SET_ORDER);

        $parse = fn (array $m) => [
            (int) (hexdec($m[1]) / (strlen($m[1]) === 4 ? 257 : 1)),
            (int) (hexdec($m[2]) / (strlen($m[2]) === 4 ? 257 : 1)),
            (int) (hexdec($m[3]) / (strlen($m[3]) === 4 ? 257 : 1)),
        ];

        static::$foregroundColor = isset($matches[0]) ? $parse($matches[0]) : [204, 204, 204];
        static::$backgroundColor = isset($matches[1]) ? $parse($matches[1]) : [0, 0, 0];
    }
}
<?php

namespace Laravel\Prompts;

class PausePrompt extends Prompt
{
    /**
     * Create a new PausePrompt instance.
     */
    public function __construct(public string $message = 'Press enter to continue...')
    {
        $this->required = false;
        $this->validate = null;

        $this->on('key', fn ($key) => match ($key) {
            Key::ENTER => $this->submit(),
            default => null,
        });
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return static::$interactive;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;

class FormStep
{
    protected readonly Closure $condition;

    public function __construct(
        protected readonly Closure $step,
        bool|Closure $condition,
        public readonly ?string $name,
        protected readonly bool $ignoreWhenReverting,
    ) {
        $this->condition = is_bool($condition)
            ? fn () => $condition
            : $condition;
    }

    /**
     * Execute this step.
     *
     * @param  array<mixed>  $responses
     */
    public function run(array $responses, mixed $previousResponse): mixed
    {
        if (! $this->shouldRun($responses)) {
            return null;
        }

        return ($this->step)($responses, $previousResponse, $this->name);
    }

    /**
     * Whether the step should run based on the given condition.
     *
     * @param  array<mixed>  $responses
     */
    protected function shouldRun(array $responses): bool
    {
        return ($this->condition)($responses);
    }

    /**
     * Whether this step should be skipped over when a subsequent step is reverted.
     *
     * @param  array<mixed>  $responses
     */
    public function shouldIgnoreWhenReverting(array $responses): bool
    {
        if (! $this->shouldRun($responses)) {
            return true;
        }

        return $this->ignoreWhenReverting;
    }
}
<?php

namespace Laravel\Prompts\Support;

/**
 * Result.
 *
 * This is a 'sentinel' value. It wraps a return value, which can
 * allow us to differentiate between a `null` return value and
 * a `null` return value that's intended to continue a loop.
 */
final class Result
{
    public function __construct(public readonly mixed $value)
    {
        //
    }

    public static function from(mixed $value): self
    {
        return new self($value);
    }
}
<?php

namespace Laravel\Prompts\Support;

use Closure;

/**
 * @internal
 */
class Utils
{
    /**
     * Determine if all items in an array match a truth test.
     *
     * @param  array<array-key, mixed>  $values
     */
    public static function allMatch(array $values, Closure $callback): bool
    {
        foreach ($values as $key => $value) {
            if (! $callback($value, $key)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get the last item from an array or null if it doesn't exist.
     *
     * @param  array<array-key, mixed>  $array
     */
    public static function last(array $array): mixed
    {
        return array_reverse($array)[0] ?? null;
    }

    /**
     * Returns the key of the first element in the array that satisfies the callback.
     *
     * @param  array<array-key, mixed>  $array
     */
    public static function search(array $array, Closure $callback): int|string|false
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return $key;
            }
        }

        return false;
    }
}
<?php

namespace Laravel\Prompts\Support;

class Logger
{
    /**
     * Create a new Logger instance.
     *
     * @param  resource|null  $socket
     */
    public function __construct(protected string $identifier, protected $socket = null)
    {
        //
    }

    /**
     * The buffer for streaming text.
     */
    protected string $streamBuffer = '';

    /**
     * Log a line to the process log.
     */
    public function line(string $message): void
    {
        $this->write(rtrim($message));
    }

    /**
     * Append a chunk of text, accumulating on the current line(s).
     */
    public function partial(string $chunk): void
    {
        $this->streamBuffer .= $chunk;
        $this->write($this->streamBuffer, 'partial');
    }

    /**
     * Commit the accumulated partial text and start fresh.
     */
    public function commitPartial(): void
    {
        $this->streamBuffer = '';
        $this->write('', 'commitpartial');
    }

    /**
     * Log a success message to the process log.
     */
    public function success(string $message): void
    {
        $this->write($message, 'success');
    }

    /**
     * Log a warning message to the process log.
     */
    public function warning(string $message): void
    {
        $this->write($message, 'warning');
    }

    /**
     * Log an error message to the process log.
     */
    public function error(string $message): void
    {
        $this->write($message, 'error');
    }

    /**
     * Update the label of the process log.
     */
    public function label(string $message): void
    {
        $this->write($message, 'label');
    }

    /**
     * Update the sub-label of the process log. Pass an empty string to clear.
     */
    public function subLabel(string $message): void
    {
        $this->write($message, 'sublabel');
    }

    /**
     * Write a message to the socket.
     */
    protected function write(string $message, ?string $type = null): void
    {
        if ($this->socket === null) {
            return;
        }

        if ($type !== null) {
            fwrite($this->socket, $this->prefix($type, $message).PHP_EOL);
        } else {
            fwrite($this->socket, $message.PHP_EOL);
        }
    }

    /**
     * Prefix a message with the identifier and type.
     */
    protected function prefix(string $type, string $message): string
    {
        return $this->identifier.'_'.$type.':'.rtrim($message, PHP_EOL);
    }
}
<?php

namespace Laravel\Prompts;

use Laravel\Prompts\Themes\Default\Concerns\InteractsWithStrings;

class Stream extends Prompt
{
    use InteractsWithStrings;

    protected int $minWidth = 0;

    protected string $message = '';

    /** @var array<int, string> */
    protected array $currentlyFading = [];

    protected int $maxWidth = 0;

    /** @var array<int, \Closure(string): string> */
    protected array $fadingOutColors = [];

    /**
     * Create a new Stream instance.
     */
    public function __construct()
    {
        $this->maxWidth = static::terminal()->cols() - 20;
        $this->hideCursor();
        $this->fadingOutColors = $this->fadeOut();
    }

    public function append(string $message): self
    {
        $this->currentlyFading[] = $message;

        while (count($this->currentlyFading) > count($this->fadingOutColors)) {
            $this->message .= array_shift($this->currentlyFading);
        }

        $this->render();

        return $this;
    }

    public function close(): void
    {
        try {
            while (count($this->currentlyFading) > 0) {
                $this->message .= array_shift($this->currentlyFading);
                $this->render();
                usleep(25_000);
            }
        } finally {
            $this->showCursor();
        }
    }

    /** @return array<int, string> */
    public function lines(): array
    {
        $toFadeIn = [];

        foreach ($this->currentlyFading as $index => $message) {
            $toFadeIn[] = $this->fadingOutColors[$index]($message);
        }

        $lines = explode(PHP_EOL, $this->message.implode('', $toFadeIn));
        $finalLines = [];

        foreach ($lines as $line) {
            $finalLines = array_merge(
                $finalLines,
                $this->ansiWordwrap($line, $this->maxWidth),
            );
        }

        return $finalLines;
    }

    public function prompt(): mixed
    {
        throw new \RuntimeException('Stream cannot be prompted');
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): string
    {
        return $this->message.implode('', $this->currentlyFading);
    }

    /**
     * Get an array of closures that progressively fade text from full color to nearly invisible.
     *
     * @return array<int, \Closure(string): string>
     */
    protected function fadeOut(int $steps = 10): array
    {
        if (! static::terminal()->supportsTrueColor()) {
            return [
                fn (string $text) => $text,
                fn (string $text) => $this->dim($text),
            ];
        }

        $fg = static::terminal()->foregroundColor();
        $bg = static::terminal()->backgroundColor();

        return array_map(
            function (int $step) use ($fg, $bg, $steps) {
                $factor = 1 - ($step / $steps);
                $r = (int) ($bg[0] + ($fg[0] - $bg[0]) * $factor);
                $g = (int) ($bg[1] + ($fg[1] - $bg[1]) * $factor);
                $b = (int) ($bg[2] + ($fg[2] - $bg[2]) * $factor);

                return fn (string $text) => "\e[38;2;{$r};{$g};{$b}m{$text}\e[0m";
            },
            range(0, $steps - 1),
        );
    }
}
<?php

namespace Laravel\Prompts;

use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;

class NotifyPrompt extends Prompt
{
    /**
     * Create a new NotifyPrompt instance.
     */
    public function __construct(
        public string $title,
        public string $body = '',
        public string $subtitle = '',
        public string $sound = '',
        public string $icon = '',
    ) {
        //
    }

    /**
     * Send the notification.
     */
    public function prompt(): bool
    {
        return match (PHP_OS_FAMILY) {
            'Darwin' => $this->sendMacOS(),
            'Linux' => $this->sendLinux(),
            default => false,
        };
    }

    /**
     * Send a notification on macOS using osascript.
     */
    protected function sendMacOS(): bool
    {
        $script = 'display notification '.$this->escapeAppleScript($this->body);
        $script .= ' with title '.$this->escapeAppleScript($this->title);

        if ($this->subtitle !== '') {
            $script .= ' subtitle '.$this->escapeAppleScript($this->subtitle);
        }

        if ($this->sound !== '') {
            $script .= ' sound name '.$this->escapeAppleScript($this->sound);
        }

        return $this->execute(['osascript', '-e', $script]);
    }

    /**
     * Send a notification on Linux, trying available notifiers.
     */
    protected function sendLinux(): bool
    {
        $finder = new ExecutableFinder;

        if ($finder->find('notify-send') !== null) {
            return $this->sendLinuxNotifySend();
        }

        if ($finder->find('kdialog') !== null) {
            return $this->sendLinuxKDialog();
        }

        return false;
    }

    /**
     * Send a notification using notify-send.
     */
    protected function sendLinuxNotifySend(): bool
    {
        $command = ['notify-send'];

        if ($this->icon !== '') {
            $command[] = '--icon';
            $command[] = $this->icon;
        }

        $command[] = $this->title;

        if ($this->body !== '') {
            $command[] = $this->body;
        }

        return $this->execute($command);
    }

    /**
     * Send a notification using kdialog.
     */
    protected function sendLinuxKDialog(): bool
    {
        $message = $this->body !== '' ? "{$this->title}: {$this->body}" : $this->title;

        return $this->execute(['kdialog', '--passivepopup', $message, '5', '--title', $this->title]);
    }

    /**
     * Execute a command and return whether it was successful.
     *
     * @param  array<int, string>  $command
     */
    protected function execute(array $command): bool
    {
        $process = new Process($command);
        $process->run();

        return $process->isSuccessful();
    }

    /**
     * Escape a string for use in AppleScript.
     */
    protected function escapeAppleScript(string $value): string
    {
        return '"'.str_replace(['\\', '"'], ['\\\\', '\\"'], $value).'"';
    }

    /**
     * Send the notification.
     */
    public function display(): void
    {
        $this->prompt();
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }
}
<?php

namespace Laravel\Prompts\Output;

class BufferedConsoleOutput extends ConsoleOutput
{
    /**
     * The output buffer.
     */
    protected string $buffer = '';

    /**
     * Empties the buffer and returns its content.
     */
    public function fetch(): string
    {
        $content = $this->buffer;
        $this->buffer = '';

        return $content;
    }

    /**
     * Return the content of the buffer.
     */
    public function content(): string
    {
        return $this->buffer;
    }

    /**
     * Write to the output buffer.
     */
    protected function doWrite(string $message, bool $newline): void
    {
        $this->buffer .= $message;

        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }
    }

    /**
     * Write output directly, bypassing newline capture.
     */
    public function writeDirectly(string $message): void
    {
        $this->doWrite($message, false);
    }
}
<?php

namespace Laravel\Prompts\Output;

use Symfony\Component\Console\Output\ConsoleOutput as SymfonyConsoleOutput;

class ConsoleOutput extends SymfonyConsoleOutput
{
    /**
     * How many new lines were written by the last output.
     */
    protected int $newLinesWritten = 1;

    /**
     * How many new lines were written by the last output.
     */
    public function newLinesWritten(): int
    {
        return $this->newLinesWritten;
    }

    /**
     * Write the output and capture the number of trailing new lines.
     */
    protected function doWrite(string $message, bool $newline): void
    {
        parent::doWrite($message, $newline);

        if ($newline) {
            $message .= \PHP_EOL;
        }

        preg_match('/(?:\r?\n)*$/', $message, $matches);

        $trailingNewLines = substr_count($matches[0] ?? '', "\n");

        if (trim($message) === '') {
            $this->newLinesWritten += $trailingNewLines;
        } else {
            $this->newLinesWritten = $trailingNewLines;
        }
    }

    /**
     * Write output directly, bypassing newline capture.
     */
    public function writeDirectly(string $message): void
    {
        parent::doWrite($message, false);
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use InvalidArgumentException;

class SearchPrompt extends Prompt
{
    use Concerns\HasInfo;
    use Concerns\Scrolling;
    use Concerns\Truncation;
    use Concerns\TypedValue;

    /**
     * The cached matches.
     *
     * @var array<int|string, string>|null
     */
    protected ?array $matches = null;

    /**
     * Create a new SearchPrompt instance.
     *
     * @param  Closure(string): array<int|string, string>  $options
     */
    public function __construct(
        public string $label,
        public Closure $options,
        public string $placeholder = '',
        public int $scroll = 5,
        public mixed $validate = null,
        public string $hint = '',
        public bool|string $required = true,
        public ?Closure $transform = null,
        public string|Closure $info = '',
    ) {
        if ($this->required === false) {
            throw new InvalidArgumentException('Argument [required] must be true or a string.');
        }

        $this->trackTypedValue(submit: false, ignore: fn ($key) => Key::oneOf([Key::HOME, Key::END, Key::CTRL_A, Key::CTRL_E], $key) && $this->highlighted !== null);

        $this->initializeScrolling(null);

        $this->on('key', fn ($key) => match ($key) {
            Key::UP, Key::UP_ARROW, Key::SHIFT_TAB, Key::CTRL_P => $this->highlightPrevious(count($this->matches), true),
            Key::DOWN, Key::DOWN_ARROW, Key::TAB, Key::CTRL_N => $this->highlightNext(count($this->matches), true),
            Key::oneOf([Key::HOME, Key::CTRL_A], $key) => $this->highlighted !== null ? $this->highlight(0) : null,
            Key::oneOf([Key::END, Key::CTRL_E], $key) => $this->highlighted !== null ? $this->highlight(count($this->matches()) - 1) : null,
            Key::ENTER => $this->highlighted !== null ? $this->submit() : $this->search(),
            Key::oneOf([Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_B, Key::CTRL_F], $key) => $this->highlighted = null,
            default => $this->search(),
        });
    }

    /**
     * Get the value of the highlighted option.
     */
    public function highlightedValue(): int|string|null
    {
        return $this->value();
    }

    /**
     * Perform the search.
     */
    protected function search(): void
    {
        $this->state = 'searching';
        $this->highlighted = null;
        $this->render();
        $this->matches = null;
        $this->firstVisible = 0;
        $this->state = 'active';
    }

    /**
     * Get the entered value with a virtual cursor.
     */
    public function valueWithCursor(int $maxWidth): string
    {
        if ($this->highlighted !== null) {
            return $this->typedValue === ''
                ? $this->dim($this->truncate($this->placeholder, $maxWidth))
                : $this->truncate($this->typedValue, $maxWidth);
        }

        if ($this->typedValue === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        return $this->addCursor($this->typedValue, $this->cursorPosition, $maxWidth);
    }

    /**
     * Get options that match the input.
     *
     * @return array<string>
     */
    public function matches(): array
    {
        if (is_array($this->matches)) {
            return $this->matches;
        }

        return $this->matches = ($this->options)($this->typedValue);
    }

    /**
     * The currently visible matches.
     *
     * @return array<string>
     */
    public function visible(): array
    {
        return array_slice($this->matches(), $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Get the current search query.
     */
    public function searchValue(): string
    {
        return $this->typedValue;
    }

    /**
     * Get the selected value.
     */
    public function value(): int|string|null
    {
        if ($this->matches === null || $this->highlighted === null) {
            return null;
        }

        return array_is_list($this->matches)
            ? $this->matches[$this->highlighted]
            : array_keys($this->matches)[$this->highlighted];
    }

    /**
     * Get the selected label.
     */
    public function label(): ?string
    {
        return $this->matches[array_keys($this->matches)[$this->highlighted]] ?? null;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;
use InvalidArgumentException;

class SelectPrompt extends Prompt
{
    use Concerns\HasInfo;
    use Concerns\Scrolling;

    /**
     * The options for the select prompt.
     *
     * @var array<int|string, string>
     */
    public array $options;

    /**
     * Create a new SelectPrompt instance.
     *
     * @param  array<int|string, string>|Collection<int|string, string>  $options
     */
    public function __construct(
        public string $label,
        array|Collection $options,
        public int|string|null $default = null,
        public int $scroll = 5,
        public mixed $validate = null,
        public string $hint = '',
        public bool|string $required = true,
        public ?Closure $transform = null,
        public string|Closure $info = '',
    ) {
        if ($this->required === false) {
            throw new InvalidArgumentException('Argument [required] must be true or a string.');
        }

        $this->options = $options instanceof Collection ? $options->all() : $options;

        if ($this->default !== null) {
            if (array_is_list($this->options)) {
                $this->initializeScrolling(array_search($this->default, $this->options) ?: 0);
            } else {
                $this->initializeScrolling(array_search($this->default, array_keys($this->options)) ?: 0);
            }

            $this->scrollToHighlighted(count($this->options));
        } else {
            $this->initializeScrolling(0);
        }

        $this->on('key', fn ($key) => match ($key) {
            Key::UP, Key::UP_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::SHIFT_TAB, Key::CTRL_P, Key::CTRL_B, 'k', 'h' => $this->highlightPrevious(count($this->options)),
            Key::DOWN, Key::DOWN_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::TAB, Key::CTRL_N, Key::CTRL_F, 'j', 'l' => $this->highlightNext(count($this->options)),
            Key::oneOf([Key::HOME, Key::CTRL_A], $key) => $this->highlight(0),
            Key::oneOf([Key::END, Key::CTRL_E], $key) => $this->highlight(count($this->options) - 1),
            Key::ENTER => $this->submit(),
            default => null,
        });
    }

    /**
     * Get the value of the highlighted option.
     */
    public function highlightedValue(): int|string|null
    {
        if (array_is_list($this->options)) {
            return $this->options[$this->highlighted] ?? null;
        }

        return array_keys($this->options)[$this->highlighted] ?? null;
    }

    /**
     * Get the selected value.
     */
    public function value(): int|string|null
    {
        if (static::$interactive === false) {
            return $this->default;
        }

        if (array_is_list($this->options)) {
            return $this->options[$this->highlighted] ?? null;
        } else {
            return array_keys($this->options)[$this->highlighted];
        }
    }

    /**
     * Get the selected label.
     */
    public function label(): ?string
    {
        if (array_is_list($this->options)) {
            return $this->options[$this->highlighted] ?? null;
        } else {
            return $this->options[array_keys($this->options)[$this->highlighted]] ?? null;
        }
    }

    /**
     * The currently visible options.
     *
     * @return array<int|string, string>
     */
    public function visible(): array
    {
        return array_slice($this->options, $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Determine whether the given value is invalid when the prompt is required.
     */
    protected function isInvalidWhenRequired(mixed $value): bool
    {
        return $value === null;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;

class AutoCompletePrompt extends Prompt
{
    use Concerns\TypedValue;

    /**
     * The options for the autocomplete prompt.
     *
     * @var array<string>|Closure(string): (array<string>|Collection<int, string>)
     */
    public array|Closure $options;

    protected string $match = '';

    protected int $highlighted = 0;

    /**
     * @var array<string>|null
     */
    protected ?array $matches = null;

    /**
     * Create a new AutoCompletePrompt instance.
     *
     * @param  array<string>|Collection<int, string>|Closure(string): (array<string>|Collection<int, string>)  $options
     */
    public function __construct(
        public string $label,
        array|Collection|Closure $options = [],
        public string $placeholder = '',
        public string $default = '',
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
    ) {
        $this->options = $options instanceof Collection ? $options->all() : $options;

        $this->on('key', function ($key) {
            if (in_array($key, [Key::UP, Key::UP_ARROW])) {
                $matches = $this->matches();

                if (count($matches) > 0) {
                    $this->highlighted = ($this->highlighted - 1 + count($matches)) % count($matches);
                }

                return;
            }

            if (in_array($key, [Key::DOWN, Key::DOWN_ARROW])) {
                $matches = $this->matches();

                if (count($matches) > 0) {
                    $this->highlighted = ($this->highlighted + 1) % count($matches);
                }

                return;
            }

            if ($key === Key::TAB && $this->cursorPosition >= mb_strlen($this->typedValue)) {
                $match = $this->getMatch();

                if ($match !== '' && mb_strlen($match) > mb_strlen($this->value())) {
                    // Ghost text is showing — accept it
                    $this->typedValue = $match;
                    $this->cursorPosition = mb_strlen($match);
                } else {
                    // No ghost text — request suggestions
                    $this->matches = null;
                    $this->highlighted = 0;
                }

                return;
            }

            if (in_array($key, [Key::RIGHT, Key::RIGHT_ARROW]) && $this->cursorPosition >= mb_strlen($this->typedValue)) {
                $match = $this->getMatch();

                if ($match !== '') {
                    $this->typedValue = $match;
                    $this->cursorPosition = mb_strlen($match);
                }

                return;
            }

            // Any other key resets the highlight and match cache
            $this->highlighted = 0;
            $this->matches = null;
        });

        $this->trackTypedValue(
            $default,
            ignore: fn ($key) => in_array($key, [Key::UP, Key::UP_ARROW, Key::DOWN, Key::DOWN_ARROW]),
        );
    }

    /**
     * Get the entered value with a virtual cursor.
     */
    public function valueWithCursor(int $maxWidth): string
    {
        if ($this->value() === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        $this->match = $this->getMatch();

        $ghostText = '';

        if ($this->match !== '' && mb_strlen($this->match) > mb_strlen($this->value())) {
            $ghostText = mb_substr($this->match, mb_strlen($this->value()));
        }

        // When cursor is at the end and there's ghost text, make the first
        // ghost character the inverted cursor so it flows naturally.
        if ($ghostText !== '' && $this->cursorPosition >= mb_strlen($this->value())) {
            $cursorChar = mb_substr($ghostText, 0, 1);
            $remainingGhost = mb_substr($ghostText, 1);

            return $this->value()
                .$this->inverse($cursorChar)
                .$this->dim($remainingGhost);
        }

        return $this->addCursor(
            $this->value(),
            $this->cursorPosition,
            $maxWidth
        ).$this->dim($ghostText);
    }

    /**
     * Get the current matches for the typed value.
     *
     * @return array<string>
     */
    public function matches(): array
    {
        if (is_array($this->matches)) {
            return $this->matches;
        }

        if ($this->options instanceof Closure) {
            $options = ($this->options)($this->value());

            return $this->matches = array_values($options instanceof Collection ? $options->all() : $options);
        }

        return $this->matches = array_values(array_filter(
            $this->options,
            fn ($option) => str_starts_with(strtolower($option), strtolower($this->value())),
        ));
    }

    /**
     * Get the current match.
     */
    protected function getMatch(): string
    {
        return $this->matches()[$this->highlighted] ?? '';
    }
}
<?php

namespace Laravel\Prompts;

use Closure;

class TextPrompt extends Prompt
{
    use Concerns\TypedValue;

    /**
     * Create a new TextPrompt instance.
     */
    public function __construct(
        public string $label,
        public string $placeholder = '',
        public string $default = '',
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
    ) {
        $this->trackTypedValue($default);
    }

    /**
     * Get the entered value with a virtual cursor.
     */
    public function valueWithCursor(int $maxWidth): string
    {
        if ($this->value() === '') {
            return $this->dim($this->addCursor($this->placeholder, 0, $maxWidth));
        }

        return $this->addCursor($this->value(), $this->cursorPosition, $maxWidth);
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;

class DataTablePrompt extends Prompt
{
    use Concerns\Scrolling;
    use Concerns\TypedValue;

    /**
     * The table headers.
     *
     * @var array<int, string|array<int, string>>
     */
    public array $headers;

    /**
     * The table rows.
     *
     * @var array<int|string, array<int, string>>
     */
    public array $rows;

    /**
     * The cached filtered rows.
     *
     * @var array<int|string, array<int, string>>|null
     */
    protected ?array $filteredCache = null;

    /**
     * The previous search query (for cache invalidation).
     */
    protected string $previousQuery = '';

    /**
     * Create a new DataTable instance.
     *
     * @param  array<int, string|array<int, string>>|Collection<int, string|array<int, string>>  $headers
     * @param  array<int|string, array<int, string>>|Collection<int|string, array<int, string>>|null  $rows
     *
     * @phpstan-param ($rows is null ? list<list<string>>|Collection<int, list<string>> : list<string|list<string>>|Collection<int, string|list<string>>) $headers
     */
    public function __construct(
        array|Collection $headers = [],
        array|Collection|null $rows = null,
        public int $scroll = 10,
        public string $label = '',
        public string $hint = '',
        public bool|string $required = false,
        public mixed $validate = null,
        public ?Closure $transform = null,
        public ?Closure $filter = null,
    ) {
        if ($rows === null) {
            $rows = $headers;
            $headers = [];
        }

        $this->headers = $headers instanceof Collection ? $headers->all() : $headers;
        $this->rows = $rows instanceof Collection ? $rows->all() : $rows;

        $this->initializeScrolling(0);

        $this->trackTypedValue(
            submit: false,
            ignore: fn ($key) => $this->state !== 'search',
        );

        $this->on('key', fn ($key) => match ($this->state) {
            'search' => $this->handleSearchKey($key),
            default => $this->handleBrowseKey($key),
        });
    }

    /**
     * Handle key presses in browse mode.
     */
    protected function handleBrowseKey(string $key): void
    {
        $total = count($this->filteredRows());

        match ($key) {
            Key::UP, Key::UP_ARROW, Key::CTRL_P => $this->highlightPrevious($total),
            Key::DOWN, Key::DOWN_ARROW, Key::CTRL_N => $this->highlightNext($total),
            Key::PAGE_UP => $this->highlight(max(0, $this->highlighted - $this->scroll)),
            Key::PAGE_DOWN => $this->highlight(min($total - 1, $this->highlighted + $this->scroll)),
            Key::oneOf([Key::HOME, Key::CTRL_A], $key) => $this->highlight(0),
            Key::oneOf([Key::END, Key::CTRL_E], $key) => $this->highlight(max(0, $total - 1)),
            Key::ENTER => $total > 0 ? $this->submit() : null,
            '/' => $this->enterSearch(),
            default => null,
        };
    }

    /**
     * Handle key presses in search mode.
     */
    protected function handleSearchKey(string $key): void
    {
        match ($key) {
            Key::ENTER => $this->exitSearch(),
            Key::ESCAPE => $this->cancelSearch(),
            default => $this->search(),
        };
    }

    /**
     * Enter search mode.
     */
    protected function enterSearch(): void
    {
        $this->state = 'search';
        $this->typedValue = '';
        $this->cursorPosition = 0;
    }

    /**
     * Exit search mode, keeping the filtered results.
     */
    protected function exitSearch(): void
    {
        $this->state = 'active';
        $this->highlighted = 0;
        $this->firstVisible = 0;
    }

    /**
     * Cancel search, clearing the query and showing all rows.
     */
    protected function cancelSearch(): void
    {
        $this->state = 'active';
        $this->typedValue = '';
        $this->cursorPosition = 0;
        $this->filteredCache = null;
        $this->previousQuery = '';
        $this->highlighted = 0;
        $this->firstVisible = 0;
    }

    /**
     * Handle typing in search mode.
     */
    protected function search(): void
    {
        $this->filteredCache = null;
        $this->highlighted = 0;
        $this->firstVisible = 0;
    }

    /**
     * Get the filtered rows based on the current search query.
     *
     * @return array<int|string, array<int, string>>
     */
    public function filteredRows(): array
    {
        if ($this->filteredCache !== null && $this->previousQuery === $this->typedValue) {
            return $this->filteredCache;
        }

        $this->previousQuery = $this->typedValue;

        if ($this->typedValue === '') {
            return $this->filteredCache = $this->rows;
        }

        if ($this->filter !== null) {
            return $this->filteredCache = array_filter(
                $this->rows,
                fn ($row) => ($this->filter)($row, $this->typedValue),
            );
        }

        return $this->filteredCache = array_filter(
            $this->rows,
            fn ($row) => str_contains(
                mb_strtolower(implode(' ', $row)),
                mb_strtolower($this->typedValue),
            ),
        );
    }

    /**
     * The currently visible rows.
     *
     * @return array<int|string, array<int, string>>
     */
    public function visible(): array
    {
        return array_slice($this->filteredRows(), $this->firstVisible, $this->scroll, preserve_keys: true);
    }

    /**
     * Get the current search query.
     */
    public function searchValue(): string
    {
        return $this->typedValue;
    }

    /**
     * Get the search query with a virtual cursor.
     */
    public function searchWithCursor(int $maxWidth): string
    {
        if ($this->typedValue === '') {
            return $this->dim($this->addCursor('', 0, $maxWidth));
        }

        return $this->addCursor($this->typedValue, $this->cursorPosition, $maxWidth);
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): mixed
    {
        if ($this->highlighted === null) {
            return null;
        }

        $filtered = $this->filteredRows();
        $keys = array_keys($filtered);

        if (! isset($keys[$this->highlighted])) {
            return null;
        }

        return $keys[$this->highlighted];
    }

    /**
     * Get the selected row for display purposes.
     *
     * @return array<int, string>|null
     */
    public function selectedRow(): ?array
    {
        if ($this->highlighted === null) {
            return null;
        }

        $filtered = $this->filteredRows();
        $keys = array_keys($filtered);

        if (! isset($keys[$this->highlighted])) {
            return null;
        }

        return $filtered[$keys[$this->highlighted]];
    }
}
<?php

namespace Laravel\Prompts;

class Key
{
    const UP = "\e[A";

    const SHIFT_UP = "\e[1;2A";

    const PAGE_UP = "\e[5~";

    const DOWN = "\e[B";

    const SHIFT_DOWN = "\e[1;2B";

    const PAGE_DOWN = "\e[6~";

    const RIGHT = "\e[C";

    const LEFT = "\e[D";

    const UP_ARROW = "\eOA";

    const DOWN_ARROW = "\eOB";

    const RIGHT_ARROW = "\eOC";

    const LEFT_ARROW = "\eOD";

    const ESCAPE = "\e";

    const DELETE = "\e[3~";

    const BACKSPACE = "\177";

    const ENTER = "\n";

    const SPACE = ' ';

    const TAB = "\t";

    const SHIFT_TAB = "\e[Z";

    const HOME = ["\e[1~", "\eOH", "\e[H", "\e[7~"];

    const END = ["\e[4~", "\eOF", "\e[F", "\e[8~"];

    /**
     * Cancel/SIGINT
     */
    const CTRL_C = "\x03";

    /**
     * Previous/Up
     */
    const CTRL_P = "\x10";

    /**
     * Next/Down
     */
    const CTRL_N = "\x0E";

    /**
     * Forward/Right
     */
    const CTRL_F = "\x06";

    /**
     * Back/Left
     */
    const CTRL_B = "\x02";

    /**
     * Backspace
     */
    const CTRL_H = "\x08";

    /**
     * Home
     */
    const CTRL_A = "\x01";

    /**
     * EOF
     */
    const CTRL_D = "\x04";

    /**
     * End
     */
    const CTRL_E = "\x05";

    /**
     * Negative affirmation
     */
    const CTRL_U = "\x15";

    const OPTION_BACKSPACE = "\e\177";

    /**
     * Checks for the constant values for the given match and returns the match
     *
     * @param  array<string|array<string>>  $keys
     */
    public static function oneOf(array $keys, string $match): ?string
    {
        foreach ($keys as $key) {
            if (is_array($key) && static::oneOf($key, $match) !== null) {
                return $match;
            } elseif ($key === $match) {
                return $match;
            }
        }

        return null;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Illuminate\Support\Collection;

if (! function_exists('\Laravel\Prompts\text')) {
    /**
     * Prompt the user for text input.
     */
    function text(
        string $label,
        string $placeholder = '',
        string $default = '',
        bool|string $required = false,
        mixed $validate = null,
        string $hint = '',
        ?Closure $transform = null,
    ): string {
        return (new TextPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\autocomplete')) {
    /**
     * Prompt the user for text input with auto-completion.
     *
     * @param  array<string>|Collection<int, string>|Closure(string): (array<string>|Collection<int, string>)  $options
     */
    function autocomplete(
        string $label,
        array|Collection|Closure $options = [],
        string $placeholder = '',
        string $default = '',
        bool|string $required = false,
        mixed $validate = null,
        string $hint = '',
        ?Closure $transform = null,
    ): string {
        return (new AutoCompletePrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\number')) {
    /**
     * Prompt the user for number input.
     */
    function number(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?int $min = null, ?int $max = null, ?int $step = null): int|string
    {
        return (new NumberPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\textarea')) {
    /**
     * Prompt the user for multiline text input.
     */
    function textarea(
        string $label,
        string $placeholder = '',
        string $default = '',
        bool|string $required = false,
        mixed $validate = null,
        string $hint = '',
        int $rows = 5,
        ?Closure $transform = null,
    ): string {
        return (new TextareaPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\password')) {
    /**
     * Prompt the user for input, hiding the value.
     */
    function password(
        string $label,
        string $placeholder = '',
        bool|string $required = false,
        mixed $validate = null,
        string $hint = '',
        ?Closure $transform = null,
    ): string {
        return (new PasswordPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\select')) {
    /**
     * Prompt the user to select an option.
     *
     * @param  array<int|string, string>|Collection<int|string, string>  $options
     * @param  true|string  $required
     */
    function select(
        string $label,
        array|Collection $options,
        int|string|null $default = null,
        int $scroll = 5,
        mixed $validate = null,
        string $hint = '',
        bool|string $required = true,
        ?Closure $transform = null,
        string|Closure $info = '',
    ): int|string {
        return (new SelectPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\multiselect')) {
    /**
     * Prompt the user to select multiple options.
     *
     * @param  array<int|string, string>|Collection<int|string, string>  $options
     * @param  array<int|string>|Collection<int, int|string>  $default
     * @return array<int|string>
     */
    function multiselect(
        string $label,
        array|Collection $options,
        array|Collection $default = [],
        int $scroll = 5,
        bool|string $required = false,
        mixed $validate = null,
        string $hint = 'Use the space bar to select options.',
        ?Closure $transform = null,
        string|Closure $info = '',
    ): array {
        return (new MultiSelectPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\confirm')) {
    /**
     * Prompt the user to confirm an action.
     */
    function confirm(
        string $label,
        bool $default = true,
        string $yes = 'Yes',
        string $no = 'No',
        bool|string $required = false,
        mixed $validate = null,
        string $hint = '',
        ?Closure $transform = null,
    ): bool {
        return (new ConfirmPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\pause')) {
    /**
     * Prompt the user to continue or cancel after pausing.
     */
    function pause(string $message = 'Press enter to continue...'): bool
    {
        return (new PausePrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\clear')) {
    /**
     * Clear the terminal.
     */
    function clear(): void
    {
        (new Clear)->display();
    }
}

if (! function_exists('\Laravel\Prompts\suggest')) {
    /**
     * Prompt the user for text input with auto-completion.
     *
     * @param  array<string>|Collection<int, string>|Closure(string): array<string>  $options
     */
    function suggest(
        string $label,
        array|Collection|Closure $options,
        string $placeholder = '',
        string $default = '',
        int $scroll = 5,
        bool|string $required = false,
        mixed $validate = null,
        string $hint = '',
        ?Closure $transform = null,
        string|Closure $info = '',
    ): string {
        return (new SuggestPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\search')) {
    /**
     * Allow the user to search for an option.
     *
     * @param  Closure(string): array<int|string, string>  $options
     * @param  true|string  $required
     */
    function search(
        string $label,
        Closure $options,
        string $placeholder = '',
        int $scroll = 5,
        mixed $validate = null,
        string $hint = '',
        bool|string $required = true,
        ?Closure $transform = null,
        string|Closure $info = '',
    ): int|string {
        return (new SearchPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\multisearch')) {
    /**
     * Allow the user to search for multiple option.
     *
     * @param  Closure(string): array<int|string, string>  $options
     * @return array<int|string>
     */
    function multisearch(
        string $label,
        Closure $options,
        string $placeholder = '',
        int $scroll = 5,
        bool|string $required = false,
        mixed $validate = null,
        string $hint = 'Use the space bar to select options.',
        ?Closure $transform = null,
        string|Closure $info = '',
    ): array {
        return (new MultiSearchPrompt(...get_defined_vars()))->prompt();
    }
}

if (! function_exists('\Laravel\Prompts\spin')) {
    /**
     * Render a spinner while the given callback is executing.
     *
     * @template TReturn of mixed
     *
     * @param  Closure(): TReturn  $callback
     * @return TReturn
     */
    function spin(Closure $callback, string $message = ''): mixed
    {
        return (new Spinner($message))->spin($callback);
    }
}

if (! function_exists('\Laravel\Prompts\note')) {
    /**
     * Display a note.
     */
    function note(string $message, ?string $type = null): void
    {
        (new Note($message, $type))->display();
    }
}

if (! function_exists('\Laravel\Prompts\error')) {
    /**
     * Display an error.
     */
    function error(string $message): void
    {
        (new Note($message, 'error'))->display();
    }
}

if (! function_exists('\Laravel\Prompts\warning')) {
    /**
     * Display a warning.
     */
    function warning(string $message): void
    {
        (new Note($message, 'warning'))->display();
    }
}

if (! function_exists('\Laravel\Prompts\alert')) {
    /**
     * Display an alert.
     */
    function alert(string $message): void
    {
        (new Note($message, 'alert'))->display();
    }
}

if (! function_exists('\Laravel\Prompts\info')) {
    /**
     * Display an informational message.
     */
    function info(string $message): void
    {
        (new Note($message, 'info'))->display();
    }
}

if (! function_exists('\Laravel\Prompts\intro')) {
    /**
     * Display an introduction.
     */
    function intro(string $message): void
    {
        (new Note($message, 'intro'))->display();
    }
}

if (! function_exists('\Laravel\Prompts\outro')) {
    /**
     * Display a closing message.
     */
    function outro(string $message): void
    {
        (new Note($message, 'outro'))->display();
    }
}

if (! function_exists('\Laravel\Prompts\notify')) {
    /**
     * Send a notification to the user. (macOS and Linux only)
     *
     * The icon option is Linux only. The subtitle and sound options are macOS only.
     *
     * @param  string  $subtitle  macOS only
     * @param  string  $sound  macOS only
     * @param  string  $icon  Linux only
     */
    function notify(string $title, string $body = '', string $subtitle = '', string $sound = '', string $icon = ''): void
    {
        (new NotifyPrompt(...get_defined_vars()))->display();
    }
}

if (! function_exists('\Laravel\Prompts\table')) {
    /**
     * Display a table.
     *
     * @param  array<int, string|array<int, string>>|Collection<int, string|array<int, string>>  $headers
     * @param  array<int, array<int, string>>|Collection<int, array<int, string>>  $rows
     */
    function table(array|Collection $headers = [], array|Collection|null $rows = null): void
    {
        (new Table($headers, $rows))->display();
    }
}

if (! function_exists('\Laravel\Prompts\grid')) {
    /**
     * Display a grid.
     *
     * @param  array<int, string>|Collection<int, string>  $items
     */
    function grid(array|Collection $items = [], ?int $maxWidth = null): void
    {
        (new Grid($items, $maxWidth))->display();
    }
}

if (! function_exists('\Laravel\Prompts\progress')) {
    /**
     * Display a progress bar.
     *
     * @template TSteps of iterable<mixed>|int
     * @template TReturn
     *
     * @param  TSteps  $steps
     * @param  ?Closure((TSteps is int ? int : value-of<TSteps>), Progress<TSteps>): TReturn  $callback
     * @return ($callback is null ? Progress<TSteps> : array<TReturn>)
     */
    function progress(
        string $label,
        iterable|int $steps,
        ?Closure $callback = null,
        string $hint = '',
    ): array|Progress {
        $progress = new Progress($label, $steps, $hint);

        if ($callback !== null) {
            return $progress->map($callback);
        }

        return $progress;
    }
}

if (! function_exists('\Laravel\Prompts\form')) {
    function form(): FormBuilder
    {
        return new FormBuilder;
    }
}

if (! function_exists('\Laravel\Prompts\title')) {
    /**
     * Update the title of the terminal.
     */
    function title(string $title): void
    {
        (new Title($title))->display();
    }
}

if (! function_exists('\Laravel\Prompts\stream')) {
    /**
     * Display a stream of text.
     */
    function stream(): Stream
    {
        return new Stream;
    }
}

if (! function_exists('\Laravel\Prompts\task')) {
    /**
     * Display a task with a spinner and live output.
     *
     * @template TReturn of mixed
     *
     * @param  Closure(Support\Logger): TReturn  $callback
     * @return TReturn
     */
    function task(string $label, Closure $callback, ?int $limit = null, bool $keepSummary = false, ?string $subLabel = null): mixed
    {
        return (new Task($label, $limit ?? 10, $keepSummary, $subLabel))->run($callback);
    }
}

if (! function_exists('\Laravel\Prompts\datatable')) {
    /**
     * Display an interactive data table.
     *
     * @param  array<int, string|array<int, string>>|Collection<int, string|array<int, string>>  $headers
     * @param  array<int|string, array<int, string>>|Collection<int|string, array<int, string>>|null  $rows
     */
    function datatable(
        array|Collection $headers = [],
        array|Collection|null $rows = null,
        int $scroll = 10,
        string $label = '',
        string $hint = '',
        bool|string $required = false,
        mixed $validate = null,
        ?Closure $transform = null,
        ?Closure $filter = null,
    ): mixed {
        return (new DataTablePrompt(
            headers: $headers,
            rows: $rows,
            scroll: $scroll,
            label: $label,
            hint: $hint,
            required: $required,
            validate: $validate,
            transform: $transform,
            filter: $filter,
        ))->prompt();
    }
}
<?php

namespace Laravel\Prompts\Exceptions;

use RuntimeException;

class FormRevertedException extends RuntimeException
{
    //
}
<?php

namespace Laravel\Prompts\Exceptions;

use RuntimeException;

class NonInteractiveValidationException extends RuntimeException
{
    //
}
<?php

namespace Laravel\Prompts;

use Closure;
use RuntimeException;

class Spinner extends Prompt
{
    /**
     * How long to wait between rendering each frame.
     */
    public int $interval = 100;

    /**
     * The number of times the spinner has been rendered.
     */
    public int $count = 0;

    /**
     * Whether the spinner can only be rendered once.
     */
    public bool $static = false;

    /**
     * The process ID after forking.
     */
    protected int $pid;

    /**
     * Create a new Spinner instance.
     */
    public function __construct(public string $message = '')
    {
        //
    }

    /**
     * Render the spinner and execute the callback.
     *
     * @template TReturn of mixed
     *
     * @param  Closure(): TReturn  $callback
     * @return TReturn
     */
    public function spin(Closure $callback): mixed
    {
        $this->capturePreviousNewLines();

        if (! (function_exists('pcntl_fork') && function_exists('posix_kill'))) {
            return $this->renderStatically($callback);
        }

        $originalAsync = pcntl_async_signals(true);

        pcntl_signal(SIGINT, fn () => exit());

        try {
            $this->hideCursor();
            $this->render();

            $this->pid = pcntl_fork();

            if ($this->pid === 0) {
                while (true) { // @phpstan-ignore-line
                    $this->render();

                    $this->count++;

                    usleep($this->interval * 1000);
                }
            } else {
                $result = $callback();

                $this->resetTerminal($originalAsync);

                return $result;
            }
        } catch (\Throwable $e) {
            $this->resetTerminal($originalAsync);

            throw $e;
        }
    }

    /**
     * Reset the terminal.
     */
    protected function resetTerminal(bool $originalAsync): void
    {
        pcntl_async_signals($originalAsync);
        pcntl_signal(SIGINT, SIG_DFL);

        $this->eraseRenderedLines();
    }

    /**
     * Render a static version of the spinner.
     *
     * @template TReturn of mixed
     *
     * @param  Closure(): TReturn  $callback
     * @return TReturn
     */
    protected function renderStatically(Closure $callback): mixed
    {
        $this->static = true;

        try {
            $this->hideCursor();
            $this->render();

            $result = $callback();
        } finally {
            $this->eraseRenderedLines();
        }

        return $result;
    }

    /**
     * Disable prompting for input.
     *
     * @throws RuntimeException
     */
    public function prompt(): never
    {
        throw new RuntimeException('Spinner cannot be prompted.');
    }

    /**
     * Get the current value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }

    /**
     * Clear the lines rendered by the spinner.
     */
    protected function eraseRenderedLines(): void
    {
        $lines = explode(PHP_EOL, $this->prevFrame);
        $this->moveCursor(-999, -count($lines) + 1);
        $this->eraseDown();
    }

    /**
     * Clean up after the spinner.
     */
    public function __destruct()
    {
        if (! empty($this->pid)) {
            posix_kill($this->pid, SIGHUP);
        }

        parent::__destruct();
    }
}
<?php

namespace Laravel\Prompts\Concerns;

trait HasSpinner
{
    /**
     * The frames of the spinner (single dot moving around the perimeter).
     *
     * @var array<string>
     */
    protected array $frames = ['⠂', '⠒', '⠐', '⠰', '⠠', '⠤', '⠄', '⠆'];

    /**
     * The frame to render when the spinner is static.
     */
    protected string $staticFrame = '⠶';

    /**
     * The interval between frames.
     */
    protected int $interval = 75;

    public function spinnerFrame(int $count): string
    {
        return $this->frames[$count % count($this->frames)];
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Laravel\Prompts\Exceptions\NonInteractiveValidationException;

trait Interactivity
{
    /**
     * Whether to render the prompt interactively.
     */
    protected static bool $interactive;

    /**
     * Set interactive mode.
     */
    public static function interactive(bool $interactive = true): void
    {
        static::$interactive = $interactive;
    }

    /**
     * Return the default value if it passes validation.
     */
    protected function default(): mixed
    {
        $default = $this->value();

        $this->validate($default);

        if ($this->state === 'error') {
            throw new NonInteractiveValidationException($this->error);
        }

        return $default;
    }
}
<?php

namespace Laravel\Prompts\Concerns;

trait Cursor
{
    /**
     * Indicates if the cursor has been hidden.
     */
    protected static bool $cursorHidden = false;

    /**
     * Hide the cursor.
     */
    public function hideCursor(): void
    {
        static::writeDirectly("\e[?25l");

        static::$cursorHidden = true;
    }

    /**
     * Show the cursor.
     */
    public function showCursor(): void
    {
        static::writeDirectly("\e[?25h");

        static::$cursorHidden = false;
    }

    /**
     * Restore the cursor if it was hidden.
     */
    public function restoreCursor(): void
    {
        if (static::$cursorHidden) {
            $this->showCursor();
        }
    }

    /**
     * Move the cursor.
     */
    public function moveCursor(int $x, int $y = 0): void
    {
        $sequence = '';

        if ($x < 0) {
            $sequence .= "\e[".abs($x).'D'; // Left
        } elseif ($x > 0) {
            $sequence .= "\e[{$x}C"; // Right
        }

        if ($y < 0) {
            $sequence .= "\e[".abs($y).'A'; // Up
        } elseif ($y > 0) {
            $sequence .= "\e[{$y}B"; // Down
        }

        static::writeDirectly($sequence);
    }

    /**
     * Move the cursor to the given column.
     */
    public function moveCursorToColumn(int $column): void
    {
        static::writeDirectly("\e[{$column}G");
    }

    /**
     * Move the cursor up by the given number of lines.
     */
    public function moveCursorUp(int $lines): void
    {
        static::writeDirectly("\e[{$lines}A");
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Laravel\Prompts\Output\BufferedConsoleOutput;

use function Termwind\render;
use function Termwind\renderUsing;

trait Termwind
{
    protected function termwind(string $html)
    {
        renderUsing($output = new BufferedConsoleOutput);

        render($html);

        return $this->restoreEscapeSequences($output->fetch());
    }

    protected function restoreEscapeSequences(string $string)
    {
        return preg_replace('/\[(\d+)m/', "\e[".'\1m', $string);
    }
}
<?php

namespace Laravel\Prompts\Concerns;

trait Erase
{
    /**
     * Erase the given number of lines downwards from the cursor position.
     */
    public function eraseLines(int $count): void
    {
        $clear = '';
        for ($i = 0; $i < $count; $i++) {
            $clear .= "\e[2K".($i < $count - 1 ? "\e[{$count}A" : '');
        }

        if ($count) {
            $clear .= "\e[G";
        }

        static::writeDirectly($clear);
    }

    /**
     * Erase from cursor until end of screen.
     */
    public function eraseDown(): void
    {
        static::writeDirectly("\e[J");
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Closure;

trait HasInfo
{
    /**
     * Get the resolved info text.
     */
    public function infoText(): string
    {
        if ($this->info instanceof Closure) {
            return ($this->info)($this->highlightedValue()) ?? '';
        }

        return $this->info;
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Laravel\Prompts\Output\BufferedConsoleOutput;
use Laravel\Prompts\Terminal;
use PHPUnit\Framework\Assert;
use RuntimeException;

trait FakesInputOutput
{
    /**
     * Fake the terminal and queue key presses to be simulated.
     *
     * @param  array<string>  $keys
     */
    public static function fake(array $keys = []): void
    {
        // Force interactive mode when testing because we will be mocking the terminal.
        static::interactive();

        $mock = \Mockery::mock(Terminal::class);

        $mock->shouldReceive('write')->byDefault();
        $mock->shouldReceive('exit')->byDefault();
        $mock->shouldReceive('setTty')->byDefault();
        $mock->shouldReceive('restoreTty')->byDefault();
        $mock->shouldReceive('cols')->byDefault()->andReturn(80);
        $mock->shouldReceive('lines')->byDefault()->andReturn(24);
        $mock->shouldReceive('initDimensions')->byDefault();
        $mock->shouldReceive('supportsTrueColor')->byDefault()->andReturn(false);

        static::fakeKeyPresses($keys, function (string $key) use ($mock): void {
            $mock->shouldReceive('read')->once()->andReturn($key);
        });

        static::$terminal = $mock;

        self::setOutput(new BufferedConsoleOutput);
    }

    /**
     * Implementation of the looping mechanism for simulating key presses.
     *
     * By ignoring the `$callable` parameter which contains the default logic
     * for simulating fake key presses, we can use a custom implementation
     * to emit key presses instead, allowing us to use different inputs.
     *
     * @param  array<string>  $keys
     * @param  callable(string $key): void  $callable
     */
    public static function fakeKeyPresses(array $keys, callable $callable): void
    {
        foreach ($keys as $key) {
            $callable($key);
        }
    }

    /**
     * Assert that the output contains the given string.
     */
    public static function assertOutputContains(string $string): void
    {
        Assert::assertStringContainsString($string, static::content());
    }

    /**
     * Assert that the output doesn't contain the given string.
     */
    public static function assertOutputDoesntContain(string $string): void
    {
        Assert::assertStringNotContainsString($string, static::content());
    }

    /**
     * Assert that the stripped output contains the given string.
     */
    public static function assertStrippedOutputContains(string $string): void
    {
        Assert::assertStringContainsString($string, static::strippedContent());
    }

    /**
     * Assert that the stripped output doesn't contain the given string.
     */
    public static function assertStrippedOutputDoesntContain(string $string): void
    {
        Assert::assertStringNotContainsString($string, static::strippedContent());
    }

    /**
     * Get the buffered console output.
     */
    public static function content(): string
    {
        if (! static::output() instanceof BufferedConsoleOutput) {
            throw new RuntimeException('Prompt must be faked before accessing content.');
        }

        return static::output()->content();
    }

    /**
     * Get the buffered console output, stripped of escape sequences.
     */
    public static function strippedContent(): string
    {
        return preg_replace("/\e\[[0-9;?]*[A-Za-z]/", '', static::content());
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Closure;

trait Events
{
    /**
     * The registered event listeners.
     *
     * @var array<string, array<int, Closure>>
     */
    protected array $listeners = [];

    /**
     * Register an event listener.
     */
    public function on(string $event, Closure $callback): void
    {
        $this->listeners[$event][] = $callback;
    }

    /**
     * Emit an event.
     */
    public function emit(string $event, mixed ...$data): void
    {
        foreach ($this->listeners[$event] ?? [] as $listener) {
            $listener(...$data);
        }
    }

    /**
     * Clean the event listeners.
     */
    public function clearListeners(): void
    {
        $this->listeners = [];
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use InvalidArgumentException;
use Laravel\Prompts\AutoCompletePrompt;
use Laravel\Prompts\Clear;
use Laravel\Prompts\ConfirmPrompt;
use Laravel\Prompts\DataTablePrompt;
use Laravel\Prompts\Grid;
use Laravel\Prompts\MultiSearchPrompt;
use Laravel\Prompts\MultiSelectPrompt;
use Laravel\Prompts\Note;
use Laravel\Prompts\NumberPrompt;
use Laravel\Prompts\PasswordPrompt;
use Laravel\Prompts\PausePrompt;
use Laravel\Prompts\Progress;
use Laravel\Prompts\Prompt;
use Laravel\Prompts\SearchPrompt;
use Laravel\Prompts\SelectPrompt;
use Laravel\Prompts\Spinner;
use Laravel\Prompts\Stream;
use Laravel\Prompts\SuggestPrompt;
use Laravel\Prompts\Table;
use Laravel\Prompts\Task;
use Laravel\Prompts\TextareaPrompt;
use Laravel\Prompts\TextPrompt;
use Laravel\Prompts\Themes\Default\AutoCompletePromptRenderer;
use Laravel\Prompts\Themes\Default\ClearRenderer;
use Laravel\Prompts\Themes\Default\ConfirmPromptRenderer;
use Laravel\Prompts\Themes\Default\DataTableRenderer;
use Laravel\Prompts\Themes\Default\GridRenderer;
use Laravel\Prompts\Themes\Default\MultiSearchPromptRenderer;
use Laravel\Prompts\Themes\Default\MultiSelectPromptRenderer;
use Laravel\Prompts\Themes\Default\NoteRenderer;
use Laravel\Prompts\Themes\Default\NumberPromptRenderer;
use Laravel\Prompts\Themes\Default\PasswordPromptRenderer;
use Laravel\Prompts\Themes\Default\PausePromptRenderer;
use Laravel\Prompts\Themes\Default\ProgressRenderer;
use Laravel\Prompts\Themes\Default\SearchPromptRenderer;
use Laravel\Prompts\Themes\Default\SelectPromptRenderer;
use Laravel\Prompts\Themes\Default\SpinnerRenderer;
use Laravel\Prompts\Themes\Default\StreamRenderer;
use Laravel\Prompts\Themes\Default\SuggestPromptRenderer;
use Laravel\Prompts\Themes\Default\TableRenderer;
use Laravel\Prompts\Themes\Default\TaskRenderer;
use Laravel\Prompts\Themes\Default\TextareaPromptRenderer;
use Laravel\Prompts\Themes\Default\TextPromptRenderer;
use Laravel\Prompts\Themes\Default\TitleRenderer;
use Laravel\Prompts\Title;

trait Themes
{
    /**
     * The name of the active theme.
     */
    protected static string $theme = 'default';

    /**
     * The available themes.
     *
     * @var array<string, array<class-string<Prompt>, class-string<object&callable>>>
     */
    protected static array $themes = [
        'default' => [
            TextPrompt::class => TextPromptRenderer::class,
            NumberPrompt::class => NumberPromptRenderer::class,
            TextareaPrompt::class => TextareaPromptRenderer::class,
            PasswordPrompt::class => PasswordPromptRenderer::class,
            SelectPrompt::class => SelectPromptRenderer::class,
            MultiSelectPrompt::class => MultiSelectPromptRenderer::class,
            ConfirmPrompt::class => ConfirmPromptRenderer::class,
            PausePrompt::class => PausePromptRenderer::class,
            SearchPrompt::class => SearchPromptRenderer::class,
            MultiSearchPrompt::class => MultiSearchPromptRenderer::class,
            SuggestPrompt::class => SuggestPromptRenderer::class,
            Spinner::class => SpinnerRenderer::class,
            Note::class => NoteRenderer::class,
            Table::class => TableRenderer::class,
            Progress::class => ProgressRenderer::class,
            Clear::class => ClearRenderer::class,
            Grid::class => GridRenderer::class,
            AutoCompletePrompt::class => AutoCompletePromptRenderer::class,
            Title::class => TitleRenderer::class,
            Stream::class => StreamRenderer::class,
            Task::class => TaskRenderer::class,
            DataTablePrompt::class => DataTableRenderer::class,
        ],
    ];

    /**
     * Get or set the active theme.
     *
     * @throws InvalidArgumentException
     */
    public static function theme(?string $name = null): string
    {
        if ($name === null) {
            return static::$theme;
        }

        if (! isset(static::$themes[$name])) {
            throw new InvalidArgumentException("Prompt theme [{$name}] not found.");
        }

        return static::$theme = $name;
    }

    /**
     * Add a new theme.
     *
     * @param  array<class-string<Prompt>, class-string<object&callable>>  $renderers
     */
    public static function addTheme(string $name, array $renderers): void
    {
        if ($name === 'default') {
            throw new InvalidArgumentException('The default theme cannot be overridden.');
        }

        static::$themes[$name] = $renderers;
    }

    /**
     * Get the renderer for the current prompt.
     */
    protected function getRenderer(): callable
    {
        $class = get_class($this);

        return new (static::$themes[static::$theme][$class] ?? static::$themes['default'][$class])($this);
    }

    /**
     * Render the prompt using the active theme.
     */
    protected function renderTheme(): string
    {
        $renderer = $this->getRenderer();

        return $renderer($this);
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use IntlBreakIterator;
use Laravel\Prompts\Key;

trait TypedValue
{
    /**
     * The value that has been typed.
     */
    protected string $typedValue = '';

    /**
     * The position of the virtual cursor.
     */
    protected int $cursorPosition = 0;

    /**
     * Track the value as the user types.
     */
    protected function trackTypedValue(string $default = '', bool $submit = true, ?callable $ignore = null, bool $allowNewLine = false): void
    {
        $this->typedValue = $default;

        if (strlen($this->typedValue) > 0) {
            $this->cursorPosition = mb_strlen($this->typedValue);
        }

        $this->on('key', function (string $key) use ($submit, $ignore, $allowNewLine): void {
            if ($key !== '' &&
                ($key[0] === "\e" || in_array($key, [Key::CTRL_B, Key::CTRL_F, Key::CTRL_A, Key::CTRL_E]))
            ) {
                if ($ignore !== null && $ignore($key)) {
                    return;
                }

                match ($key) {
                    Key::LEFT, Key::LEFT_ARROW, Key::CTRL_B => $this->cursorPosition = max(0, $this->cursorPosition - 1),
                    Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_F => $this->cursorPosition = min(mb_strlen($this->typedValue), $this->cursorPosition + 1),
                    Key::oneOf([Key::HOME, Key::CTRL_A], $key) => $this->cursorPosition = 0,
                    Key::oneOf([Key::END, Key::CTRL_E], $key) => $this->cursorPosition = mb_strlen($this->typedValue),
                    Key::DELETE => $this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition).mb_substr($this->typedValue, $this->cursorPosition + 1),
                    Key::OPTION_BACKSPACE => $this->deleteWordBackward(),
                    default => null,
                };

                return;
            }

            // Keys may be buffered.
            foreach (mb_str_split($key) as $key) {
                if ($ignore !== null && $ignore($key)) {
                    return;
                }

                if ($key === Key::ENTER) {
                    if ($submit) {
                        $this->submit();

                        return;
                    }

                    if ($allowNewLine) {
                        $this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition).PHP_EOL.mb_substr($this->typedValue, $this->cursorPosition);
                        $this->cursorPosition++;
                    }
                } elseif ($key === Key::BACKSPACE || $key === Key::CTRL_H) {
                    if ($this->cursorPosition === 0) {
                        return;
                    }

                    $this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition - 1).mb_substr($this->typedValue, $this->cursorPosition);
                    $this->cursorPosition--;
                } elseif (mb_ord($key) >= 32) {
                    $this->typedValue = mb_substr($this->typedValue, 0, $this->cursorPosition).$key.mb_substr($this->typedValue, $this->cursorPosition);
                    $this->cursorPosition++;
                }
            }
        });
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): string
    {
        return $this->typedValue;
    }

    /**
     * Add a virtual cursor to the value and truncate if necessary.
     */
    protected function addCursor(string $value, int $cursorPosition, ?int $maxWidth = null): string
    {
        $before = mb_substr($value, 0, $cursorPosition);
        $current = mb_substr($value, $cursorPosition, 1);
        $after = mb_substr($value, $cursorPosition + 1);

        $cursor = mb_strlen($current) && $current !== PHP_EOL ? $current : ' ';

        $spaceBefore = $maxWidth < 0 || $maxWidth === null ? mb_strwidth($before) : $maxWidth - mb_strwidth($cursor) - (mb_strwidth($after) > 0 ? 1 : 0);
        [$truncatedBefore, $wasTruncatedBefore] = mb_strwidth($before) > $spaceBefore
            ? [$this->trimWidthBackwards($before, 0, $spaceBefore - 1), true]
            : [$before, false];

        $spaceAfter = $maxWidth < 0 || $maxWidth === null ? mb_strwidth($after) : $maxWidth - ($wasTruncatedBefore ? 1 : 0) - mb_strwidth($truncatedBefore) - mb_strwidth($cursor);
        [$truncatedAfter, $wasTruncatedAfter] = mb_strwidth($after) > $spaceAfter
            ? [mb_strimwidth($after, 0, $spaceAfter - 1), true]
            : [$after, false];

        return ($wasTruncatedBefore ? $this->dim('…') : '')
            .$truncatedBefore
            .$this->inverse($cursor)
            .($current === PHP_EOL ? PHP_EOL : '')
            .$truncatedAfter
            .($wasTruncatedAfter ? $this->dim('…') : '');
    }

    /**
     * Get a truncated string with the specified width from the end.
     */
    private function trimWidthBackwards(string $string, int $start, int $width): string
    {
        $reversed = implode('', array_reverse(mb_str_split($string, 1)));

        $trimmed = mb_strimwidth($reversed, $start, $width);

        return implode('', array_reverse(mb_str_split($trimmed, 1)));
    }

    /**
     * Delete from the start of the current word (before cursor) through the cursor.
     */
    protected function deleteWordBackward(): void
    {
        if ($this->cursorPosition === 0) {
            return;
        }

        $start = $this->findWordStartBeforeCursor();
        $this->typedValue = mb_substr($this->typedValue, 0, $start).mb_substr($this->typedValue, $this->cursorPosition);
        $this->cursorPosition = $start;
    }

    /**
     * Character offset of the word boundary immediately before the cursor (Intl + punctuation).
     * Punctuation (e.g. . - _) is treated as a word boundary so "word.word" deletes in two steps.
     */
    protected function findWordStartBeforeCursor(): int
    {
        $before = mb_substr($this->typedValue, 0, $this->cursorPosition);

        if ($before === '') {
            return 0;
        }

        $regexStart = $this->findLastWordStartByLettersAndNumbers($before);

        if (extension_loaded('intl')) {
            $iterator = IntlBreakIterator::createWordInstance('');
            $iterator->setText($before);
            $endByte = strlen($before);
            $wordStartByte = $iterator->preceding($endByte);

            if ($wordStartByte === IntlBreakIterator::DONE) {
                return $regexStart;
            }

            $intlStart = mb_strlen(substr($before, 0, $wordStartByte), 'UTF-8');

            return max($intlStart, $regexStart);
        }

        return $regexStart;
    }

    /**
     * Start (character offset) of the last run of letters/numbers in string (punctuation breaks words).
     */
    protected function findLastWordStartByLettersAndNumbers(string $before): int
    {
        if (preg_match_all('/((?:\p{L}\p{M}*|\p{N})+)/u', $before, $m, PREG_OFFSET_CAPTURE) && $m[1] !== []) {
            $last = end($m[1]);

            return mb_strlen(substr($before, 0, $last[1]), 'UTF-8');
        }

        return 0;
    }
}
<?php

namespace Laravel\Prompts\Concerns;

trait Colors
{
    /**
     * Reset all colors and styles.
     */
    public function reset(string $text): string
    {
        return "\e[0m{$text}\e[0m";
    }

    /**
     * Make the text bold.
     */
    public function bold(string $text): string
    {
        return "\e[1m{$text}\e[22m";
    }

    /**
     * Make the text dim.
     */
    public function dim(string $text): string
    {
        return "\e[2m{$text}\e[22m";
    }

    /**
     * Make the text italic.
     */
    public function italic(string $text): string
    {
        return "\e[3m{$text}\e[23m";
    }

    /**
     * Underline the text.
     */
    public function underline(string $text): string
    {
        return "\e[4m{$text}\e[24m";
    }

    /**
     * Invert the text and background colors.
     */
    public function inverse(string $text): string
    {
        return "\e[7m{$text}\e[27m";
    }

    /**
     * Hide the text.
     */
    public function hidden(string $text): string
    {
        return "\e[8m{$text}\e[28m";
    }

    /**
     * Strike through the text.
     */
    public function strikethrough(string $text): string
    {
        return "\e[9m{$text}\e[29m";
    }

    /**
     * Set the text color to black.
     */
    public function black(string $text): string
    {
        return "\e[30m{$text}\e[39m";
    }

    /**
     * Set the text color to red.
     */
    public function red(string $text): string
    {
        return "\e[31m{$text}\e[39m";
    }

    /**
     * Set the text color to green.
     */
    public function green(string $text): string
    {
        return "\e[32m{$text}\e[39m";
    }

    /**
     * Set the text color to yellow.
     */
    public function yellow(string $text): string
    {
        return "\e[33m{$text}\e[39m";
    }

    /**
     * Set the text color to blue.
     */
    public function blue(string $text): string
    {
        return "\e[34m{$text}\e[39m";
    }

    /**
     * Set the text color to magenta.
     */
    public function magenta(string $text): string
    {
        return "\e[35m{$text}\e[39m";
    }

    /**
     * Set the text color to cyan.
     */
    public function cyan(string $text): string
    {
        return "\e[36m{$text}\e[39m";
    }

    /**
     * Set the text color to white.
     */
    public function white(string $text): string
    {
        return "\e[37m{$text}\e[39m";
    }

    /**
     * Set the text background to black.
     */
    public function bgBlack(string $text): string
    {
        return "\e[40m{$text}\e[49m";
    }

    /**
     * Set the text background to red.
     */
    public function bgRed(string $text): string
    {
        return "\e[41m{$text}\e[49m";
    }

    /**
     * Set the text background to green.
     */
    public function bgGreen(string $text): string
    {
        return "\e[42m{$text}\e[49m";
    }

    /**
     * Set the text background to yellow.
     */
    public function bgYellow(string $text): string
    {
        return "\e[43m{$text}\e[49m";
    }

    /**
     * Set the text background to blue.
     */
    public function bgBlue(string $text): string
    {
        return "\e[44m{$text}\e[49m";
    }

    /**
     * Set the text background to magenta.
     */
    public function bgMagenta(string $text): string
    {
        return "\e[45m{$text}\e[49m";
    }

    /**
     * Set the text background to cyan.
     */
    public function bgCyan(string $text): string
    {
        return "\e[46m{$text}\e[49m";
    }

    /**
     * Set the text background to white.
     */
    public function bgWhite(string $text): string
    {
        return "\e[47m{$text}\e[49m";
    }

    /**
     * Set the text color to gray.
     */
    public function gray(string $text): string
    {
        return "\e[90m{$text}\e[39m";
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use InvalidArgumentException;

trait Truncation
{
    /**
     * Truncate a value with an ellipsis if it exceeds the given width.
     */
    protected function truncate(string $string, int $width): string
    {
        if ($width <= 0) {
            throw new InvalidArgumentException("Width [{$width}] must be greater than zero.");
        }

        return mb_strwidth($string) <= $width ? $string : (mb_strimwidth($string, 0, $width - 1).'…');
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Closure;
use RuntimeException;

trait Fallback
{
    /**
     * Whether to fallback to a custom implementation
     */
    protected static bool $shouldFallback = false;

    /**
     * The fallback implementations.
     *
     * @var array<class-string, Closure($this): mixed>
     */
    protected static array $fallbacks = [];

    /**
     * Enable the fallback implementation.
     */
    public static function fallbackWhen(bool $condition): void
    {
        static::$shouldFallback = $condition || static::$shouldFallback;
    }

    /**
     * Whether the prompt should fallback to a custom implementation.
     */
    public static function shouldFallback(): bool
    {
        return static::$shouldFallback && isset(static::$fallbacks[static::class]);
    }

    /**
     * Set the fallback implementation.
     *
     * @param  Closure($this): mixed  $fallback
     */
    public static function fallbackUsing(Closure $fallback): void
    {
        static::$fallbacks[static::class] = $fallback;
    }

    /**
     * Call the registered fallback implementation.
     */
    public function fallback(): mixed
    {
        $fallback = static::$fallbacks[static::class] ?? null;

        if ($fallback === null) {
            throw new RuntimeException('No fallback implementation registered for ['.static::class.']');
        }

        return $fallback($this);
    }
}
<?php

namespace Laravel\Prompts\Concerns;

use Laravel\Prompts\Themes\Contracts\Scrolling as ScrollingRenderer;

trait Scrolling
{
    /**
     * The number of items to display before scrolling.
     */
    public int $scroll;

    /**
     * The index of the highlighted option.
     */
    public ?int $highlighted;

    /**
     * The index of the first visible option.
     */
    public int $firstVisible = 0;

    /**
     * Initialize scrolling.
     */
    protected function initializeScrolling(?int $highlighted = null): void
    {
        $this->highlighted = $highlighted;

        $this->reduceScrollingToFitTerminal();
    }

    /**
     * Reduce the scroll property to fit the terminal height.
     */
    protected function reduceScrollingToFitTerminal(): void
    {
        $reservedLines = ($renderer = $this->getRenderer()) instanceof ScrollingRenderer ? $renderer->reservedLines() : 0;

        $this->scroll = max(1, min($this->scroll, $this->terminal()->lines() - $reservedLines));
    }

    /**
     * Highlight the given index.
     */
    protected function highlight(?int $index): void
    {
        $this->highlighted = $index;

        if ($this->highlighted === null) {
            return;
        }

        if ($this->highlighted < $this->firstVisible) {
            $this->firstVisible = $this->highlighted;
        } elseif ($this->highlighted > $this->firstVisible + $this->scroll - 1) {
            $this->firstVisible = $this->highlighted - $this->scroll + 1;
        }
    }

    /**
     * Highlight the previous entry, or wrap around to the last entry.
     */
    protected function highlightPrevious(int $total, bool $allowNull = false): void
    {
        if ($total === 0) {
            return;
        }

        if ($this->highlighted === null) {
            $this->highlight($total - 1);
        } elseif ($this->highlighted === 0) {
            $this->highlight($allowNull ? null : ($total - 1));
        } else {
            $this->highlight($this->highlighted - 1);
        }
    }

    /**
     * Highlight the next entry, or wrap around to the first entry.
     */
    protected function highlightNext(int $total, bool $allowNull = false): void
    {
        if ($total === 0) {
            return;
        }

        if ($this->highlighted === $total - 1) {
            $this->highlight($allowNull ? null : 0);
        } else {
            $this->highlight(($this->highlighted ?? -1) + 1);
        }
    }

    /**
     * Center the highlighted option.
     */
    protected function scrollToHighlighted(int $total): void
    {
        if ($this->highlighted < $this->scroll) {
            return;
        }

        $remaining = $total - $this->highlighted - 1;
        $halfScroll = (int) floor($this->scroll / 2);
        $endOffset = max(0, $halfScroll - $remaining);

        if ($this->scroll % 2 === 0) {
            $endOffset--;
        }

        $this->firstVisible = $this->highlighted - $halfScroll - $endOffset;
    }
}
<?php

namespace Laravel\Prompts;

class Note extends Prompt
{
    /**
     * Create a new Note instance.
     */
    public function __construct(public string $message, public ?string $type = null)
    {
        //
    }

    /**
     * Display the note.
     */
    public function display(): void
    {
        $this->prompt();
    }

    /**
     * Display the note.
     */
    public function prompt(): bool
    {
        $this->capturePreviousNewLines();

        if (static::shouldFallback()) {
            return $this->fallback();
        }

        $this->state = 'submit';

        static::output()->write($this->renderTheme());

        return true;
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;
use Laravel\Prompts\Support\Logger;
use Laravel\Prompts\Themes\Default\Concerns\InteractsWithStrings;
use RuntimeException;

class Task extends Prompt
{
    use InteractsWithStrings;

    /**
     * The minimum width for the longest line calculation.
     */
    protected int $minWidth = 0;

    /**
     * How long to wait between rendering each frame.
     */
    public int $interval = 100;

    /**
     * The number of times the task has been rendered.
     */
    public int $count = 0;

    /**
     * Whether the task can only be rendered once.
     */
    public bool $static = false;

    /**
     * The process ID after forking.
     */
    protected int $pid;

    /**
     * The socket for IPC communication.
     *
     * @var resource|null
     */
    protected $socket;

    /**
     * Pre-wrapped log lines for the scrolling output area.
     *
     * @var array<int, string>
     */
    public array $logs = [];

    /**
     * Stable status messages (success, warning, error).
     *
     * @var list<array{type: string, message: string}>
     */
    public array $stableMessages = [];

    /**
     * The maximum number of stable messages to display.
     */
    public int $maxStableMessages = 10;

    /**
     * The identifier for the task.
     */
    public string $identifier = '';

    /**
     * Whether the task has finished.
     */
    public bool $finished = false;

    /**
     * Buffer for incomplete lines from non-blocking socket reads.
     */
    protected string $buffer = '';

    /**
     * The log index where the current partial started, or null if not streaming.
     */
    protected ?int $partialStartIndex = null;

    /**
     * Create a new Task instance.
     */
    public function __construct(
        public string $label = '',
        public int $limit = 10,
        public bool $keepSummary = false,
        public ?string $subLabel = null,
    ) {
        $this->identifier = uniqid();
    }

    /**
     * Render the task and execute the callback.
     *
     * @template TReturn of mixed
     *
     * @param  Closure(Logger): TReturn  $callback
     * @return TReturn
     */
    public function run(Closure $callback): mixed
    {
        $this->limit = min($this->limit, $this->terminal()->lines() - 10);
        $this->recalculateMaxStableMessages();

        $this->capturePreviousNewLines();

        if (! (function_exists('pcntl_fork') && function_exists('posix_kill'))) {
            return $this->renderStatically($callback);
        }

        $originalAsync = pcntl_async_signals(true);

        pcntl_signal(SIGINT, fn () => exit());

        try {
            $this->hideCursor();
            $this->render();

            $sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);

            if ($sockets === false) {
                return $this->renderStatically($callback);
            }

            $this->pid = pcntl_fork();

            if ($this->pid === 0) {
                fclose($sockets[1]);
                $childSocket = $sockets[0];
                stream_set_blocking($childSocket, false);

                while (true) { // @phpstan-ignore-line
                    $this->receiveMessages($childSocket);

                    if (! $this->finished) {
                        $this->render();
                        $this->count++;
                    }

                    usleep($this->interval * 1000);
                }
            } else {
                fclose($sockets[0]);
                $this->socket = $sockets[1];

                $logger = new Logger($this->identifier, $this->socket);
                $result = $callback($logger);

                if ($this->socket !== null) {
                    // Send a reset message to the parent process to reset the terminal.
                    fwrite($this->socket, $this->identifier.'_'.'reset:'.($originalAsync ? 1 : 0).PHP_EOL);
                    usleep($this->interval * 2000);
                }

                return $result;
            }
        } catch (\Throwable $e) {
            $this->resetTerminal($originalAsync);

            throw $e;
        }
    }

    /**
     * Receive and process messages from the parent process.
     *
     * @param  resource  $socket
     */
    protected function receiveMessages($socket): void
    {
        $prefix = preg_quote($this->identifier, '/');

        while (($data = fgets($socket)) !== false) {
            // Buffer incomplete lines from non-blocking reads.
            if (! str_ends_with($data, PHP_EOL)) {
                $this->buffer .= $data;

                continue;
            }

            $line = rtrim($this->buffer.$data, PHP_EOL);
            $this->buffer = '';

            if ($line === '') {
                continue;
            }

            // Check for typed messages: {id}_{type}:{content}
            if (preg_match('/^'.$prefix.'_(success|warning|error|label|sublabel|reset|partial|commitpartial):(.*)/', $line, $matches)) {
                $type = $matches[1];
                $content = $matches[2];

                if ($type === 'reset') {
                    $this->resetTerminal((bool) $content);

                    continue;
                }

                if ($type === 'partial') {
                    $this->replacePartialLines($content);

                    continue;
                }

                if ($type === 'commitpartial') {
                    $this->partialStartIndex = null;

                    continue;
                }

                if ($type === 'label') {
                    $this->label = $content;
                } elseif ($type === 'sublabel') {
                    $this->subLabel = $content;
                    $this->recalculateMaxStableMessages();
                } else {
                    $this->stableMessages[] = ['type' => $type, 'message' => $content];
                    $this->logs = [];
                    $this->partialStartIndex = null;
                }

                while (count($this->stableMessages) > $this->maxStableMessages) {
                    array_shift($this->stableMessages);
                }

                continue;
            }

            // Regular log line — strip cursor-reset control sequences.
            $line = preg_replace('/\e\[(?:1)?G\e\[2K/', '', $line);

            // Wrap and add to ring buffer.
            $this->addLogLines($line);
        }
    }

    /**
     * Wrap a log line and append to the ring buffer, trimming to the limit.
     */
    protected function addLogLines(string $line): void
    {
        $width = $this->terminal()->cols() - 10;
        $plainText = $this->stripEscapeSequences($line);

        if (mb_strwidth($plainText) > $width) {
            $wrapped = $this->ansiWordwrap($line, $width);
        } else {
            $wrapped = [$line];
        }

        array_push($this->logs, ...$wrapped);

        while (count($this->logs) > $this->limit) {
            array_shift($this->logs);
        }
    }

    /**
     * Replace the in-progress partial lines with the full accumulated text.
     */
    protected function replacePartialLines(string $text): void
    {
        if ($this->partialStartIndex === null) {
            $this->partialStartIndex = count($this->logs);
        }

        // Truncate back to where the partial started.
        $this->logs = array_slice($this->logs, 0, $this->partialStartIndex);

        // Wrap and append the full accumulated partial text.
        $width = $this->terminal()->cols() - 10;
        $plainText = $this->stripEscapeSequences($text);

        if (mb_strwidth($plainText) > $width) {
            $wrapped = $this->ansiWordwrap($text, $width);
        } else {
            $wrapped = [$text];
        }

        array_push($this->logs, ...$wrapped);

        while (count($this->logs) > $this->limit) {
            array_shift($this->logs);
            $this->partialStartIndex = max(0, $this->partialStartIndex - 1);
        }
    }

    /**
     * Recompute the stable-message budget based on the current sub-label state.
     */
    protected function recalculateMaxStableMessages(): void
    {
        $reserved = 2 + ($this->subLabel !== null && $this->subLabel !== '' ? 1 : 0);
        $this->maxStableMessages = max(0, $this->terminal()->lines() - 10 - $this->limit - $reserved);
    }

    /**
     * Reset the terminal.
     */
    protected function resetTerminal(bool $originalAsync): void
    {
        $this->finished = true;

        pcntl_async_signals($originalAsync);
        pcntl_signal(SIGINT, SIG_DFL);

        if ($this->socket !== null) {
            fclose($this->socket);
            $this->socket = null;
        }

        if ($this->keepSummary && count($this->stableMessages) > 0) {
            $this->render();

            return;
        }

        $this->eraseRenderedLines();
    }

    /**
     * Render a static version of the task.
     *
     * @template TReturn of mixed
     *
     * @param  Closure(Logger): TReturn  $callback
     * @return TReturn
     */
    protected function renderStatically(Closure $callback): mixed
    {
        $this->static = true;

        try {
            $this->hideCursor();
            $this->render();

            $logger = new Logger($this->identifier);
            $result = $callback($logger);
        } finally {
            $this->eraseRenderedLines();
        }

        return $result;
    }

    /**
     * Disable prompting for input.
     *
     * @throws RuntimeException
     */
    public function prompt(): never
    {
        throw new RuntimeException('Task cannot be prompted.');
    }

    /**
     * Get the current value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }

    /**
     * Clear the lines rendered by the task.
     */
    protected function eraseRenderedLines(): void
    {
        $lines = explode(PHP_EOL, $this->prevFrame);
        $this->moveCursor(-999, -count($lines) + 1);
        $this->eraseDown();
    }

    /**
     * Clean up after the task.
     */
    public function __destruct()
    {
        if (! empty($this->pid)) {
            posix_kill($this->pid, SIGHUP);
        }

        parent::__destruct();
    }
}
<?php

namespace Laravel\Prompts;

use Illuminate\Support\Collection;

class Table extends Prompt
{
    /**
     * The table headers.
     *
     * @var array<int, string|array<int, string>>
     */
    public array $headers;

    /**
     * The table rows.
     *
     * @var array<int, array<int, string>>
     */
    public array $rows;

    /**
     * Create a new Table instance.
     *
     * @param  array<int, string|array<int, string>>|Collection<int, string|array<int, string>>  $headers
     * @param  array<int, array<int, string>>|Collection<int, array<int, string>>  $rows
     *
     * @phpstan-param ($rows is null ? list<list<string>>|Collection<int, list<string>> : list<string|list<string>>|Collection<int, string|list<string>>) $headers
     */
    public function __construct(array|Collection $headers = [], array|Collection|null $rows = null)
    {
        if ($rows === null) {
            $rows = $headers;
            $headers = [];
        }

        $this->headers = $headers instanceof Collection ? $headers->all() : $headers;
        $this->rows = $rows instanceof Collection ? $rows->all() : $rows;
    }

    /**
     * Display the table.
     */
    public function display(): void
    {
        $this->prompt();
    }

    /**
     * Display the table.
     */
    public function prompt(): bool
    {
        $this->capturePreviousNewLines();

        $this->state = 'submit';

        static::output()->write($this->renderTheme());

        return true;
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return true;
    }
}
<?php

namespace Laravel\Prompts;

use Closure;

class ConfirmPrompt extends Prompt
{
    /**
     * Whether the prompt has been confirmed.
     */
    public bool $confirmed;

    /**
     * Create a new ConfirmPrompt instance.
     */
    public function __construct(
        public string $label,
        public bool $default = true,
        public string $yes = 'Yes',
        public string $no = 'No',
        public bool|string $required = false,
        public mixed $validate = null,
        public string $hint = '',
        public ?Closure $transform = null,
    ) {
        $this->confirmed = $default;

        $this->on('key', fn ($key) => match ($key) {
            'y' => $this->confirmed = true,
            'n' => $this->confirmed = false,
            Key::TAB, Key::UP, Key::UP_ARROW, Key::DOWN, Key::DOWN_ARROW, Key::LEFT, Key::LEFT_ARROW, Key::RIGHT, Key::RIGHT_ARROW, Key::CTRL_P, Key::CTRL_F, Key::CTRL_N, Key::CTRL_B, 'h', 'j', 'k', 'l' => $this->confirmed = ! $this->confirmed,
            Key::ENTER => $this->submit(),
            default => null,
        });
    }

    /**
     * Get the value of the prompt.
     */
    public function value(): bool
    {
        return $this->confirmed;
    }

    /**
     * Get the label of the selected option.
     */
    public function label(): string
    {
        return $this->confirmed ? $this->yes : $this->no;
    }
}
<?php

// autoload.php @generated by Composer

if (PHP_VERSION_ID < 50600) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, $err);
        } elseif (!headers_sent()) {
            echo $err;
        }
    }
    throw new RuntimeException($err);
}

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInita408f660b5e9690e372ddcb0227a007b::getLoader();
<?php

namespace Psr\SimpleCache;

/**
 * Interface used for all types of exceptions thrown by the implementing library.
 */
interface CacheException extends \Throwable
{
}
<?php

namespace Psr\SimpleCache;

interface CacheInterface
{
    /**
     * Fetches a value from the cache.
     *
     * @param string $key     The unique key of this item in the cache.
     * @param mixed  $default Default value to return if the key does not exist.
     *
     * @return mixed The value of the item from the cache, or $default in case of cache miss.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function get(string $key, mixed $default = null): mixed;

    /**
     * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
     *
     * @param string                 $key   The key of the item to store.
     * @param mixed                  $value The value of the item to store, must be serializable.
     * @param null|int|\DateInterval $ttl   Optional. The TTL value of this item. If no value is sent and
     *                                      the driver supports TTL then the library may set a default value
     *                                      for it or let the driver take care of that.
     *
     * @return bool True on success and false on failure.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool;

    /**
     * Delete an item from the cache by its unique key.
     *
     * @param string $key The unique cache key of the item to delete.
     *
     * @return bool True if the item was successfully removed. False if there was an error.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function delete(string $key): bool;

    /**
     * Wipes clean the entire cache's keys.
     *
     * @return bool True on success and false on failure.
     */
    public function clear(): bool;

    /**
     * Obtains multiple cache items by their unique keys.
     *
     * @param iterable<string> $keys    A list of keys that can be obtained in a single operation.
     * @param mixed            $default Default value to return for keys that do not exist.
     *
     * @return iterable<string, mixed> A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if $keys is neither an array nor a Traversable,
     *   or if any of the $keys are not a legal value.
     */
    public function getMultiple(iterable $keys, mixed $default = null): iterable;

    /**
     * Persists a set of key => value pairs in the cache, with an optional TTL.
     *
     * @param iterable               $values A list of key => value pairs for a multiple-set operation.
     * @param null|int|\DateInterval $ttl    Optional. The TTL value of this item. If no value is sent and
     *                                       the driver supports TTL then the library may set a default value
     *                                       for it or let the driver take care of that.
     *
     * @return bool True on success and false on failure.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if $values is neither an array nor a Traversable,
     *   or if any of the $values are not a legal value.
     */
    public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool;

    /**
     * Deletes multiple cache items in a single operation.
     *
     * @param iterable<string> $keys A list of string-based keys to be deleted.
     *
     * @return bool True if the items were successfully removed. False if there was an error.
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if $keys is neither an array nor a Traversable,
     *   or if any of the $keys are not a legal value.
     */
    public function deleteMultiple(iterable $keys): bool;

    /**
     * Determines whether an item is present in the cache.
     *
     * NOTE: It is recommended that has() is only to be used for cache warming type purposes
     * and not to be used within your live applications operations for get/set, as this method
     * is subject to a race condition where your has() will return true and immediately after,
     * another script can remove it making the state of your app out of date.
     *
     * @param string $key The cache item key.
     *
     * @return bool
     *
     * @throws \Psr\SimpleCache\InvalidArgumentException
     *   MUST be thrown if the $key string is not a legal value.
     */
    public function has(string $key): bool;
}
<?php

namespace Psr\SimpleCache;

/**
 * Exception interface for invalid cache arguments.
 *
 * When an invalid argument is passed it must throw an exception which implements
 * this interface
 */
interface InvalidArgumentException extends CacheException
{
}
<?php

namespace Psr\Container;

/**
 * No entry was found in the container.
 */
interface NotFoundExceptionInterface extends ContainerExceptionInterface
{
}
<?php

declare(strict_types=1);

namespace Psr\Container;

/**
 * Describes the interface of a container that exposes methods to read its entries.
 */
interface ContainerInterface
{
    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get(string $id);

    /**
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return bool
     */
    public function has(string $id): bool;
}
<?php

namespace Psr\Container;

use Throwable;

/**
 * Base interface representing a generic exception in a container.
 */
interface ContainerExceptionInterface extends Throwable
{
}
The MIT License (MIT)

Copyright (c) 2013-2016 container-interop
Copyright (c) 2016 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<?php

namespace Psr\Clock;

use DateTimeImmutable;

interface ClockInterface
{
    /**
     * Returns the current time as a DateTimeImmutable Object
     */
    public function now(): DateTimeImmutable;
}
Copyright (c) 2017 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\MessageFormatter;

use Symfony\Component\Translation\Formatter\MessageFormatterInterface;

if (!class_exists(LazyMessageFormatter::class, false)) {
    abstract class LazyMessageFormatter implements MessageFormatterInterface
    {
        public function format(string $message, string $locale, array $parameters = []): string
        {
            return $this->formatter->format(
                $message,
                $this->transformLocale($locale),
                $parameters
            );
        }
    }
}
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\MessageFormatter;

use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;

if (!class_exists(LazyMessageFormatter::class, false)) {
    abstract class LazyMessageFormatter implements MessageFormatterInterface, ChoiceMessageFormatterInterface
    {
        abstract protected function transformLocale(?string $locale): ?string;

        public function format($message, $locale, array $parameters = [])
        {
            return $this->formatter->format(
                $message,
                $this->transformLocale($locale),
                $parameters
            );
        }

        public function choiceFormat($message, $number, $locale, array $parameters = [])
        {
            return $this->formatter->choiceFormat($message, $number, $locale, $parameters);
        }
    }
}
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use DatePeriod;

if (!class_exists(DatePeriodBase::class, false)) {
    class DatePeriodBase extends DatePeriod
    {
    }
}
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use DatePeriod;

if (!class_exists(DatePeriodBase::class, false)) {
    class DatePeriodBase extends DatePeriod
    {
        /**
         * Period start in PHP < 8.2.
         *
         * @var CarbonInterface
         *
         * @deprecated PHP 8.2 this property is no longer in sync with the actual period start.
         */
        protected $start;

        /**
         * Period end in PHP < 8.2.
         *
         * @var CarbonInterface|null
         *
         * @deprecated PHP 8.2 this property is no longer in sync with the actual period end.
         */
        protected $end;

        /**
         * Period current iterated date in PHP < 8.2.
         *
         * @var CarbonInterface|null
         *
         * @deprecated PHP 8.2 this property is no longer in sync with the actual period current iterated date.
         */
        protected $current;

        /**
         * Period interval in PHP < 8.2.
         *
         * @var CarbonInterval|null
         *
         * @deprecated PHP 8.2 this property is no longer in sync with the actual period interval.
         */
        protected $interval;

        /**
         * Period recurrences in PHP < 8.2.
         *
         * @var int|float|null
         *
         * @deprecated PHP 8.2 this property is no longer in sync with the actual period recurrences.
         */
        protected $recurrences;

        /**
         * Period start included option in PHP < 8.2.
         *
         * @var bool
         *
         * @deprecated PHP 8.2 this property is no longer in sync with the actual period start included option.
         */
        protected $include_start_date;
    }
}
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Symfony\Component\Translation\MessageCatalogueInterface;

if (!class_exists(LazyTranslator::class, false)) {
    class LazyTranslator extends AbstractTranslator implements TranslatorStrongTypeInterface
    {
        public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
        {
            return $this->translate($id, $parameters, $domain, $locale);
        }

        public function getFromCatalogue(MessageCatalogueInterface $catalogue, string $id, string $domain = 'messages')
        {
            $messages = $this->getPrivateProperty($catalogue, 'messages');

            if (isset($messages[$domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX][$id])) {
                return $messages[$domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX][$id];
            }

            if (isset($messages[$domain][$id])) {
                return $messages[$domain][$id];
            }

            $fallbackCatalogue = $this->getPrivateProperty($catalogue, 'fallbackCatalogue');

            if ($fallbackCatalogue !== null) {
                return $this->getFromCatalogue($fallbackCatalogue, $id, $domain);
            }

            return $id;
        }

        private function getPrivateProperty($instance, string $field)
        {
            return (function (string $field) {
                return $this->$field;
            })->call($instance, $field);
        }
    }
}
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

if (!class_exists(LazyTranslator::class, false)) {
    class LazyTranslator extends AbstractTranslator
    {
        /**
         * Returns the translation.
         *
         * @param string|null $id
         * @param array       $parameters
         * @param string|null $domain
         * @param string|null $locale
         *
         * @return string
         */
        public function trans($id, array $parameters = [], $domain = null, $locale = null)
        {
            return $this->translate($id, $parameters, $domain, $locale);
        }
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Closure;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use InvalidArgumentException;
use ReflectionMethod;
use RuntimeException;
use Symfony\Contracts\Translation\TranslatorInterface;
use Throwable;

/**
 * A factory to generate Carbon instances with common settings.
 *
 * <autodoc generated by `composer phpdoc`>
 *
 * @method bool                canBeCreatedFromFormat(?string $date, string $format)                                                                                Checks if the (date)time string is in a given format and valid to create a
 *                                                                                                                                                                  new instance.
 * @method ?Carbon             create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null)                                       Create a new Carbon instance from a specific date and time.
 *                                                                                                                                                                  If any of $year, $month or $day are set to null their now() values will
 *                                                                                                                                                                  be used.
 *                                                                                                                                                                  If $hour is null it will be set to its now() value and the default
 *                                                                                                                                                                  values for $minute and $second will be their now() values.
 *                                                                                                                                                                  If $hour is not null then the default values for $minute and $second
 *                                                                                                                                                                  will be 0.
 * @method Carbon              createFromDate($year = null, $month = null, $day = null, $timezone = null)                                                           Create a Carbon instance from just a date. The time portion is set to now.
 * @method ?Carbon             createFromFormat($format, $time, $timezone = null)                                                                                   Create a Carbon instance from a specific format.
 * @method ?Carbon             createFromIsoFormat(string $format, string $time, $timezone = null, ?string $locale = 'en', ?TranslatorInterface $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
 * @method ?Carbon             createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null)                                               Create a Carbon instance from a specific format and a string in a given language.
 * @method ?Carbon             createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null)                                            Create a Carbon instance from a specific ISO format and a string in a given language.
 * @method Carbon              createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null)                                                                Create a Carbon instance from just a time. The date portion is set to today.
 * @method Carbon              createFromTimeString(string $time, DateTimeZone|string|int|null $timezone = null)                                                    Create a Carbon instance from a time string. The date portion is set to today.
 * @method Carbon              createFromTimestamp(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null)                                      Create a Carbon instance from a timestamp and set the timezone (UTC by default).
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method Carbon              createFromTimestampMs(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null)                                    Create a Carbon instance from a timestamp in milliseconds.
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method Carbon              createFromTimestampMsUTC($timestamp)                                                                                                 Create a Carbon instance from a timestamp in milliseconds.
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method Carbon              createFromTimestampUTC(string|int|float $timestamp)                                                                                  Create a Carbon instance from a timestamp keeping the timezone to UTC.
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method Carbon              createMidnightDate($year = null, $month = null, $day = null, $timezone = null)                                                       Create a Carbon instance from just a date. The time portion is set to midnight.
 * @method ?Carbon             createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null)                 Create a new safe Carbon instance from a specific date and time.
 *                                                                                                                                                                  If any of $year, $month or $day are set to null their now() values will
 *                                                                                                                                                                  be used.
 *                                                                                                                                                                  If $hour is null it will be set to its now() value and the default
 *                                                                                                                                                                  values for $minute and $second will be their now() values.
 *                                                                                                                                                                  If $hour is not null then the default values for $minute and $second
 *                                                                                                                                                                  will be 0.
 *                                                                                                                                                                  If one of the set values is not valid, an InvalidDateException
 *                                                                                                                                                                  will be thrown.
 * @method Carbon              createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null)   Create a new Carbon instance from a specific date and time using strict validation.
 * @method mixed               executeWithLocale(string $locale, callable $func)                                                                                    Set the current locale to the given, execute the passed function, reset the locale to previous one,
 *                                                                                                                                                                  then return the result of the closure (or null if the closure was void).
 * @method Carbon              fromSerialized($value, array $options = [])                                                                                          Create an instance from a serialized string.
 *                                                                                                                                                                  If $value is not from a trusted source, consider using the allowed_classes option to limit
 *                                                                                                                                                                  the types of objects that can be built, for instance:
 * @method array               getAvailableLocales()                                                                                                                Returns the list of internally available locales and already loaded custom locales.
 *                                                                                                                                                                  (It will ignore custom translator dynamic loading.)
 * @method Language[]          getAvailableLocalesInfo()                                                                                                            Returns list of Language object for each available locale. This object allow you to get the ISO name, native
 *                                                                                                                                                                  name, region and variant of the locale.
 * @method array               getDays()                                                                                                                            Get the days of the week.
 * @method ?string             getFallbackLocale()                                                                                                                  Get the fallback locale.
 * @method array               getFormatsToIsoReplacements()                                                                                                        List of replacements from date() format to isoFormat().
 * @method array               getIsoUnits()                                                                                                                        Returns list of locale units for ISO formatting.
 * @method array|false         getLastErrors()                                                                                                                      {@inheritdoc}
 * @method string              getLocale()                                                                                                                          Get the current translator locale.
 * @method int                 getMidDayAt()                                                                                                                        get midday/noon hour
 * @method string              getTimeFormatByPrecision(string $unitPrecision)                                                                                      Return a format from H:i to H:i:s.u according to given unit precision.
 * @method string|Closure|null getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)                                 Returns raw translation message for a given key.
 * @method int                 getWeekEndsAt(?string $locale = null)                                                                                                Get the last day of week.
 * @method int                 getWeekStartsAt(?string $locale = null)                                                                                              Get the first day of week.
 * @method bool                hasRelativeKeywords(?string $time)                                                                                                   Determine if a time string will produce a relative date.
 * @method Carbon              instance(DateTimeInterface $date)                                                                                                    Create a Carbon instance from a DateTime one.
 * @method bool                isImmutable()                                                                                                                        Returns true if the current class/instance is immutable.
 * @method bool                isModifiableUnit($unit)                                                                                                              Returns true if a property can be changed via setter.
 * @method bool                isMutable()                                                                                                                          Returns true if the current class/instance is mutable.
 * @method bool                localeHasDiffOneDayWords(string $locale)                                                                                             Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
 *                                                                                                                                                                  Support is considered enabled if the 3 words are translated in the given locale.
 * @method bool                localeHasDiffSyntax(string $locale)                                                                                                  Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
 *                                                                                                                                                                  Support is considered enabled if the 4 sentences are translated in the given locale.
 * @method bool                localeHasDiffTwoDayWords(string $locale)                                                                                             Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
 *                                                                                                                                                                  Support is considered enabled if the 2 words are translated in the given locale.
 * @method bool                localeHasPeriodSyntax($locale)                                                                                                       Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
 *                                                                                                                                                                  Support is considered enabled if the 4 sentences are translated in the given locale.
 * @method bool                localeHasShortUnits(string $locale)                                                                                                  Returns true if the given locale is internally supported and has short-units support.
 *                                                                                                                                                                  Support is considered enabled if either year, day or hour has a short variant translated.
 * @method ?Carbon             make($var, DateTimeZone|string|null $timezone = null)                                                                                Make a Carbon instance from given variable if possible.
 *                                                                                                                                                                  Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
 *                                                                                                                                                                  and recurrences). Throw an exception for invalid format, but otherwise return null.
 * @method void                mixin(object|string $mixin)                                                                                                          Mix another object into the class.
 * @method Carbon              now(DateTimeZone|string|int|null $timezone = null)                                                                                   Get a Carbon instance for the current date and time.
 * @method Carbon              parse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null)                    Create a carbon instance from a string.
 *                                                                                                                                                                  This is an alias for the constructor that allows better fluent syntax
 *                                                                                                                                                                  as it allows you to do Carbon::parse('Monday next week')->fn() rather
 *                                                                                                                                                                  than (new Carbon('Monday next week'))->fn().
 * @method Carbon              parseFromLocale(string $time, ?string $locale = null, DateTimeZone|string|int|null $timezone = null)                                 Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
 * @method string              pluralUnit(string $unit)                                                                                                             Returns standardized plural of a given singular/plural unit name (in English).
 * @method ?Carbon             rawCreateFromFormat(string $format, string $time, $timezone = null)                                                                  Create a Carbon instance from a specific format.
 * @method Carbon              rawParse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null)                 Create a carbon instance from a string.
 *                                                                                                                                                                  This is an alias for the constructor that allows better fluent syntax
 *                                                                                                                                                                  as it allows you to do Carbon::parse('Monday next week')->fn() rather
 *                                                                                                                                                                  than (new Carbon('Monday next week'))->fn().
 * @method void                setFallbackLocale(string $locale)                                                                                                    Set the fallback locale.
 * @method void                setLocale(string $locale)                                                                                                            Set the current translator locale and indicate if the source locale file exists.
 *                                                                                                                                                                  Pass 'auto' as locale to use the closest language to the current LC_TIME locale.
 * @method void                setMidDayAt($hour)                                                                                                                   @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
 *                                                                                                                                                                              You should rather consider mid-day is always 12pm, then if you need to test if it's an other
 *                                                                                                                                                                              hour, test it explicitly:
 *                                                                                                                                                                                  $date->format('G') == 13
 *                                                                                                                                                                              or to set explicitly to a given hour:
 *                                                                                                                                                                                  $date->setTime(13, 0, 0, 0)
 *                                                                                                                                                                  Set midday/noon hour
 * @method string              singularUnit(string $unit)                                                                                                           Returns standardized singular of a given singular/plural unit name (in English).
 * @method void                sleep(int|float $seconds)
 * @method Carbon              today(DateTimeZone|string|int|null $timezone = null)                                                                                 Create a Carbon instance for today.
 * @method Carbon              tomorrow(DateTimeZone|string|int|null $timezone = null)                                                                              Create a Carbon instance for tomorrow.
 * @method string              translateTimeString(string $timeString, ?string $from = null, ?string $to = null, int $mode = CarbonInterface::TRANSLATE_ALL)        Translate a time string from a locale to an other.
 * @method string              translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null)                                  Translate using translation string or callback available.
 * @method Carbon              yesterday(DateTimeZone|string|int|null $timezone = null)                                                                             Create a Carbon instance for yesterday.
 *
 * </autodoc>
 */
class Factory
{
    protected string $className = Carbon::class;

    protected array $settings = [];

    /**
     * A test Carbon instance to be returned when now instances are created.
     */
    protected Closure|CarbonInterface|null $testNow = null;

    /**
     * The timezone to restore to when clearing the time mock.
     */
    protected ?string $testDefaultTimezone = null;

    /**
     * Is true when test-now is generated by a closure and timezone should be taken on the fly from it.
     */
    protected bool $useTimezoneFromTestNow = false;

    /**
     * Default translator.
     */
    protected TranslatorInterface $translator;

    /**
     * Days of weekend.
     */
    protected array $weekendDays = [
        CarbonInterface::SATURDAY,
        CarbonInterface::SUNDAY,
    ];

    /**
     * Format regex patterns.
     *
     * @var array<string, string>
     */
    protected array $regexFormats = [
        'd' => '(3[01]|[12][0-9]|0[1-9])',
        'D' => '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)',
        'j' => '([123][0-9]|[1-9])',
        'l' => '([a-zA-Z]{2,})',
        'N' => '([1-7])',
        'S' => '(st|nd|rd|th)',
        'w' => '([0-6])',
        'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])',
        'W' => '(5[012]|[1-4][0-9]|0?[1-9])',
        'F' => '([a-zA-Z]{2,})',
        'm' => '(1[012]|0[1-9])',
        'M' => '([a-zA-Z]{3})',
        'n' => '(1[012]|[1-9])',
        't' => '(2[89]|3[01])',
        'L' => '(0|1)',
        'o' => '([1-9][0-9]{0,4})',
        'Y' => '([1-9]?[0-9]{4})',
        'y' => '([0-9]{2})',
        'a' => '(am|pm)',
        'A' => '(AM|PM)',
        'B' => '([0-9]{3})',
        'g' => '(1[012]|[1-9])',
        'G' => '(2[0-3]|1?[0-9])',
        'h' => '(1[012]|0[1-9])',
        'H' => '(2[0-3]|[01][0-9])',
        'i' => '([0-5][0-9])',
        's' => '([0-5][0-9])',
        'u' => '([0-9]{1,6})',
        'v' => '([0-9]{1,3})',
        'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\\/[a-zA-Z]*)',
        'I' => '(0|1)',
        'O' => '([+-](1[0123]|0[0-9])[0134][05])',
        'P' => '([+-](1[0123]|0[0-9]):[0134][05])',
        'p' => '(Z|[+-](1[0123]|0[0-9]):[0134][05])',
        'T' => '([a-zA-Z]{1,5})',
        'Z' => '(-?[1-5]?[0-9]{1,4})',
        'U' => '([0-9]*)',

        // The formats below are combinations of the above formats.
        'c' => '(([1-9]?[0-9]{4})-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[+-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP
        'r' => '(([a-zA-Z]{3}), ([123][0-9]|0[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [+-](1[012]|0[0-9])([0134][05]))', // D, d M Y H:i:s O
    ];

    /**
     * Format modifiers (such as available in createFromFormat) regex patterns.
     *
     * @var array
     */
    protected array $regexFormatModifiers = [
        '*' => '.+',
        ' ' => '[   ]',
        '#' => '[;:\\/.,()-]',
        '?' => '([^a]|[a])',
        '!' => '',
        '|' => '',
        '+' => '',
    ];

    public function __construct(array $settings = [], ?string $className = null)
    {
        if ($className) {
            $this->className = $className;
        }

        $this->settings = $settings;
    }

    public function getClassName(): string
    {
        return $this->className;
    }

    public function setClassName(string $className): self
    {
        $this->className = $className;

        return $this;
    }

    public function className(?string $className = null): self|string
    {
        return $className === null ? $this->getClassName() : $this->setClassName($className);
    }

    public function getSettings(): array
    {
        return $this->settings;
    }

    public function setSettings(array $settings): self
    {
        $this->settings = $settings;

        return $this;
    }

    public function settings(?array $settings = null): self|array
    {
        return $settings === null ? $this->getSettings() : $this->setSettings($settings);
    }

    public function mergeSettings(array $settings): self
    {
        $this->settings = array_merge($this->settings, $settings);

        return $this;
    }

    public function setHumanDiffOptions(int $humanDiffOptions): void
    {
        $this->mergeSettings([
            'humanDiffOptions' => $humanDiffOptions,
        ]);
    }

    public function enableHumanDiffOption($humanDiffOption): void
    {
        $this->setHumanDiffOptions($this->getHumanDiffOptions() | $humanDiffOption);
    }

    public function disableHumanDiffOption(int $humanDiffOption): void
    {
        $this->setHumanDiffOptions($this->getHumanDiffOptions() & ~$humanDiffOption);
    }

    public function getHumanDiffOptions(): int
    {
        return (int) ($this->getSettings()['humanDiffOptions'] ?? 0);
    }

    /**
     * Register a custom macro.
     *
     * Pass null macro to remove it.
     *
     * @example
     * ```
     * $userSettings = [
     *   'locale' => 'pt',
     *   'timezone' => 'America/Sao_Paulo',
     * ];
     * $factory->macro('userFormat', function () use ($userSettings) {
     *   return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
     * });
     * echo $factory->yesterday()->hours(11)->userFormat();
     * ```
     *
     * @param-closure-this  static  $macro
     */
    public function macro(string $name, ?callable $macro): void
    {
        $macros = $this->getSettings()['macros'] ?? [];
        $macros[$name] = $macro;

        $this->mergeSettings([
            'macros' => $macros,
        ]);
    }

    /**
     * Remove all macros and generic macros.
     */
    public function resetMacros(): void
    {
        $this->mergeSettings([
            'macros' => null,
            'genericMacros' => null,
        ]);
    }

    /**
     * Register a custom macro.
     *
     * @param callable $macro
     * @param int      $priority marco with higher priority is tried first
     *
     * @return void
     */
    public function genericMacro(callable $macro, int $priority = 0): void
    {
        $genericMacros = $this->getSettings()['genericMacros'] ?? [];

        if (!isset($genericMacros[$priority])) {
            $genericMacros[$priority] = [];
            krsort($genericMacros, SORT_NUMERIC);
        }

        $genericMacros[$priority][] = $macro;

        $this->mergeSettings([
            'genericMacros' => $genericMacros,
        ]);
    }

    /**
     * Checks if macro is registered globally.
     */
    public function hasMacro(string $name): bool
    {
        return isset($this->getSettings()['macros'][$name]);
    }

    /**
     * Get the raw callable macro registered globally for a given name.
     */
    public function getMacro(string $name): ?callable
    {
        return $this->getSettings()['macros'][$name] ?? null;
    }

    /**
     * Set the default translator instance to use.
     */
    public function setTranslator(TranslatorInterface $translator): void
    {
        $this->translator = $translator;
    }

    /**
     * Initialize the default translator instance if necessary.
     */
    public function getTranslator(): TranslatorInterface
    {
        return $this->translator ??= Translator::get();
    }

    /**
     * Reset the format used to the default when type juggling a Carbon instance to a string
     *
     * @return void
     */
    public function resetToStringFormat(): void
    {
        $this->setToStringFormat(null);
    }

    /**
     * Set the default format used when type juggling a Carbon instance to a string.
     */
    public function setToStringFormat(string|Closure|null $format): void
    {
        $this->mergeSettings([
            'toStringFormat' => $format,
        ]);
    }

    /**
     * JSON serialize all Carbon instances using the given callback.
     */
    public function serializeUsing(string|callable|null $format): void
    {
        $this->mergeSettings([
            'toJsonFormat' => $format,
        ]);
    }

    /**
     * Enable the strict mode (or disable with passing false).
     */
    public function useStrictMode(bool $strictModeEnabled = true): void
    {
        $this->mergeSettings([
            'strictMode' => $strictModeEnabled,
        ]);
    }

    /**
     * Returns true if the strict mode is globally in use, false else.
     * (It can be overridden in specific instances.)
     */
    public function isStrictModeEnabled(): bool
    {
        return $this->getSettings()['strictMode'] ?? true;
    }

    /**
     * Indicates if months should be calculated with overflow.
     */
    public function useMonthsOverflow(bool $monthsOverflow = true): void
    {
        $this->mergeSettings([
            'monthOverflow' => $monthsOverflow,
        ]);
    }

    /**
     * Reset the month overflow behavior.
     */
    public function resetMonthsOverflow(): void
    {
        $this->useMonthsOverflow();
    }

    /**
     * Get the month overflow global behavior (can be overridden in specific instances).
     */
    public function shouldOverflowMonths(): bool
    {
        return $this->getSettings()['monthOverflow'] ?? true;
    }

    /**
     * Indicates if years should be calculated with overflow.
     */
    public function useYearsOverflow(bool $yearsOverflow = true): void
    {
        $this->mergeSettings([
            'yearOverflow' => $yearsOverflow,
        ]);
    }

    /**
     * Reset the month overflow behavior.
     */
    public function resetYearsOverflow(): void
    {
        $this->useYearsOverflow();
    }

    /**
     * Get the month overflow global behavior (can be overridden in specific instances).
     */
    public function shouldOverflowYears(): bool
    {
        return $this->getSettings()['yearOverflow'] ?? true;
    }

    /**
     * Get weekend days
     *
     * @return array
     */
    public function getWeekendDays(): array
    {
        return $this->weekendDays;
    }

    /**
     * Set weekend days
     */
    public function setWeekendDays(array $days): void
    {
        $this->weekendDays = $days;
    }

    /**
     * Checks if the (date)time string is in a given format.
     *
     * @example
     * ```
     * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
     * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
     * ```
     */
    public function hasFormat(string $date, string $format): bool
    {
        // createFromFormat() is known to handle edge cases silently.
        // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format.
        // To ensure we're really testing against our desired format, perform an additional regex validation.

        return $this->matchFormatPattern($date, preg_quote($format, '/'), $this->regexFormats);
    }

    /**
     * Checks if the (date)time string is in a given format.
     *
     * @example
     * ```
     * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true
     * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false
     * ```
     */
    public function hasFormatWithModifiers(string $date, string $format): bool
    {
        return $this->matchFormatPattern($date, $format, array_merge($this->regexFormats, $this->regexFormatModifiers));
    }

    /**
     * Set a Carbon instance (real or mock) to be returned when a "now"
     * instance is created.  The provided instance will be returned
     * specifically under the following conditions:
     *   - A call to the static now() method, ex. Carbon::now()
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
     *   - When a string containing the desired time is passed to Carbon::parse().
     *
     * Note the timezone parameter was left out of the examples above and
     * has no affect as the mock value will be returned regardless of its value.
     *
     * Only the moment is mocked with setTestNow(), the timezone will still be the one passed
     * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()).
     *
     * To clear the test instance call this method using the default
     * parameter of null.
     *
     * /!\ Use this method for unit tests only.
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
     */
    public function setTestNow(mixed $testNow = null): void
    {
        $this->useTimezoneFromTestNow = false;
        $this->testNow = $testNow instanceof self || $testNow instanceof Closure
            ? $testNow
            : $this->make($testNow);
    }

    /**
     * Set a Carbon instance (real or mock) to be returned when a "now"
     * instance is created.  The provided instance will be returned
     * specifically under the following conditions:
     *   - A call to the static now() method, ex. Carbon::now()
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
     *   - When a string containing the desired time is passed to Carbon::parse().
     *
     * It will also align default timezone (e.g. call date_default_timezone_set()) with
     * the second argument or if null, with the timezone of the given date object.
     *
     * To clear the test instance call this method using the default
     * parameter of null.
     *
     * /!\ Use this method for unit tests only.
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
     */
    public function setTestNowAndTimezone(mixed $testNow = null, $timezone = null): void
    {
        if ($testNow) {
            $this->testDefaultTimezone ??= date_default_timezone_get();
        }

        $useDateInstanceTimezone = $testNow instanceof DateTimeInterface;

        if ($useDateInstanceTimezone) {
            $this->setDefaultTimezone($testNow->getTimezone()->getName(), $testNow);
        }

        $this->setTestNow($testNow);
        $this->useTimezoneFromTestNow = ($timezone === null && $testNow instanceof Closure);

        if (!$useDateInstanceTimezone) {
            $now = $this->getMockedTestNow(\func_num_args() === 1 ? null : $timezone);
            $this->setDefaultTimezone($now?->tzName ?? $this->testDefaultTimezone ?? 'UTC', $now);
        }

        if (!$testNow) {
            $this->testDefaultTimezone = null;
        }
    }

    /**
     * Temporarily sets a static date to be used within the callback.
     * Using setTestNow to set the date, executing the callback, then
     * clearing the test instance.
     *
     * /!\ Use this method for unit tests only.
     *
     * @template T
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow  real or mock Carbon instance
     * @param Closure(): T                                       $callback
     *
     * @return T
     */
    public function withTestNow(mixed $testNow, callable $callback): mixed
    {
        $previousTestNow = $this->getTestNow();
        $this->setTestNow($testNow);

        try {
            $result = $callback();
        } finally {
            $this->setTestNow($previousTestNow);
        }

        return $result;
    }

    /**
     * Get the Carbon instance (real or mock) to be returned when a "now"
     * instance is created.
     *
     * @return Closure|CarbonInterface|null the current instance used for testing
     */
    public function getTestNow(): Closure|CarbonInterface|null
    {
        if ($this->testNow === null) {
            $factory = FactoryImmutable::getDefaultInstance();

            if ($factory !== $this) {
                return $factory->getTestNow();
            }
        }

        return $this->testNow;
    }

    public function handleTestNowClosure(
        Closure|CarbonInterface|null $testNow,
        DateTimeZone|string|int|null $timezone = null,
    ): ?CarbonInterface {
        if ($testNow instanceof Closure) {
            $callback = Callback::fromClosure($testNow);
            $realNow = new DateTimeImmutable('now');
            $testNow = $testNow($callback->prepareParameter($this->parse(
                $realNow->format('Y-m-d H:i:s.u'),
                $timezone ?? $realNow->getTimezone(),
            )));

            if ($testNow !== null && !($testNow instanceof DateTimeInterface)) {
                $function = $callback->getReflectionFunction();
                $type = \is_object($testNow) ? $testNow::class : \gettype($testNow);

                throw new RuntimeException(
                    'The test closure defined in '.$function->getFileName().
                    ' at line '.$function->getStartLine().' returned '.$type.
                    '; expected '.CarbonInterface::class.'|null',
                );
            }

            if (!($testNow instanceof CarbonInterface)) {
                $timezone ??= $this->useTimezoneFromTestNow ? $testNow->getTimezone() : null;
                $testNow = $this->__call('instance', [$testNow, $timezone]);
            }
        }

        return $testNow;
    }

    /**
     * Determine if there is a valid test instance set. A valid test instance
     * is anything that is not null.
     *
     * @return bool true if there is a test instance, otherwise false
     */
    public function hasTestNow(): bool
    {
        return $this->getTestNow() !== null;
    }

    public function withTimeZone(DateTimeZone|string|int|null $timezone): static
    {
        $factory = clone $this;
        $factory->settings['timezone'] = $timezone;

        return $factory;
    }

    public function __call(string $name, array $arguments): mixed
    {
        $method = new ReflectionMethod($this->className, $name);
        $settings = $this->settings;

        if ($settings && isset($settings['timezone'])) {
            $timezoneParameters = array_filter($method->getParameters(), function ($parameter) {
                return \in_array($parameter->getName(), ['tz', 'timezone'], true);
            });
            $timezoneSetting = $settings['timezone'];

            if (isset($arguments[0]) && \in_array($name, ['instance', 'make', 'create', 'parse'], true)) {
                if ($arguments[0] instanceof DateTimeInterface) {
                    $settings['innerTimezone'] = $settings['timezone'];
                } elseif (\is_string($arguments[0]) && date_parse($arguments[0])['is_localtime']) {
                    unset($settings['timezone'], $settings['innerTimezone']);
                }
            }

            if (\count($timezoneParameters)) {
                $index = key($timezoneParameters);

                if (!isset($arguments[$index])) {
                    array_splice($arguments, key($timezoneParameters), 0, [$timezoneSetting]);
                }

                unset($settings['timezone']);
            }
        }

        $clock = FactoryImmutable::getCurrentClock();
        FactoryImmutable::setCurrentClock($this);

        try {
            $result = $this->className::$name(...$arguments);
        } finally {
            FactoryImmutable::setCurrentClock($clock);
        }

        if (isset($this->translator)) {
            $settings['translator'] = $this->translator;
        }

        return $result instanceof CarbonInterface && !empty($settings)
            ? $result->settings($settings)
            : $result;
    }

    /**
     * Get the mocked date passed in setTestNow() and if it's a Closure, execute it.
     */
    protected function getMockedTestNow(DateTimeZone|string|int|null $timezone): ?CarbonInterface
    {
        $testNow = $this->handleTestNowClosure($this->getTestNow());

        if ($testNow instanceof CarbonInterface) {
            $testNow = $testNow->avoidMutation();

            if ($timezone !== null) {
                return $testNow->setTimezone($timezone);
            }
        }

        return $testNow;
    }

    /**
     * Checks if the (date)time string is in a given format with
     * given list of pattern replacements.
     *
     * @example
     * ```
     * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
     * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
     * ```
     *
     * @param string $date
     * @param string $format
     * @param array  $replacements
     *
     * @return bool
     */
    private function matchFormatPattern(string $date, string $format, array $replacements): bool
    {
        // Preg quote, but remove escaped backslashes since we'll deal with escaped characters in the format string.
        $regex = str_replace('\\\\', '\\', $format);
        // Replace not-escaped letters
        $regex = preg_replace_callback(
            '/(?<!\\\\)((?:\\\\{2})*)(['.implode('', array_keys($replacements)).'])/',
            static fn ($match) => $match[1].strtr($match[2], $replacements),
            $regex,
        );
        // Replace escaped letters by the letter itself
        $regex = preg_replace('/(?<!\\\\)((?:\\\\{2})*)\\\\(\w)/', '$1$2', $regex);
        // Escape not escaped slashes
        $regex = preg_replace('#(?<!\\\\)((?:\\\\{2})*)/#', '$1\\/', $regex);

        return (bool) @preg_match('/^'.$regex.'$/', $date);
    }

    private function setDefaultTimezone(string $timezone, ?DateTimeInterface $date = null): void
    {
        $previous = null;
        $success = false;

        try {
            $success = date_default_timezone_set($timezone);
        } catch (Throwable $exception) {
            $previous = $exception;
        }

        if (!$success) {
            $suggestion = @CarbonTimeZone::create($timezone)->toRegionName($date);

            throw new InvalidArgumentException(
                "Timezone ID '$timezone' is invalid".
                ($suggestion && $suggestion !== $timezone ? ", did you mean '$suggestion'?" : '.')."\n".
                "It must be one of the IDs from DateTimeZone::listIdentifiers(),\n".
                'For the record, hours/minutes offset are relevant only for a particular moment, '.
                'but not as a default timezone.',
                0,
                $previous
            );
        }
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Traits\Date;
use DateTimeImmutable;
use DateTimeInterface;

/**
 * A simple API extension for DateTimeImmutable.
 *
 * <autodoc generated by `composer phpdoc`>
 *
 * @property      string           $localeDayOfWeek                                                                   the day of week in current locale
 * @property      string           $shortLocaleDayOfWeek                                                              the abbreviated day of week in current locale
 * @property      string           $localeMonth                                                                       the month in current locale
 * @property      string           $shortLocaleMonth                                                                  the abbreviated month in current locale
 * @property      int              $year
 * @property      int              $yearIso
 * @property      int              $month
 * @property      int              $day
 * @property      int              $hour
 * @property      int              $minute
 * @property      int              $second
 * @property      int              $micro
 * @property      int              $microsecond
 * @property      int              $dayOfWeekIso                                                                      1 (for Monday) through 7 (for Sunday)
 * @property      int|float|string $timestamp                                                                         seconds since the Unix Epoch
 * @property      string           $englishDayOfWeek                                                                  the day of week in English
 * @property      string           $shortEnglishDayOfWeek                                                             the abbreviated day of week in English
 * @property      string           $englishMonth                                                                      the month in English
 * @property      string           $shortEnglishMonth                                                                 the abbreviated month in English
 * @property      int              $milliseconds
 * @property      int              $millisecond
 * @property      int              $milli
 * @property      int              $week                                                                              1 through 53
 * @property      int              $isoWeek                                                                           1 through 53
 * @property      int              $weekYear                                                                          year according to week format
 * @property      int              $isoWeekYear                                                                       year according to ISO week format
 * @property      int              $age                                                                               does a diffInYears() with default parameters
 * @property      int              $offset                                                                            the timezone offset in seconds from UTC
 * @property      int              $offsetMinutes                                                                     the timezone offset in minutes from UTC
 * @property      int              $offsetHours                                                                       the timezone offset in hours from UTC
 * @property      CarbonTimeZone   $timezone                                                                          the current timezone
 * @property      CarbonTimeZone   $tz                                                                                alias of $timezone
 * @property      int              $centuryOfMillennium                                                               The value of the century starting from the beginning of the current millennium
 * @property      int              $dayOfCentury                                                                      The value of the day starting from the beginning of the current century
 * @property      int              $dayOfDecade                                                                       The value of the day starting from the beginning of the current decade
 * @property      int              $dayOfMillennium                                                                   The value of the day starting from the beginning of the current millennium
 * @property      int              $dayOfMonth                                                                        The value of the day starting from the beginning of the current month
 * @property      int              $dayOfQuarter                                                                      The value of the day starting from the beginning of the current quarter
 * @property      int              $dayOfWeek                                                                         0 (for Sunday) through 6 (for Saturday)
 * @property      int              $dayOfYear                                                                         1 through 366
 * @property      int              $decadeOfCentury                                                                   The value of the decade starting from the beginning of the current century
 * @property      int              $decadeOfMillennium                                                                The value of the decade starting from the beginning of the current millennium
 * @property      int              $hourOfCentury                                                                     The value of the hour starting from the beginning of the current century
 * @property      int              $hourOfDay                                                                         The value of the hour starting from the beginning of the current day
 * @property      int              $hourOfDecade                                                                      The value of the hour starting from the beginning of the current decade
 * @property      int              $hourOfMillennium                                                                  The value of the hour starting from the beginning of the current millennium
 * @property      int              $hourOfMonth                                                                       The value of the hour starting from the beginning of the current month
 * @property      int              $hourOfQuarter                                                                     The value of the hour starting from the beginning of the current quarter
 * @property      int              $hourOfWeek                                                                        The value of the hour starting from the beginning of the current week
 * @property      int              $hourOfYear                                                                        The value of the hour starting from the beginning of the current year
 * @property      int              $microsecondOfCentury                                                              The value of the microsecond starting from the beginning of the current century
 * @property      int              $microsecondOfDay                                                                  The value of the microsecond starting from the beginning of the current day
 * @property      int              $microsecondOfDecade                                                               The value of the microsecond starting from the beginning of the current decade
 * @property      int              $microsecondOfHour                                                                 The value of the microsecond starting from the beginning of the current hour
 * @property      int              $microsecondOfMillennium                                                           The value of the microsecond starting from the beginning of the current millennium
 * @property      int              $microsecondOfMillisecond                                                          The value of the microsecond starting from the beginning of the current millisecond
 * @property      int              $microsecondOfMinute                                                               The value of the microsecond starting from the beginning of the current minute
 * @property      int              $microsecondOfMonth                                                                The value of the microsecond starting from the beginning of the current month
 * @property      int              $microsecondOfQuarter                                                              The value of the microsecond starting from the beginning of the current quarter
 * @property      int              $microsecondOfSecond                                                               The value of the microsecond starting from the beginning of the current second
 * @property      int              $microsecondOfWeek                                                                 The value of the microsecond starting from the beginning of the current week
 * @property      int              $microsecondOfYear                                                                 The value of the microsecond starting from the beginning of the current year
 * @property      int              $millisecondOfCentury                                                              The value of the millisecond starting from the beginning of the current century
 * @property      int              $millisecondOfDay                                                                  The value of the millisecond starting from the beginning of the current day
 * @property      int              $millisecondOfDecade                                                               The value of the millisecond starting from the beginning of the current decade
 * @property      int              $millisecondOfHour                                                                 The value of the millisecond starting from the beginning of the current hour
 * @property      int              $millisecondOfMillennium                                                           The value of the millisecond starting from the beginning of the current millennium
 * @property      int              $millisecondOfMinute                                                               The value of the millisecond starting from the beginning of the current minute
 * @property      int              $millisecondOfMonth                                                                The value of the millisecond starting from the beginning of the current month
 * @property      int              $millisecondOfQuarter                                                              The value of the millisecond starting from the beginning of the current quarter
 * @property      int              $millisecondOfSecond                                                               The value of the millisecond starting from the beginning of the current second
 * @property      int              $millisecondOfWeek                                                                 The value of the millisecond starting from the beginning of the current week
 * @property      int              $millisecondOfYear                                                                 The value of the millisecond starting from the beginning of the current year
 * @property      int              $minuteOfCentury                                                                   The value of the minute starting from the beginning of the current century
 * @property      int              $minuteOfDay                                                                       The value of the minute starting from the beginning of the current day
 * @property      int              $minuteOfDecade                                                                    The value of the minute starting from the beginning of the current decade
 * @property      int              $minuteOfHour                                                                      The value of the minute starting from the beginning of the current hour
 * @property      int              $minuteOfMillennium                                                                The value of the minute starting from the beginning of the current millennium
 * @property      int              $minuteOfMonth                                                                     The value of the minute starting from the beginning of the current month
 * @property      int              $minuteOfQuarter                                                                   The value of the minute starting from the beginning of the current quarter
 * @property      int              $minuteOfWeek                                                                      The value of the minute starting from the beginning of the current week
 * @property      int              $minuteOfYear                                                                      The value of the minute starting from the beginning of the current year
 * @property      int              $monthOfCentury                                                                    The value of the month starting from the beginning of the current century
 * @property      int              $monthOfDecade                                                                     The value of the month starting from the beginning of the current decade
 * @property      int              $monthOfMillennium                                                                 The value of the month starting from the beginning of the current millennium
 * @property      int              $monthOfQuarter                                                                    The value of the month starting from the beginning of the current quarter
 * @property      int              $monthOfYear                                                                       The value of the month starting from the beginning of the current year
 * @property      int              $quarterOfCentury                                                                  The value of the quarter starting from the beginning of the current century
 * @property      int              $quarterOfDecade                                                                   The value of the quarter starting from the beginning of the current decade
 * @property      int              $quarterOfMillennium                                                               The value of the quarter starting from the beginning of the current millennium
 * @property      int              $quarterOfYear                                                                     The value of the quarter starting from the beginning of the current year
 * @property      int              $secondOfCentury                                                                   The value of the second starting from the beginning of the current century
 * @property      int              $secondOfDay                                                                       The value of the second starting from the beginning of the current day
 * @property      int              $secondOfDecade                                                                    The value of the second starting from the beginning of the current decade
 * @property      int              $secondOfHour                                                                      The value of the second starting from the beginning of the current hour
 * @property      int              $secondOfMillennium                                                                The value of the second starting from the beginning of the current millennium
 * @property      int              $secondOfMinute                                                                    The value of the second starting from the beginning of the current minute
 * @property      int              $secondOfMonth                                                                     The value of the second starting from the beginning of the current month
 * @property      int              $secondOfQuarter                                                                   The value of the second starting from the beginning of the current quarter
 * @property      int              $secondOfWeek                                                                      The value of the second starting from the beginning of the current week
 * @property      int              $secondOfYear                                                                      The value of the second starting from the beginning of the current year
 * @property      int              $weekOfCentury                                                                     The value of the week starting from the beginning of the current century
 * @property      int              $weekOfDecade                                                                      The value of the week starting from the beginning of the current decade
 * @property      int              $weekOfMillennium                                                                  The value of the week starting from the beginning of the current millennium
 * @property      int              $weekOfMonth                                                                       1 through 5
 * @property      int              $weekOfQuarter                                                                     The value of the week starting from the beginning of the current quarter
 * @property      int              $weekOfYear                                                                        ISO-8601 week number of year, weeks starting on Monday
 * @property      int              $yearOfCentury                                                                     The value of the year starting from the beginning of the current century
 * @property      int              $yearOfDecade                                                                      The value of the year starting from the beginning of the current decade
 * @property      int              $yearOfMillennium                                                                  The value of the year starting from the beginning of the current millennium
 * @property-read string           $latinMeridiem                                                                     "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
 * @property-read string           $latinUpperMeridiem                                                                "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
 * @property-read string           $timezoneAbbreviatedName                                                           the current timezone abbreviated name
 * @property-read string           $tzAbbrName                                                                        alias of $timezoneAbbreviatedName
 * @property-read string           $dayName                                                                           long name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortDayName                                                                      short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $minDayName                                                                        very short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $monthName                                                                         long name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortMonthName                                                                    short name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $meridiem                                                                          lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read string           $upperMeridiem                                                                     uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read int              $noZeroHour                                                                        current hour from 1 to 24
 * @property-read int              $isoWeeksInYear                                                                    51 through 53
 * @property-read int              $weekNumberInMonth                                                                 1 through 5
 * @property-read int              $firstWeekDay                                                                      0 through 6
 * @property-read int              $lastWeekDay                                                                       0 through 6
 * @property-read int              $quarter                                                                           the quarter of this instance, 1 - 4
 * @property-read int              $decade                                                                            the decade of this instance
 * @property-read int              $century                                                                           the century of this instance
 * @property-read int              $millennium                                                                        the millennium of this instance
 * @property-read bool             $dst                                                                               daylight savings time indicator, true if DST, false otherwise
 * @property-read bool             $local                                                                             checks if the timezone is local, true if local, false otherwise
 * @property-read bool             $utc                                                                               checks if the timezone is UTC, true if UTC, false otherwise
 * @property-read string           $timezoneName                                                                      the current timezone name
 * @property-read string           $tzName                                                                            alias of $timezoneName
 * @property-read string           $locale                                                                            locale of the current instance
 * @property-read int              $centuriesInMillennium                                                             The number of centuries contained in the current millennium
 * @property-read int              $daysInCentury                                                                     The number of days contained in the current century
 * @property-read int              $daysInDecade                                                                      The number of days contained in the current decade
 * @property-read int              $daysInMillennium                                                                  The number of days contained in the current millennium
 * @property-read int              $daysInMonth                                                                       number of days in the given month
 * @property-read int              $daysInQuarter                                                                     The number of days contained in the current quarter
 * @property-read int              $daysInWeek                                                                        The number of days contained in the current week
 * @property-read int              $daysInYear                                                                        365 or 366
 * @property-read int              $decadesInCentury                                                                  The number of decades contained in the current century
 * @property-read int              $decadesInMillennium                                                               The number of decades contained in the current millennium
 * @property-read int              $hoursInCentury                                                                    The number of hours contained in the current century
 * @property-read int              $hoursInDay                                                                        The number of hours contained in the current day
 * @property-read int              $hoursInDecade                                                                     The number of hours contained in the current decade
 * @property-read int              $hoursInMillennium                                                                 The number of hours contained in the current millennium
 * @property-read int              $hoursInMonth                                                                      The number of hours contained in the current month
 * @property-read int              $hoursInQuarter                                                                    The number of hours contained in the current quarter
 * @property-read int              $hoursInWeek                                                                       The number of hours contained in the current week
 * @property-read int              $hoursInYear                                                                       The number of hours contained in the current year
 * @property-read int              $microsecondsInCentury                                                             The number of microseconds contained in the current century
 * @property-read int              $microsecondsInDay                                                                 The number of microseconds contained in the current day
 * @property-read int              $microsecondsInDecade                                                              The number of microseconds contained in the current decade
 * @property-read int              $microsecondsInHour                                                                The number of microseconds contained in the current hour
 * @property-read int              $microsecondsInMillennium                                                          The number of microseconds contained in the current millennium
 * @property-read int              $microsecondsInMillisecond                                                         The number of microseconds contained in the current millisecond
 * @property-read int              $microsecondsInMinute                                                              The number of microseconds contained in the current minute
 * @property-read int              $microsecondsInMonth                                                               The number of microseconds contained in the current month
 * @property-read int              $microsecondsInQuarter                                                             The number of microseconds contained in the current quarter
 * @property-read int              $microsecondsInSecond                                                              The number of microseconds contained in the current second
 * @property-read int              $microsecondsInWeek                                                                The number of microseconds contained in the current week
 * @property-read int              $microsecondsInYear                                                                The number of microseconds contained in the current year
 * @property-read int              $millisecondsInCentury                                                             The number of milliseconds contained in the current century
 * @property-read int              $millisecondsInDay                                                                 The number of milliseconds contained in the current day
 * @property-read int              $millisecondsInDecade                                                              The number of milliseconds contained in the current decade
 * @property-read int              $millisecondsInHour                                                                The number of milliseconds contained in the current hour
 * @property-read int              $millisecondsInMillennium                                                          The number of milliseconds contained in the current millennium
 * @property-read int              $millisecondsInMinute                                                              The number of milliseconds contained in the current minute
 * @property-read int              $millisecondsInMonth                                                               The number of milliseconds contained in the current month
 * @property-read int              $millisecondsInQuarter                                                             The number of milliseconds contained in the current quarter
 * @property-read int              $millisecondsInSecond                                                              The number of milliseconds contained in the current second
 * @property-read int              $millisecondsInWeek                                                                The number of milliseconds contained in the current week
 * @property-read int              $millisecondsInYear                                                                The number of milliseconds contained in the current year
 * @property-read int              $minutesInCentury                                                                  The number of minutes contained in the current century
 * @property-read int              $minutesInDay                                                                      The number of minutes contained in the current day
 * @property-read int              $minutesInDecade                                                                   The number of minutes contained in the current decade
 * @property-read int              $minutesInHour                                                                     The number of minutes contained in the current hour
 * @property-read int              $minutesInMillennium                                                               The number of minutes contained in the current millennium
 * @property-read int              $minutesInMonth                                                                    The number of minutes contained in the current month
 * @property-read int              $minutesInQuarter                                                                  The number of minutes contained in the current quarter
 * @property-read int              $minutesInWeek                                                                     The number of minutes contained in the current week
 * @property-read int              $minutesInYear                                                                     The number of minutes contained in the current year
 * @property-read int              $monthsInCentury                                                                   The number of months contained in the current century
 * @property-read int              $monthsInDecade                                                                    The number of months contained in the current decade
 * @property-read int              $monthsInMillennium                                                                The number of months contained in the current millennium
 * @property-read int              $monthsInQuarter                                                                   The number of months contained in the current quarter
 * @property-read int              $monthsInYear                                                                      The number of months contained in the current year
 * @property-read int              $quartersInCentury                                                                 The number of quarters contained in the current century
 * @property-read int              $quartersInDecade                                                                  The number of quarters contained in the current decade
 * @property-read int              $quartersInMillennium                                                              The number of quarters contained in the current millennium
 * @property-read int              $quartersInYear                                                                    The number of quarters contained in the current year
 * @property-read int              $secondsInCentury                                                                  The number of seconds contained in the current century
 * @property-read int              $secondsInDay                                                                      The number of seconds contained in the current day
 * @property-read int              $secondsInDecade                                                                   The number of seconds contained in the current decade
 * @property-read int              $secondsInHour                                                                     The number of seconds contained in the current hour
 * @property-read int              $secondsInMillennium                                                               The number of seconds contained in the current millennium
 * @property-read int              $secondsInMinute                                                                   The number of seconds contained in the current minute
 * @property-read int              $secondsInMonth                                                                    The number of seconds contained in the current month
 * @property-read int              $secondsInQuarter                                                                  The number of seconds contained in the current quarter
 * @property-read int              $secondsInWeek                                                                     The number of seconds contained in the current week
 * @property-read int              $secondsInYear                                                                     The number of seconds contained in the current year
 * @property-read int              $weeksInCentury                                                                    The number of weeks contained in the current century
 * @property-read int              $weeksInDecade                                                                     The number of weeks contained in the current decade
 * @property-read int              $weeksInMillennium                                                                 The number of weeks contained in the current millennium
 * @property-read int              $weeksInMonth                                                                      The number of weeks contained in the current month
 * @property-read int              $weeksInQuarter                                                                    The number of weeks contained in the current quarter
 * @property-read int              $weeksInYear                                                                       51 through 53
 * @property-read int              $yearsInCentury                                                                    The number of years contained in the current century
 * @property-read int              $yearsInDecade                                                                     The number of years contained in the current decade
 * @property-read int              $yearsInMillennium                                                                 The number of years contained in the current millennium
 *
 * @method        bool             isUtc()                                                                            Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
 * @method        bool             isLocal()                                                                          Check if the current instance has non-UTC timezone.
 * @method        bool             isValid()                                                                          Check if the current instance is a valid date.
 * @method        bool             isDST()                                                                            Check if the current instance is in a daylight saving time.
 * @method        bool             isSunday()                                                                         Checks if the instance day is sunday.
 * @method        bool             isMonday()                                                                         Checks if the instance day is monday.
 * @method        bool             isTuesday()                                                                        Checks if the instance day is tuesday.
 * @method        bool             isWednesday()                                                                      Checks if the instance day is wednesday.
 * @method        bool             isThursday()                                                                       Checks if the instance day is thursday.
 * @method        bool             isFriday()                                                                         Checks if the instance day is friday.
 * @method        bool             isSaturday()                                                                       Checks if the instance day is saturday.
 * @method        bool             isSameYear(DateTimeInterface|string $date)                                         Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentYear()                                                                    Checks if the instance is in the same year as the current moment.
 * @method        bool             isNextYear()                                                                       Checks if the instance is in the same year as the current moment next year.
 * @method        bool             isLastYear()                                                                       Checks if the instance is in the same year as the current moment last year.
 * @method        bool             isCurrentMonth()                                                                   Checks if the instance is in the same month as the current moment.
 * @method        bool             isNextMonth()                                                                      Checks if the instance is in the same month as the current moment next month.
 * @method        bool             isLastMonth()                                                                      Checks if the instance is in the same month as the current moment last month.
 * @method        bool             isSameWeek(DateTimeInterface|string $date)                                         Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentWeek()                                                                    Checks if the instance is in the same week as the current moment.
 * @method        bool             isNextWeek()                                                                       Checks if the instance is in the same week as the current moment next week.
 * @method        bool             isLastWeek()                                                                       Checks if the instance is in the same week as the current moment last week.
 * @method        bool             isSameDay(DateTimeInterface|string $date)                                          Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDay()                                                                     Checks if the instance is in the same day as the current moment.
 * @method        bool             isNextDay()                                                                        Checks if the instance is in the same day as the current moment next day.
 * @method        bool             isLastDay()                                                                        Checks if the instance is in the same day as the current moment last day.
 * @method        bool             isSameHour(DateTimeInterface|string $date)                                         Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentHour()                                                                    Checks if the instance is in the same hour as the current moment.
 * @method        bool             isNextHour()                                                                       Checks if the instance is in the same hour as the current moment next hour.
 * @method        bool             isLastHour()                                                                       Checks if the instance is in the same hour as the current moment last hour.
 * @method        bool             isSameMinute(DateTimeInterface|string $date)                                       Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMinute()                                                                  Checks if the instance is in the same minute as the current moment.
 * @method        bool             isNextMinute()                                                                     Checks if the instance is in the same minute as the current moment next minute.
 * @method        bool             isLastMinute()                                                                     Checks if the instance is in the same minute as the current moment last minute.
 * @method        bool             isSameSecond(DateTimeInterface|string $date)                                       Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentSecond()                                                                  Checks if the instance is in the same second as the current moment.
 * @method        bool             isNextSecond()                                                                     Checks if the instance is in the same second as the current moment next second.
 * @method        bool             isLastSecond()                                                                     Checks if the instance is in the same second as the current moment last second.
 * @method        bool             isSameMilli(DateTimeInterface|string $date)                                        Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMilli()                                                                   Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMilli()                                                                      Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMilli()                                                                      Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMillisecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillisecond()                                                             Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMicro(DateTimeInterface|string $date)                                        Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicro()                                                                   Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicro()                                                                      Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicro()                                                                      Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameMicrosecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicrosecond()                                                             Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameDecade(DateTimeInterface|string $date)                                       Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDecade()                                                                  Checks if the instance is in the same decade as the current moment.
 * @method        bool             isNextDecade()                                                                     Checks if the instance is in the same decade as the current moment next decade.
 * @method        bool             isLastDecade()                                                                     Checks if the instance is in the same decade as the current moment last decade.
 * @method        bool             isSameCentury(DateTimeInterface|string $date)                                      Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentCentury()                                                                 Checks if the instance is in the same century as the current moment.
 * @method        bool             isNextCentury()                                                                    Checks if the instance is in the same century as the current moment next century.
 * @method        bool             isLastCentury()                                                                    Checks if the instance is in the same century as the current moment last century.
 * @method        bool             isSameMillennium(DateTimeInterface|string $date)                                   Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillennium()                                                              Checks if the instance is in the same millennium as the current moment.
 * @method        bool             isNextMillennium()                                                                 Checks if the instance is in the same millennium as the current moment next millennium.
 * @method        bool             isLastMillennium()                                                                 Checks if the instance is in the same millennium as the current moment last millennium.
 * @method        bool             isCurrentQuarter()                                                                 Checks if the instance is in the same quarter as the current moment.
 * @method        bool             isNextQuarter()                                                                    Checks if the instance is in the same quarter as the current moment next quarter.
 * @method        bool             isLastQuarter()                                                                    Checks if the instance is in the same quarter as the current moment last quarter.
 * @method        CarbonImmutable  years(int $value)                                                                  Set current instance year to the given value.
 * @method        CarbonImmutable  year(int $value)                                                                   Set current instance year to the given value.
 * @method        CarbonImmutable  setYears(int $value)                                                               Set current instance year to the given value.
 * @method        CarbonImmutable  setYear(int $value)                                                                Set current instance year to the given value.
 * @method        CarbonImmutable  months(Month|int $value)                                                           Set current instance month to the given value.
 * @method        CarbonImmutable  month(Month|int $value)                                                            Set current instance month to the given value.
 * @method        CarbonImmutable  setMonths(Month|int $value)                                                        Set current instance month to the given value.
 * @method        CarbonImmutable  setMonth(Month|int $value)                                                         Set current instance month to the given value.
 * @method        CarbonImmutable  days(int $value)                                                                   Set current instance day to the given value.
 * @method        CarbonImmutable  day(int $value)                                                                    Set current instance day to the given value.
 * @method        CarbonImmutable  setDays(int $value)                                                                Set current instance day to the given value.
 * @method        CarbonImmutable  setDay(int $value)                                                                 Set current instance day to the given value.
 * @method        CarbonImmutable  hours(int $value)                                                                  Set current instance hour to the given value.
 * @method        CarbonImmutable  hour(int $value)                                                                   Set current instance hour to the given value.
 * @method        CarbonImmutable  setHours(int $value)                                                               Set current instance hour to the given value.
 * @method        CarbonImmutable  setHour(int $value)                                                                Set current instance hour to the given value.
 * @method        CarbonImmutable  minutes(int $value)                                                                Set current instance minute to the given value.
 * @method        CarbonImmutable  minute(int $value)                                                                 Set current instance minute to the given value.
 * @method        CarbonImmutable  setMinutes(int $value)                                                             Set current instance minute to the given value.
 * @method        CarbonImmutable  setMinute(int $value)                                                              Set current instance minute to the given value.
 * @method        CarbonImmutable  seconds(int $value)                                                                Set current instance second to the given value.
 * @method        CarbonImmutable  second(int $value)                                                                 Set current instance second to the given value.
 * @method        CarbonImmutable  setSeconds(int $value)                                                             Set current instance second to the given value.
 * @method        CarbonImmutable  setSecond(int $value)                                                              Set current instance second to the given value.
 * @method        CarbonImmutable  millis(int $value)                                                                 Set current instance millisecond to the given value.
 * @method        CarbonImmutable  milli(int $value)                                                                  Set current instance millisecond to the given value.
 * @method        CarbonImmutable  setMillis(int $value)                                                              Set current instance millisecond to the given value.
 * @method        CarbonImmutable  setMilli(int $value)                                                               Set current instance millisecond to the given value.
 * @method        CarbonImmutable  milliseconds(int $value)                                                           Set current instance millisecond to the given value.
 * @method        CarbonImmutable  millisecond(int $value)                                                            Set current instance millisecond to the given value.
 * @method        CarbonImmutable  setMilliseconds(int $value)                                                        Set current instance millisecond to the given value.
 * @method        CarbonImmutable  setMillisecond(int $value)                                                         Set current instance millisecond to the given value.
 * @method        CarbonImmutable  micros(int $value)                                                                 Set current instance microsecond to the given value.
 * @method        CarbonImmutable  micro(int $value)                                                                  Set current instance microsecond to the given value.
 * @method        CarbonImmutable  setMicros(int $value)                                                              Set current instance microsecond to the given value.
 * @method        CarbonImmutable  setMicro(int $value)                                                               Set current instance microsecond to the given value.
 * @method        CarbonImmutable  microseconds(int $value)                                                           Set current instance microsecond to the given value.
 * @method        CarbonImmutable  microsecond(int $value)                                                            Set current instance microsecond to the given value.
 * @method        CarbonImmutable  setMicroseconds(int $value)                                                        Set current instance microsecond to the given value.
 * @method        self             setMicrosecond(int $value)                                                         Set current instance microsecond to the given value.
 * @method        CarbonImmutable  addYears(int|float $value = 1)                                                     Add years (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addYear()                                                                          Add one year to the instance (using date interval).
 * @method        CarbonImmutable  subYears(int|float $value = 1)                                                     Sub years (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subYear()                                                                          Sub one year to the instance (using date interval).
 * @method        CarbonImmutable  addYearsWithOverflow(int|float $value = 1)                                         Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addYearWithOverflow()                                                              Add one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subYearsWithOverflow(int|float $value = 1)                                         Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subYearWithOverflow()                                                              Sub one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addYearsWithoutOverflow(int|float $value = 1)                                      Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addYearWithoutOverflow()                                                           Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subYearsWithoutOverflow(int|float $value = 1)                                      Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subYearWithoutOverflow()                                                           Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addYearsWithNoOverflow(int|float $value = 1)                                       Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addYearWithNoOverflow()                                                            Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subYearsWithNoOverflow(int|float $value = 1)                                       Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subYearWithNoOverflow()                                                            Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addYearsNoOverflow(int|float $value = 1)                                           Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addYearNoOverflow()                                                                Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subYearsNoOverflow(int|float $value = 1)                                           Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subYearNoOverflow()                                                                Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMonths(int|float $value = 1)                                                    Add months (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMonth()                                                                         Add one month to the instance (using date interval).
 * @method        CarbonImmutable  subMonths(int|float $value = 1)                                                    Sub months (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMonth()                                                                         Sub one month to the instance (using date interval).
 * @method        CarbonImmutable  addMonthsWithOverflow(int|float $value = 1)                                        Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addMonthWithOverflow()                                                             Add one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subMonthsWithOverflow(int|float $value = 1)                                        Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subMonthWithOverflow()                                                             Sub one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addMonthsWithoutOverflow(int|float $value = 1)                                     Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMonthWithoutOverflow()                                                          Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMonthsWithoutOverflow(int|float $value = 1)                                     Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMonthWithoutOverflow()                                                          Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMonthsWithNoOverflow(int|float $value = 1)                                      Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMonthWithNoOverflow()                                                           Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMonthsWithNoOverflow(int|float $value = 1)                                      Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMonthWithNoOverflow()                                                           Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMonthsNoOverflow(int|float $value = 1)                                          Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMonthNoOverflow()                                                               Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMonthsNoOverflow(int|float $value = 1)                                          Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMonthNoOverflow()                                                               Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDays(int|float $value = 1)                                                      Add days (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addDay()                                                                           Add one day to the instance (using date interval).
 * @method        CarbonImmutable  subDays(int|float $value = 1)                                                      Sub days (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subDay()                                                                           Sub one day to the instance (using date interval).
 * @method        CarbonImmutable  addHours(int|float $value = 1)                                                     Add hours (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addHour()                                                                          Add one hour to the instance (using date interval).
 * @method        CarbonImmutable  subHours(int|float $value = 1)                                                     Sub hours (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subHour()                                                                          Sub one hour to the instance (using date interval).
 * @method        CarbonImmutable  addMinutes(int|float $value = 1)                                                   Add minutes (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMinute()                                                                        Add one minute to the instance (using date interval).
 * @method        CarbonImmutable  subMinutes(int|float $value = 1)                                                   Sub minutes (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMinute()                                                                        Sub one minute to the instance (using date interval).
 * @method        CarbonImmutable  addSeconds(int|float $value = 1)                                                   Add seconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addSecond()                                                                        Add one second to the instance (using date interval).
 * @method        CarbonImmutable  subSeconds(int|float $value = 1)                                                   Sub seconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subSecond()                                                                        Sub one second to the instance (using date interval).
 * @method        CarbonImmutable  addMillis(int|float $value = 1)                                                    Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMilli()                                                                         Add one millisecond to the instance (using date interval).
 * @method        CarbonImmutable  subMillis(int|float $value = 1)                                                    Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMilli()                                                                         Sub one millisecond to the instance (using date interval).
 * @method        CarbonImmutable  addMilliseconds(int|float $value = 1)                                              Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMillisecond()                                                                   Add one millisecond to the instance (using date interval).
 * @method        CarbonImmutable  subMilliseconds(int|float $value = 1)                                              Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMillisecond()                                                                   Sub one millisecond to the instance (using date interval).
 * @method        CarbonImmutable  addMicros(int|float $value = 1)                                                    Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMicro()                                                                         Add one microsecond to the instance (using date interval).
 * @method        CarbonImmutable  subMicros(int|float $value = 1)                                                    Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMicro()                                                                         Sub one microsecond to the instance (using date interval).
 * @method        CarbonImmutable  addMicroseconds(int|float $value = 1)                                              Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMicrosecond()                                                                   Add one microsecond to the instance (using date interval).
 * @method        CarbonImmutable  subMicroseconds(int|float $value = 1)                                              Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMicrosecond()                                                                   Sub one microsecond to the instance (using date interval).
 * @method        CarbonImmutable  addMillennia(int|float $value = 1)                                                 Add millennia (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addMillennium()                                                                    Add one millennium to the instance (using date interval).
 * @method        CarbonImmutable  subMillennia(int|float $value = 1)                                                 Sub millennia (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subMillennium()                                                                    Sub one millennium to the instance (using date interval).
 * @method        CarbonImmutable  addMillenniaWithOverflow(int|float $value = 1)                                     Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addMillenniumWithOverflow()                                                        Add one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subMillenniaWithOverflow(int|float $value = 1)                                     Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subMillenniumWithOverflow()                                                        Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addMillenniaWithoutOverflow(int|float $value = 1)                                  Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMillenniumWithoutOverflow()                                                     Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMillenniaWithoutOverflow(int|float $value = 1)                                  Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMillenniumWithoutOverflow()                                                     Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMillenniaWithNoOverflow(int|float $value = 1)                                   Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMillenniumWithNoOverflow()                                                      Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMillenniaWithNoOverflow(int|float $value = 1)                                   Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMillenniumWithNoOverflow()                                                      Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMillenniaNoOverflow(int|float $value = 1)                                       Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addMillenniumNoOverflow()                                                          Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMillenniaNoOverflow(int|float $value = 1)                                       Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subMillenniumNoOverflow()                                                          Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addCenturies(int|float $value = 1)                                                 Add centuries (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addCentury()                                                                       Add one century to the instance (using date interval).
 * @method        CarbonImmutable  subCenturies(int|float $value = 1)                                                 Sub centuries (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subCentury()                                                                       Sub one century to the instance (using date interval).
 * @method        CarbonImmutable  addCenturiesWithOverflow(int|float $value = 1)                                     Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addCenturyWithOverflow()                                                           Add one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subCenturiesWithOverflow(int|float $value = 1)                                     Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subCenturyWithOverflow()                                                           Sub one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addCenturiesWithoutOverflow(int|float $value = 1)                                  Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addCenturyWithoutOverflow()                                                        Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subCenturiesWithoutOverflow(int|float $value = 1)                                  Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subCenturyWithoutOverflow()                                                        Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addCenturiesWithNoOverflow(int|float $value = 1)                                   Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addCenturyWithNoOverflow()                                                         Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subCenturiesWithNoOverflow(int|float $value = 1)                                   Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subCenturyWithNoOverflow()                                                         Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addCenturiesNoOverflow(int|float $value = 1)                                       Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addCenturyNoOverflow()                                                             Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subCenturiesNoOverflow(int|float $value = 1)                                       Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subCenturyNoOverflow()                                                             Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDecades(int|float $value = 1)                                                   Add decades (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addDecade()                                                                        Add one decade to the instance (using date interval).
 * @method        CarbonImmutable  subDecades(int|float $value = 1)                                                   Sub decades (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subDecade()                                                                        Sub one decade to the instance (using date interval).
 * @method        CarbonImmutable  addDecadesWithOverflow(int|float $value = 1)                                       Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addDecadeWithOverflow()                                                            Add one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subDecadesWithOverflow(int|float $value = 1)                                       Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subDecadeWithOverflow()                                                            Sub one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addDecadesWithoutOverflow(int|float $value = 1)                                    Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDecadeWithoutOverflow()                                                         Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subDecadesWithoutOverflow(int|float $value = 1)                                    Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subDecadeWithoutOverflow()                                                         Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDecadesWithNoOverflow(int|float $value = 1)                                     Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDecadeWithNoOverflow()                                                          Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subDecadesWithNoOverflow(int|float $value = 1)                                     Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subDecadeWithNoOverflow()                                                          Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDecadesNoOverflow(int|float $value = 1)                                         Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addDecadeNoOverflow()                                                              Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subDecadesNoOverflow(int|float $value = 1)                                         Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subDecadeNoOverflow()                                                              Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addQuarters(int|float $value = 1)                                                  Add quarters (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addQuarter()                                                                       Add one quarter to the instance (using date interval).
 * @method        CarbonImmutable  subQuarters(int|float $value = 1)                                                  Sub quarters (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subQuarter()                                                                       Sub one quarter to the instance (using date interval).
 * @method        CarbonImmutable  addQuartersWithOverflow(int|float $value = 1)                                      Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addQuarterWithOverflow()                                                           Add one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subQuartersWithOverflow(int|float $value = 1)                                      Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  subQuarterWithOverflow()                                                           Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonImmutable  addQuartersWithoutOverflow(int|float $value = 1)                                   Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addQuarterWithoutOverflow()                                                        Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subQuartersWithoutOverflow(int|float $value = 1)                                   Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subQuarterWithoutOverflow()                                                        Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addQuartersWithNoOverflow(int|float $value = 1)                                    Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addQuarterWithNoOverflow()                                                         Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subQuartersWithNoOverflow(int|float $value = 1)                                    Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subQuarterWithNoOverflow()                                                         Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addQuartersNoOverflow(int|float $value = 1)                                        Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addQuarterNoOverflow()                                                             Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subQuartersNoOverflow(int|float $value = 1)                                        Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  subQuarterNoOverflow()                                                             Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonImmutable  addWeeks(int|float $value = 1)                                                     Add weeks (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addWeek()                                                                          Add one week to the instance (using date interval).
 * @method        CarbonImmutable  subWeeks(int|float $value = 1)                                                     Sub weeks (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subWeek()                                                                          Sub one week to the instance (using date interval).
 * @method        CarbonImmutable  addWeekdays(int|float $value = 1)                                                  Add weekdays (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  addWeekday()                                                                       Add one weekday to the instance (using date interval).
 * @method        CarbonImmutable  subWeekdays(int|float $value = 1)                                                  Sub weekdays (the $value count passed in) to the instance (using date interval).
 * @method        CarbonImmutable  subWeekday()                                                                       Sub one weekday to the instance (using date interval).
 * @method        CarbonImmutable  addUTCMicros(int|float $value = 1)                                                 Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMicro()                                                                      Add one microsecond to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMicros(int|float $value = 1)                                                 Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMicro()                                                                      Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicros(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        CarbonImmutable  addUTCMicroseconds(int|float $value = 1)                                           Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMicrosecond()                                                                Add one microsecond to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMicroseconds(int|float $value = 1)                                           Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMicrosecond()                                                                Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicroseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        CarbonImmutable  addUTCMillis(int|float $value = 1)                                                 Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMilli()                                                                      Add one millisecond to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMillis(int|float $value = 1)                                                 Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMilli()                                                                      Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMillis(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        CarbonImmutable  addUTCMilliseconds(int|float $value = 1)                                           Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMillisecond()                                                                Add one millisecond to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMilliseconds(int|float $value = 1)                                           Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMillisecond()                                                                Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMilliseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        CarbonImmutable  addUTCSeconds(int|float $value = 1)                                                Add seconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCSecond()                                                                     Add one second to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCSeconds(int|float $value = 1)                                                Sub seconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCSecond()                                                                     Sub one second to the instance (using timestamp).
 * @method        CarbonPeriod     secondsUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
 * @method        float            diffInUTCSeconds(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of seconds.
 * @method        CarbonImmutable  addUTCMinutes(int|float $value = 1)                                                Add minutes (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMinute()                                                                     Add one minute to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMinutes(int|float $value = 1)                                                Sub minutes (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMinute()                                                                     Sub one minute to the instance (using timestamp).
 * @method        CarbonPeriod     minutesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
 * @method        float            diffInUTCMinutes(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of minutes.
 * @method        CarbonImmutable  addUTCHours(int|float $value = 1)                                                  Add hours (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCHour()                                                                       Add one hour to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCHours(int|float $value = 1)                                                  Sub hours (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCHour()                                                                       Sub one hour to the instance (using timestamp).
 * @method        CarbonPeriod     hoursUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
 * @method        float            diffInUTCHours(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of hours.
 * @method        CarbonImmutable  addUTCDays(int|float $value = 1)                                                   Add days (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCDay()                                                                        Add one day to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCDays(int|float $value = 1)                                                   Sub days (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCDay()                                                                        Sub one day to the instance (using timestamp).
 * @method        CarbonPeriod     daysUntil($endDate = null, int|float $factor = 1)                                  Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
 * @method        float            diffInUTCDays(DateTimeInterface|string|null $date, bool $absolute = false)         Convert current and given date in UTC timezone and return a floating number of days.
 * @method        CarbonImmutable  addUTCWeeks(int|float $value = 1)                                                  Add weeks (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCWeek()                                                                       Add one week to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCWeeks(int|float $value = 1)                                                  Sub weeks (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCWeek()                                                                       Sub one week to the instance (using timestamp).
 * @method        CarbonPeriod     weeksUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
 * @method        float            diffInUTCWeeks(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of weeks.
 * @method        CarbonImmutable  addUTCMonths(int|float $value = 1)                                                 Add months (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMonth()                                                                      Add one month to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMonths(int|float $value = 1)                                                 Sub months (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMonth()                                                                      Sub one month to the instance (using timestamp).
 * @method        CarbonPeriod     monthsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
 * @method        float            diffInUTCMonths(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of months.
 * @method        CarbonImmutable  addUTCQuarters(int|float $value = 1)                                               Add quarters (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCQuarter()                                                                    Add one quarter to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCQuarters(int|float $value = 1)                                               Sub quarters (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCQuarter()                                                                    Sub one quarter to the instance (using timestamp).
 * @method        CarbonPeriod     quartersUntil($endDate = null, int|float $factor = 1)                              Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
 * @method        float            diffInUTCQuarters(DateTimeInterface|string|null $date, bool $absolute = false)     Convert current and given date in UTC timezone and return a floating number of quarters.
 * @method        CarbonImmutable  addUTCYears(int|float $value = 1)                                                  Add years (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCYear()                                                                       Add one year to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCYears(int|float $value = 1)                                                  Sub years (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCYear()                                                                       Sub one year to the instance (using timestamp).
 * @method        CarbonPeriod     yearsUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
 * @method        float            diffInUTCYears(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of years.
 * @method        CarbonImmutable  addUTCDecades(int|float $value = 1)                                                Add decades (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCDecade()                                                                     Add one decade to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCDecades(int|float $value = 1)                                                Sub decades (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCDecade()                                                                     Sub one decade to the instance (using timestamp).
 * @method        CarbonPeriod     decadesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
 * @method        float            diffInUTCDecades(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of decades.
 * @method        CarbonImmutable  addUTCCenturies(int|float $value = 1)                                              Add centuries (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCCentury()                                                                    Add one century to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCCenturies(int|float $value = 1)                                              Sub centuries (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCCentury()                                                                    Sub one century to the instance (using timestamp).
 * @method        CarbonPeriod     centuriesUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
 * @method        float            diffInUTCCenturies(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of centuries.
 * @method        CarbonImmutable  addUTCMillennia(int|float $value = 1)                                              Add millennia (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  addUTCMillennium()                                                                 Add one millennium to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMillennia(int|float $value = 1)                                              Sub millennia (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonImmutable  subUTCMillennium()                                                                 Sub one millennium to the instance (using timestamp).
 * @method        CarbonPeriod     millenniaUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
 * @method        float            diffInUTCMillennia(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of millennia.
 * @method        CarbonImmutable  roundYear(float $precision = 1, string $function = "round")                        Round the current instance year with given precision using the given function.
 * @method        CarbonImmutable  roundYears(float $precision = 1, string $function = "round")                       Round the current instance year with given precision using the given function.
 * @method        CarbonImmutable  floorYear(float $precision = 1)                                                    Truncate the current instance year with given precision.
 * @method        CarbonImmutable  floorYears(float $precision = 1)                                                   Truncate the current instance year with given precision.
 * @method        CarbonImmutable  ceilYear(float $precision = 1)                                                     Ceil the current instance year with given precision.
 * @method        CarbonImmutable  ceilYears(float $precision = 1)                                                    Ceil the current instance year with given precision.
 * @method        CarbonImmutable  roundMonth(float $precision = 1, string $function = "round")                       Round the current instance month with given precision using the given function.
 * @method        CarbonImmutable  roundMonths(float $precision = 1, string $function = "round")                      Round the current instance month with given precision using the given function.
 * @method        CarbonImmutable  floorMonth(float $precision = 1)                                                   Truncate the current instance month with given precision.
 * @method        CarbonImmutable  floorMonths(float $precision = 1)                                                  Truncate the current instance month with given precision.
 * @method        CarbonImmutable  ceilMonth(float $precision = 1)                                                    Ceil the current instance month with given precision.
 * @method        CarbonImmutable  ceilMonths(float $precision = 1)                                                   Ceil the current instance month with given precision.
 * @method        CarbonImmutable  roundDay(float $precision = 1, string $function = "round")                         Round the current instance day with given precision using the given function.
 * @method        CarbonImmutable  roundDays(float $precision = 1, string $function = "round")                        Round the current instance day with given precision using the given function.
 * @method        CarbonImmutable  floorDay(float $precision = 1)                                                     Truncate the current instance day with given precision.
 * @method        CarbonImmutable  floorDays(float $precision = 1)                                                    Truncate the current instance day with given precision.
 * @method        CarbonImmutable  ceilDay(float $precision = 1)                                                      Ceil the current instance day with given precision.
 * @method        CarbonImmutable  ceilDays(float $precision = 1)                                                     Ceil the current instance day with given precision.
 * @method        CarbonImmutable  roundHour(float $precision = 1, string $function = "round")                        Round the current instance hour with given precision using the given function.
 * @method        CarbonImmutable  roundHours(float $precision = 1, string $function = "round")                       Round the current instance hour with given precision using the given function.
 * @method        CarbonImmutable  floorHour(float $precision = 1)                                                    Truncate the current instance hour with given precision.
 * @method        CarbonImmutable  floorHours(float $precision = 1)                                                   Truncate the current instance hour with given precision.
 * @method        CarbonImmutable  ceilHour(float $precision = 1)                                                     Ceil the current instance hour with given precision.
 * @method        CarbonImmutable  ceilHours(float $precision = 1)                                                    Ceil the current instance hour with given precision.
 * @method        CarbonImmutable  roundMinute(float $precision = 1, string $function = "round")                      Round the current instance minute with given precision using the given function.
 * @method        CarbonImmutable  roundMinutes(float $precision = 1, string $function = "round")                     Round the current instance minute with given precision using the given function.
 * @method        CarbonImmutable  floorMinute(float $precision = 1)                                                  Truncate the current instance minute with given precision.
 * @method        CarbonImmutable  floorMinutes(float $precision = 1)                                                 Truncate the current instance minute with given precision.
 * @method        CarbonImmutable  ceilMinute(float $precision = 1)                                                   Ceil the current instance minute with given precision.
 * @method        CarbonImmutable  ceilMinutes(float $precision = 1)                                                  Ceil the current instance minute with given precision.
 * @method        CarbonImmutable  roundSecond(float $precision = 1, string $function = "round")                      Round the current instance second with given precision using the given function.
 * @method        CarbonImmutable  roundSeconds(float $precision = 1, string $function = "round")                     Round the current instance second with given precision using the given function.
 * @method        CarbonImmutable  floorSecond(float $precision = 1)                                                  Truncate the current instance second with given precision.
 * @method        CarbonImmutable  floorSeconds(float $precision = 1)                                                 Truncate the current instance second with given precision.
 * @method        CarbonImmutable  ceilSecond(float $precision = 1)                                                   Ceil the current instance second with given precision.
 * @method        CarbonImmutable  ceilSeconds(float $precision = 1)                                                  Ceil the current instance second with given precision.
 * @method        CarbonImmutable  roundMillennium(float $precision = 1, string $function = "round")                  Round the current instance millennium with given precision using the given function.
 * @method        CarbonImmutable  roundMillennia(float $precision = 1, string $function = "round")                   Round the current instance millennium with given precision using the given function.
 * @method        CarbonImmutable  floorMillennium(float $precision = 1)                                              Truncate the current instance millennium with given precision.
 * @method        CarbonImmutable  floorMillennia(float $precision = 1)                                               Truncate the current instance millennium with given precision.
 * @method        CarbonImmutable  ceilMillennium(float $precision = 1)                                               Ceil the current instance millennium with given precision.
 * @method        CarbonImmutable  ceilMillennia(float $precision = 1)                                                Ceil the current instance millennium with given precision.
 * @method        CarbonImmutable  roundCentury(float $precision = 1, string $function = "round")                     Round the current instance century with given precision using the given function.
 * @method        CarbonImmutable  roundCenturies(float $precision = 1, string $function = "round")                   Round the current instance century with given precision using the given function.
 * @method        CarbonImmutable  floorCentury(float $precision = 1)                                                 Truncate the current instance century with given precision.
 * @method        CarbonImmutable  floorCenturies(float $precision = 1)                                               Truncate the current instance century with given precision.
 * @method        CarbonImmutable  ceilCentury(float $precision = 1)                                                  Ceil the current instance century with given precision.
 * @method        CarbonImmutable  ceilCenturies(float $precision = 1)                                                Ceil the current instance century with given precision.
 * @method        CarbonImmutable  roundDecade(float $precision = 1, string $function = "round")                      Round the current instance decade with given precision using the given function.
 * @method        CarbonImmutable  roundDecades(float $precision = 1, string $function = "round")                     Round the current instance decade with given precision using the given function.
 * @method        CarbonImmutable  floorDecade(float $precision = 1)                                                  Truncate the current instance decade with given precision.
 * @method        CarbonImmutable  floorDecades(float $precision = 1)                                                 Truncate the current instance decade with given precision.
 * @method        CarbonImmutable  ceilDecade(float $precision = 1)                                                   Ceil the current instance decade with given precision.
 * @method        CarbonImmutable  ceilDecades(float $precision = 1)                                                  Ceil the current instance decade with given precision.
 * @method        CarbonImmutable  roundQuarter(float $precision = 1, string $function = "round")                     Round the current instance quarter with given precision using the given function.
 * @method        CarbonImmutable  roundQuarters(float $precision = 1, string $function = "round")                    Round the current instance quarter with given precision using the given function.
 * @method        CarbonImmutable  floorQuarter(float $precision = 1)                                                 Truncate the current instance quarter with given precision.
 * @method        CarbonImmutable  floorQuarters(float $precision = 1)                                                Truncate the current instance quarter with given precision.
 * @method        CarbonImmutable  ceilQuarter(float $precision = 1)                                                  Ceil the current instance quarter with given precision.
 * @method        CarbonImmutable  ceilQuarters(float $precision = 1)                                                 Ceil the current instance quarter with given precision.
 * @method        CarbonImmutable  roundMillisecond(float $precision = 1, string $function = "round")                 Round the current instance millisecond with given precision using the given function.
 * @method        CarbonImmutable  roundMilliseconds(float $precision = 1, string $function = "round")                Round the current instance millisecond with given precision using the given function.
 * @method        CarbonImmutable  floorMillisecond(float $precision = 1)                                             Truncate the current instance millisecond with given precision.
 * @method        CarbonImmutable  floorMilliseconds(float $precision = 1)                                            Truncate the current instance millisecond with given precision.
 * @method        CarbonImmutable  ceilMillisecond(float $precision = 1)                                              Ceil the current instance millisecond with given precision.
 * @method        CarbonImmutable  ceilMilliseconds(float $precision = 1)                                             Ceil the current instance millisecond with given precision.
 * @method        CarbonImmutable  roundMicrosecond(float $precision = 1, string $function = "round")                 Round the current instance microsecond with given precision using the given function.
 * @method        CarbonImmutable  roundMicroseconds(float $precision = 1, string $function = "round")                Round the current instance microsecond with given precision using the given function.
 * @method        CarbonImmutable  floorMicrosecond(float $precision = 1)                                             Truncate the current instance microsecond with given precision.
 * @method        CarbonImmutable  floorMicroseconds(float $precision = 1)                                            Truncate the current instance microsecond with given precision.
 * @method        CarbonImmutable  ceilMicrosecond(float $precision = 1)                                              Ceil the current instance microsecond with given precision.
 * @method        CarbonImmutable  ceilMicroseconds(float $precision = 1)                                             Ceil the current instance microsecond with given precision.
 * @method        string           shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)   Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)    Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1)  Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        int              centuriesInMillennium()                                                            Return the number of centuries contained in the current millennium
 * @method        int|static       centuryOfMillennium(?int $century = null)                                          Return the value of the century starting from the beginning of the current millennium when called with no parameters, change the current century when called with an integer value
 * @method        int|static       dayOfCentury(?int $day = null)                                                     Return the value of the day starting from the beginning of the current century when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfDecade(?int $day = null)                                                      Return the value of the day starting from the beginning of the current decade when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMillennium(?int $day = null)                                                  Return the value of the day starting from the beginning of the current millennium when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMonth(?int $day = null)                                                       Return the value of the day starting from the beginning of the current month when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfQuarter(?int $day = null)                                                     Return the value of the day starting from the beginning of the current quarter when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfWeek(?int $day = null)                                                        Return the value of the day starting from the beginning of the current week when called with no parameters, change the current day when called with an integer value
 * @method        int              daysInCentury()                                                                    Return the number of days contained in the current century
 * @method        int              daysInDecade()                                                                     Return the number of days contained in the current decade
 * @method        int              daysInMillennium()                                                                 Return the number of days contained in the current millennium
 * @method        int              daysInMonth()                                                                      Return the number of days contained in the current month
 * @method        int              daysInQuarter()                                                                    Return the number of days contained in the current quarter
 * @method        int              daysInWeek()                                                                       Return the number of days contained in the current week
 * @method        int              daysInYear()                                                                       Return the number of days contained in the current year
 * @method        int|static       decadeOfCentury(?int $decade = null)                                               Return the value of the decade starting from the beginning of the current century when called with no parameters, change the current decade when called with an integer value
 * @method        int|static       decadeOfMillennium(?int $decade = null)                                            Return the value of the decade starting from the beginning of the current millennium when called with no parameters, change the current decade when called with an integer value
 * @method        int              decadesInCentury()                                                                 Return the number of decades contained in the current century
 * @method        int              decadesInMillennium()                                                              Return the number of decades contained in the current millennium
 * @method        int|static       hourOfCentury(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current century when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDay(?int $hour = null)                                                       Return the value of the hour starting from the beginning of the current day when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDecade(?int $hour = null)                                                    Return the value of the hour starting from the beginning of the current decade when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMillennium(?int $hour = null)                                                Return the value of the hour starting from the beginning of the current millennium when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMonth(?int $hour = null)                                                     Return the value of the hour starting from the beginning of the current month when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfQuarter(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current quarter when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfWeek(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current week when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfYear(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current year when called with no parameters, change the current hour when called with an integer value
 * @method        int              hoursInCentury()                                                                   Return the number of hours contained in the current century
 * @method        int              hoursInDay()                                                                       Return the number of hours contained in the current day
 * @method        int              hoursInDecade()                                                                    Return the number of hours contained in the current decade
 * @method        int              hoursInMillennium()                                                                Return the number of hours contained in the current millennium
 * @method        int              hoursInMonth()                                                                     Return the number of hours contained in the current month
 * @method        int              hoursInQuarter()                                                                   Return the number of hours contained in the current quarter
 * @method        int              hoursInWeek()                                                                      Return the number of hours contained in the current week
 * @method        int              hoursInYear()                                                                      Return the number of hours contained in the current year
 * @method        int|static       microsecondOfCentury(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current century when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDay(?int $microsecond = null)                                         Return the value of the microsecond starting from the beginning of the current day when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDecade(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current decade when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfHour(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current hour when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillennium(?int $microsecond = null)                                  Return the value of the microsecond starting from the beginning of the current millennium when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillisecond(?int $microsecond = null)                                 Return the value of the microsecond starting from the beginning of the current millisecond when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMinute(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current minute when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMonth(?int $microsecond = null)                                       Return the value of the microsecond starting from the beginning of the current month when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfQuarter(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current quarter when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfSecond(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current second when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfWeek(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current week when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfYear(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current year when called with no parameters, change the current microsecond when called with an integer value
 * @method        int              microsecondsInCentury()                                                            Return the number of microseconds contained in the current century
 * @method        int              microsecondsInDay()                                                                Return the number of microseconds contained in the current day
 * @method        int              microsecondsInDecade()                                                             Return the number of microseconds contained in the current decade
 * @method        int              microsecondsInHour()                                                               Return the number of microseconds contained in the current hour
 * @method        int              microsecondsInMillennium()                                                         Return the number of microseconds contained in the current millennium
 * @method        int              microsecondsInMillisecond()                                                        Return the number of microseconds contained in the current millisecond
 * @method        int              microsecondsInMinute()                                                             Return the number of microseconds contained in the current minute
 * @method        int              microsecondsInMonth()                                                              Return the number of microseconds contained in the current month
 * @method        int              microsecondsInQuarter()                                                            Return the number of microseconds contained in the current quarter
 * @method        int              microsecondsInSecond()                                                             Return the number of microseconds contained in the current second
 * @method        int              microsecondsInWeek()                                                               Return the number of microseconds contained in the current week
 * @method        int              microsecondsInYear()                                                               Return the number of microseconds contained in the current year
 * @method        int|static       millisecondOfCentury(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current century when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDay(?int $millisecond = null)                                         Return the value of the millisecond starting from the beginning of the current day when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDecade(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current decade when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfHour(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current hour when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMillennium(?int $millisecond = null)                                  Return the value of the millisecond starting from the beginning of the current millennium when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMinute(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current minute when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMonth(?int $millisecond = null)                                       Return the value of the millisecond starting from the beginning of the current month when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfQuarter(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current quarter when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfSecond(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current second when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfWeek(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current week when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfYear(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current year when called with no parameters, change the current millisecond when called with an integer value
 * @method        int              millisecondsInCentury()                                                            Return the number of milliseconds contained in the current century
 * @method        int              millisecondsInDay()                                                                Return the number of milliseconds contained in the current day
 * @method        int              millisecondsInDecade()                                                             Return the number of milliseconds contained in the current decade
 * @method        int              millisecondsInHour()                                                               Return the number of milliseconds contained in the current hour
 * @method        int              millisecondsInMillennium()                                                         Return the number of milliseconds contained in the current millennium
 * @method        int              millisecondsInMinute()                                                             Return the number of milliseconds contained in the current minute
 * @method        int              millisecondsInMonth()                                                              Return the number of milliseconds contained in the current month
 * @method        int              millisecondsInQuarter()                                                            Return the number of milliseconds contained in the current quarter
 * @method        int              millisecondsInSecond()                                                             Return the number of milliseconds contained in the current second
 * @method        int              millisecondsInWeek()                                                               Return the number of milliseconds contained in the current week
 * @method        int              millisecondsInYear()                                                               Return the number of milliseconds contained in the current year
 * @method        int|static       minuteOfCentury(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current century when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDay(?int $minute = null)                                                   Return the value of the minute starting from the beginning of the current day when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDecade(?int $minute = null)                                                Return the value of the minute starting from the beginning of the current decade when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfHour(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current hour when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMillennium(?int $minute = null)                                            Return the value of the minute starting from the beginning of the current millennium when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMonth(?int $minute = null)                                                 Return the value of the minute starting from the beginning of the current month when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfQuarter(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current quarter when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfWeek(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current week when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfYear(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current year when called with no parameters, change the current minute when called with an integer value
 * @method        int              minutesInCentury()                                                                 Return the number of minutes contained in the current century
 * @method        int              minutesInDay()                                                                     Return the number of minutes contained in the current day
 * @method        int              minutesInDecade()                                                                  Return the number of minutes contained in the current decade
 * @method        int              minutesInHour()                                                                    Return the number of minutes contained in the current hour
 * @method        int              minutesInMillennium()                                                              Return the number of minutes contained in the current millennium
 * @method        int              minutesInMonth()                                                                   Return the number of minutes contained in the current month
 * @method        int              minutesInQuarter()                                                                 Return the number of minutes contained in the current quarter
 * @method        int              minutesInWeek()                                                                    Return the number of minutes contained in the current week
 * @method        int              minutesInYear()                                                                    Return the number of minutes contained in the current year
 * @method        int|static       monthOfCentury(?int $month = null)                                                 Return the value of the month starting from the beginning of the current century when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfDecade(?int $month = null)                                                  Return the value of the month starting from the beginning of the current decade when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfMillennium(?int $month = null)                                              Return the value of the month starting from the beginning of the current millennium when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfQuarter(?int $month = null)                                                 Return the value of the month starting from the beginning of the current quarter when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfYear(?int $month = null)                                                    Return the value of the month starting from the beginning of the current year when called with no parameters, change the current month when called with an integer value
 * @method        int              monthsInCentury()                                                                  Return the number of months contained in the current century
 * @method        int              monthsInDecade()                                                                   Return the number of months contained in the current decade
 * @method        int              monthsInMillennium()                                                               Return the number of months contained in the current millennium
 * @method        int              monthsInQuarter()                                                                  Return the number of months contained in the current quarter
 * @method        int              monthsInYear()                                                                     Return the number of months contained in the current year
 * @method        int|static       quarterOfCentury(?int $quarter = null)                                             Return the value of the quarter starting from the beginning of the current century when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfDecade(?int $quarter = null)                                              Return the value of the quarter starting from the beginning of the current decade when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfMillennium(?int $quarter = null)                                          Return the value of the quarter starting from the beginning of the current millennium when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfYear(?int $quarter = null)                                                Return the value of the quarter starting from the beginning of the current year when called with no parameters, change the current quarter when called with an integer value
 * @method        int              quartersInCentury()                                                                Return the number of quarters contained in the current century
 * @method        int              quartersInDecade()                                                                 Return the number of quarters contained in the current decade
 * @method        int              quartersInMillennium()                                                             Return the number of quarters contained in the current millennium
 * @method        int              quartersInYear()                                                                   Return the number of quarters contained in the current year
 * @method        int|static       secondOfCentury(?int $second = null)                                               Return the value of the second starting from the beginning of the current century when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDay(?int $second = null)                                                   Return the value of the second starting from the beginning of the current day when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDecade(?int $second = null)                                                Return the value of the second starting from the beginning of the current decade when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfHour(?int $second = null)                                                  Return the value of the second starting from the beginning of the current hour when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMillennium(?int $second = null)                                            Return the value of the second starting from the beginning of the current millennium when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMinute(?int $second = null)                                                Return the value of the second starting from the beginning of the current minute when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMonth(?int $second = null)                                                 Return the value of the second starting from the beginning of the current month when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfQuarter(?int $second = null)                                               Return the value of the second starting from the beginning of the current quarter when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfWeek(?int $second = null)                                                  Return the value of the second starting from the beginning of the current week when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfYear(?int $second = null)                                                  Return the value of the second starting from the beginning of the current year when called with no parameters, change the current second when called with an integer value
 * @method        int              secondsInCentury()                                                                 Return the number of seconds contained in the current century
 * @method        int              secondsInDay()                                                                     Return the number of seconds contained in the current day
 * @method        int              secondsInDecade()                                                                  Return the number of seconds contained in the current decade
 * @method        int              secondsInHour()                                                                    Return the number of seconds contained in the current hour
 * @method        int              secondsInMillennium()                                                              Return the number of seconds contained in the current millennium
 * @method        int              secondsInMinute()                                                                  Return the number of seconds contained in the current minute
 * @method        int              secondsInMonth()                                                                   Return the number of seconds contained in the current month
 * @method        int              secondsInQuarter()                                                                 Return the number of seconds contained in the current quarter
 * @method        int              secondsInWeek()                                                                    Return the number of seconds contained in the current week
 * @method        int              secondsInYear()                                                                    Return the number of seconds contained in the current year
 * @method        int|static       weekOfCentury(?int $week = null)                                                   Return the value of the week starting from the beginning of the current century when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfDecade(?int $week = null)                                                    Return the value of the week starting from the beginning of the current decade when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMillennium(?int $week = null)                                                Return the value of the week starting from the beginning of the current millennium when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMonth(?int $week = null)                                                     Return the value of the week starting from the beginning of the current month when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfQuarter(?int $week = null)                                                   Return the value of the week starting from the beginning of the current quarter when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfYear(?int $week = null)                                                      Return the value of the week starting from the beginning of the current year when called with no parameters, change the current week when called with an integer value
 * @method        int              weeksInCentury()                                                                   Return the number of weeks contained in the current century
 * @method        int              weeksInDecade()                                                                    Return the number of weeks contained in the current decade
 * @method        int              weeksInMillennium()                                                                Return the number of weeks contained in the current millennium
 * @method        int              weeksInMonth()                                                                     Return the number of weeks contained in the current month
 * @method        int              weeksInQuarter()                                                                   Return the number of weeks contained in the current quarter
 * @method        int|static       yearOfCentury(?int $year = null)                                                   Return the value of the year starting from the beginning of the current century when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfDecade(?int $year = null)                                                    Return the value of the year starting from the beginning of the current decade when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfMillennium(?int $year = null)                                                Return the value of the year starting from the beginning of the current millennium when called with no parameters, change the current year when called with an integer value
 * @method        int              yearsInCentury()                                                                   Return the number of years contained in the current century
 * @method        int              yearsInDecade()                                                                    Return the number of years contained in the current decade
 * @method        int              yearsInMillennium()                                                                Return the number of years contained in the current millennium
 *
 * </autodoc>
 */
class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
{
    use Date {
        __clone as dateTraitClone;
    }

    public function __clone(): void
    {
        $this->dateTraitClone();
        $this->endOfTime = false;
        $this->startOfTime = false;
    }

    /**
     * Create a very old date representing start of time.
     *
     * @return static
     */
    public static function startOfTime(): static
    {
        $date = static::parse('0001-01-01')->years(self::getStartOfTimeYear());
        $date->startOfTime = true;

        return $date;
    }

    /**
     * Create a very far date representing end of time.
     *
     * @return static
     */
    public static function endOfTime(): static
    {
        $date = static::parse('9999-12-31 23:59:59.999999')->years(self::getEndOfTimeYear());
        $date->endOfTime = true;

        return $date;
    }

    /**
     * @codeCoverageIgnore
     */
    private static function getEndOfTimeYear(): int
    {
        return 1118290769066902787; // PHP_INT_MAX no longer work since PHP 8.1
    }

    /**
     * @codeCoverageIgnore
     */
    private static function getStartOfTimeYear(): int
    {
        return -1118290769066898816; // PHP_INT_MIN no longer work since PHP 8.1
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Psr\Clock\ClockInterface as PsrClockInterface;
use RuntimeException;
use Symfony\Component\Clock\ClockInterface;

final class WrapperClock implements ClockInterface
{
    public function __construct(
        private PsrClockInterface|Factory|DateTimeInterface $currentClock,
    ) {
    }

    public function unwrap(): PsrClockInterface|Factory|DateTimeInterface
    {
        return $this->currentClock;
    }

    public function getFactory(): Factory
    {
        if ($this->currentClock instanceof Factory) {
            return $this->currentClock;
        }

        if ($this->currentClock instanceof DateTime) {
            $factory = new Factory();
            $factory->setTestNowAndTimezone($this->currentClock);

            return $factory;
        }

        if ($this->currentClock instanceof DateTimeImmutable) {
            $factory = new FactoryImmutable();
            $factory->setTestNowAndTimezone($this->currentClock);

            return $factory;
        }

        $factory = new FactoryImmutable();
        $factory->setTestNowAndTimezone(fn () => $this->currentClock->now());

        return $factory;
    }

    private function nowRaw(): DateTimeInterface
    {
        if ($this->currentClock instanceof DateTimeInterface) {
            return $this->currentClock;
        }

        if ($this->currentClock instanceof Factory) {
            return $this->currentClock->__call('now', []);
        }

        return $this->currentClock->now();
    }

    public function now(): DateTimeImmutable
    {
        $now = $this->nowRaw();

        return $now instanceof DateTimeImmutable
            ? $now
            : new CarbonImmutable($now);
    }

    /**
     * @template T of CarbonInterface
     *
     * @param class-string<T> $class
     *
     * @return T
     */
    public function nowAs(string $class, DateTimeZone|string|int|null $timezone = null): CarbonInterface
    {
        $now = $this->nowRaw();
        $date = $now instanceof $class ? $now : $class::instance($now);

        return $timezone === null ? $date : $date->setTimezone($timezone);
    }

    public function nowAsCarbon(DateTimeZone|string|int|null $timezone = null): CarbonInterface
    {
        $now = $this->nowRaw();

        return $now instanceof CarbonInterface
            ? ($timezone === null ? $now : $now->setTimezone($timezone))
            : $this->dateAsCarbon($now, $timezone);
    }

    private function dateAsCarbon(DateTimeInterface $date, DateTimeZone|string|int|null $timezone): CarbonInterface
    {
        return $date instanceof DateTimeImmutable
            ? new CarbonImmutable($date, $timezone)
            : new Carbon($date, $timezone);
    }

    public function sleep(float|int $seconds): void
    {
        if ($seconds === 0 || $seconds === 0.0) {
            return;
        }

        if ($seconds < 0) {
            throw new RuntimeException('Expected positive number of seconds, '.$seconds.' given');
        }

        if ($this->currentClock instanceof DateTimeInterface) {
            $this->currentClock = $this->addSeconds($this->currentClock, $seconds);

            return;
        }

        if ($this->currentClock instanceof ClockInterface) {
            $this->currentClock->sleep($seconds);

            return;
        }

        $this->currentClock = $this->addSeconds($this->currentClock->now(), $seconds);
    }

    public function withTimeZone(DateTimeZone|string $timezone): static
    {
        if ($this->currentClock instanceof ClockInterface) {
            return new self($this->currentClock->withTimeZone($timezone));
        }

        $now = $this->currentClock instanceof DateTimeInterface
            ? $this->currentClock
            : $this->currentClock->now();

        if (!($now instanceof DateTimeImmutable)) {
            $now = clone $now;
        }

        if (\is_string($timezone)) {
            $timezone = new DateTimeZone($timezone);
        }

        return new self($now->setTimezone($timezone));
    }

    private function addSeconds(DateTimeInterface $date, float|int $seconds): DateTimeInterface
    {
        $secondsPerHour = CarbonInterface::SECONDS_PER_MINUTE * CarbonInterface::MINUTES_PER_HOUR;
        $hours = number_format(
            floor($seconds / $secondsPerHour),
            thousands_separator: '',
        );
        $microseconds = number_format(
            ($seconds - $hours * $secondsPerHour) * CarbonInterface::MICROSECONDS_PER_SECOND,
            thousands_separator: '',
        );

        if (!($date instanceof DateTimeImmutable)) {
            $date = clone $date;
        }

        if ($hours !== '0') {
            $date = $date->modify("$hours hours");
        }

        if ($microseconds !== '0') {
            $date = $date->modify("$microseconds microseconds");
        }

        return $date;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\MessageFormatter;

use ReflectionMethod;
use Symfony\Component\Translation\Formatter\MessageFormatter;
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;

// @codeCoverageIgnoreStart
$transMethod = new ReflectionMethod(MessageFormatterInterface::class, 'format');

require $transMethod->getParameters()[0]->hasType()
    ? __DIR__.'/../../../lazy/Carbon/MessageFormatter/MessageFormatterMapperStrongType.php'
    : __DIR__.'/../../../lazy/Carbon/MessageFormatter/MessageFormatterMapperWeakType.php';
// @codeCoverageIgnoreEnd

final class MessageFormatterMapper extends LazyMessageFormatter
{
    /**
     * Wrapped formatter.
     *
     * @var MessageFormatterInterface
     */
    protected $formatter;

    public function __construct(?MessageFormatterInterface $formatter = null)
    {
        $this->formatter = $formatter ?? new MessageFormatter();
    }

    protected function transformLocale(?string $locale): ?string
    {
        return $locale ? preg_replace('/[_@][A-Za-z][a-z]{2,}/', '', $locale) : $locale;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Exceptions\InvalidCastException;
use Carbon\Exceptions\InvalidTimeZoneException;
use Carbon\Traits\LocalFactory;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Exception;
use Throwable;

class CarbonTimeZone extends DateTimeZone
{
    use LocalFactory;

    public const MAXIMUM_TIMEZONE_OFFSET = 99;

    public function __construct(string|int|float $timezone)
    {
        $this->initLocalFactory();

        parent::__construct(static::getDateTimeZoneNameFromMixed($timezone));
    }

    protected static function parseNumericTimezone(string|int|float $timezone): string
    {
        if (abs((float) $timezone) > static::MAXIMUM_TIMEZONE_OFFSET) {
            throw new InvalidTimeZoneException(
                'Absolute timezone offset cannot be greater than '.
                static::MAXIMUM_TIMEZONE_OFFSET.'.',
            );
        }

        return ($timezone >= 0 ? '+' : '').ltrim((string) $timezone, '+').':00';
    }

    protected static function getDateTimeZoneNameFromMixed(string|int|float $timezone): string
    {
        if (\is_string($timezone)) {
            $timezone = preg_replace('/^\s*([+-]\d+)(\d{2})\s*$/', '$1:$2', $timezone);
        }

        if (is_numeric($timezone)) {
            return static::parseNumericTimezone($timezone);
        }

        return $timezone;
    }

    /**
     * Cast the current instance into the given class.
     *
     * @param class-string<DateTimeZone> $className The $className::instance() method will be called to cast the current object.
     *
     * @return DateTimeZone|mixed
     */
    public function cast(string $className): mixed
    {
        if (!method_exists($className, 'instance')) {
            if (is_a($className, DateTimeZone::class, true)) {
                return new $className($this->getName());
            }

            throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
        }

        return $className::instance($this);
    }

    /**
     * Create a CarbonTimeZone from mixed input.
     *
     * @param DateTimeZone|string|int|false|null $object     original value to get CarbonTimeZone from it.
     * @param DateTimeZone|string|int|false|null $objectDump dump of the object for error messages.
     *
     * @throws InvalidTimeZoneException
     *
     * @return static|null
     */
    public static function instance(
        DateTimeZone|string|int|false|null $object,
        DateTimeZone|string|int|false|null $objectDump = null,
    ): ?self {
        $timezone = $object;

        if ($timezone instanceof static) {
            return $timezone;
        }

        if ($timezone === null || $timezone === false) {
            return null;
        }

        try {
            if (!($timezone instanceof DateTimeZone)) {
                $name = static::getDateTimeZoneNameFromMixed($object);
                $timezone = new static($name);
            }

            return $timezone instanceof static ? $timezone : new static($timezone->getName());
        } catch (Exception $exception) {
            throw new InvalidTimeZoneException(
                'Unknown or bad timezone ('.($objectDump ?: $object).')',
                previous: $exception,
            );
        }
    }

    /**
     * Returns abbreviated name of the current timezone according to DST setting.
     *
     * @param bool $dst
     *
     * @return string
     */
    public function getAbbreviatedName(bool $dst = false): string
    {
        $name = $this->getName();

        $date = new DateTimeImmutable($dst ? 'July 1' : 'January 1', $this);
        $timezone = $date->format('T');
        $abbreviations = $this->listAbbreviations();
        $matchingZones = array_merge($abbreviations[$timezone] ?? [], $abbreviations[strtolower($timezone)] ?? []);

        if ($matchingZones !== []) {
            foreach ($matchingZones as $zone) {
                if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) {
                    return $timezone;
                }
            }
        }

        foreach ($abbreviations as $abbreviation => $zones) {
            foreach ($zones as $zone) {
                if ($zone['timezone_id'] === $name && $zone['dst'] == $dst) {
                    return strtoupper($abbreviation);
                }
            }
        }

        return 'unknown';
    }

    /**
     * @alias getAbbreviatedName
     *
     * Returns abbreviated name of the current timezone according to DST setting.
     *
     * @param bool $dst
     *
     * @return string
     */
    public function getAbbr(bool $dst = false): string
    {
        return $this->getAbbreviatedName($dst);
    }

    /**
     * Get the offset as string "sHH:MM" (such as "+00:00" or "-12:30").
     */
    public function toOffsetName(?DateTimeInterface $date = null): string
    {
        return static::getOffsetNameFromMinuteOffset(
            $this->getOffset($this->resolveCarbon($date)) / 60,
        );
    }

    /**
     * Returns a new CarbonTimeZone object using the offset string instead of region string.
     */
    public function toOffsetTimeZone(?DateTimeInterface $date = null): static
    {
        return new static($this->toOffsetName($date));
    }

    /**
     * Returns the first region string (such as "America/Toronto") that matches the current timezone or
     * false if no match is found.
     *
     * @see timezone_name_from_abbr native PHP function.
     */
    public function toRegionName(?DateTimeInterface $date = null, int $isDST = 1): ?string
    {
        $name = $this->getName();
        $firstChar = substr($name, 0, 1);

        if ($firstChar !== '+' && $firstChar !== '-') {
            return $name;
        }

        $date = $this->resolveCarbon($date);

        // Integer construction no longer supported since PHP 8
        // @codeCoverageIgnoreStart
        try {
            $offset = @$this->getOffset($date) ?: 0;
        } catch (Throwable) {
            $offset = 0;
        }
        // @codeCoverageIgnoreEnd

        $name = @timezone_name_from_abbr('', $offset, $isDST);

        if ($name) {
            return $name;
        }

        foreach (timezone_identifiers_list() as $timezone) {
            if (Carbon::instance($date)->setTimezone($timezone)->getOffset() === $offset) {
                return $timezone;
            }
        }

        return null;
    }

    /**
     * Returns a new CarbonTimeZone object using the region string instead of offset string.
     */
    public function toRegionTimeZone(?DateTimeInterface $date = null): ?self
    {
        $timezone = $this->toRegionName($date);

        if ($timezone !== null) {
            return new static($timezone);
        }

        if (Carbon::isStrictModeEnabled()) {
            throw new InvalidTimeZoneException('Unknown timezone for offset '.$this->getOffset($this->resolveCarbon($date)).' seconds.');
        }

        return null;
    }

    /**
     * Cast to string (get timezone name).
     *
     * @return string
     */
    public function __toString()
    {
        return $this->getName();
    }

    /**
     * Return the type number:
     *
     * Type 1; A UTC offset, such as -0300
     * Type 2; A timezone abbreviation, such as GMT
     * Type 3: A timezone identifier, such as Europe/London
     */
    public function getType(): int
    {
        return preg_match('/"timezone_type";i:(\d)/', serialize($this), $match) ? (int) $match[1] : 3;
    }

    /**
     * Create a CarbonTimeZone from mixed input.
     *
     * @param DateTimeZone|string|int|null $object
     *
     * @return false|static
     */
    public static function create($object = null)
    {
        return static::instance($object);
    }

    /**
     * Create a CarbonTimeZone from int/float hour offset.
     *
     * @param float $hourOffset number of hour of the timezone shift (can be decimal).
     *
     * @return false|static
     */
    public static function createFromHourOffset(float $hourOffset)
    {
        return static::createFromMinuteOffset($hourOffset * Carbon::MINUTES_PER_HOUR);
    }

    /**
     * Create a CarbonTimeZone from int/float minute offset.
     *
     * @param float $minuteOffset number of total minutes of the timezone shift.
     *
     * @return false|static
     */
    public static function createFromMinuteOffset(float $minuteOffset)
    {
        return static::instance(static::getOffsetNameFromMinuteOffset($minuteOffset));
    }

    /**
     * Convert a total minutes offset into a standardized timezone offset string.
     *
     * @param float $minutes number of total minutes of the timezone shift.
     *
     * @return string
     */
    public static function getOffsetNameFromMinuteOffset(float $minutes): string
    {
        $minutes = round($minutes);
        $unsignedMinutes = abs($minutes);

        return ($minutes < 0 ? '-' : '+').
            str_pad((string) floor($unsignedMinutes / 60), 2, '0', STR_PAD_LEFT).
            ':'.
            str_pad((string) ($unsignedMinutes % 60), 2, '0', STR_PAD_LEFT);
    }

    private function resolveCarbon(?DateTimeInterface $date): DateTimeInterface
    {
        if ($date) {
            return $date;
        }

        if (isset($this->clock)) {
            return $this->clock->now()->setTimezone($this);
        }

        return Carbon::now($this);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Constants\UnitValue;
use Carbon\Exceptions\EndLessPeriodException;
use Carbon\Exceptions\InvalidCastException;
use Carbon\Exceptions\InvalidIntervalException;
use Carbon\Exceptions\InvalidPeriodDateException;
use Carbon\Exceptions\InvalidPeriodParameterException;
use Carbon\Exceptions\NotACarbonClassException;
use Carbon\Exceptions\NotAPeriodException;
use Carbon\Exceptions\UnknownGetterException;
use Carbon\Exceptions\UnknownMethodException;
use Carbon\Exceptions\UnreachableException;
use Carbon\Traits\DeprecatedPeriodProperties;
use Carbon\Traits\IntervalRounding;
use Carbon\Traits\LocalFactory;
use Carbon\Traits\Mixin;
use Carbon\Traits\Options;
use Carbon\Traits\ToStringFormat;
use Closure;
use Countable;
use DateInterval;
use DatePeriod;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Generator;
use InvalidArgumentException;
use JsonSerializable;
use ReflectionException;
use ReturnTypeWillChange;
use RuntimeException;
use Throwable;

// @codeCoverageIgnoreStart
require PHP_VERSION < 8.2
    ? __DIR__.'/../../lazy/Carbon/ProtectedDatePeriod.php'
    : __DIR__.'/../../lazy/Carbon/UnprotectedDatePeriod.php';
// @codeCoverageIgnoreEnd

/**
 * Substitution of DatePeriod with some modifications and many more features.
 *
 * @method static static|CarbonInterface start($date = null, $inclusive = null) Create instance specifying start date or modify the start date if called on an instance.
 * @method static static since($date = null, $inclusive = null) Alias for start().
 * @method static static sinceNow($inclusive = null) Create instance with start date set to now or set the start date to now if called on an instance.
 * @method static static|CarbonInterface end($date = null, $inclusive = null) Create instance specifying end date or modify the end date if called on an instance.
 * @method static static until($date = null, $inclusive = null) Alias for end().
 * @method static static untilNow($inclusive = null) Create instance with end date set to now or set the end date to now if called on an instance.
 * @method static static dates($start, $end = null) Create instance with start and end dates or modify the start and end dates if called on an instance.
 * @method static static between($start, $end = null) Create instance with start and end dates or modify the start and end dates if called on an instance.
 * @method static static recurrences($recurrences = null) Create instance with maximum number of recurrences or modify the number of recurrences if called on an instance.
 * @method static static times($recurrences = null) Alias for recurrences().
 * @method static static|int|null options($options = null) Create instance with options or modify the options if called on an instance.
 * @method static static toggle($options, $state = null) Create instance with options toggled on or off, or toggle options if called on an instance.
 * @method static static filter($callback, $name = null) Create instance with filter added to the stack or append a filter if called on an instance.
 * @method static static push($callback, $name = null) Alias for filter().
 * @method static static prepend($callback, $name = null) Create instance with filter prepended to the stack or prepend a filter if called on an instance.
 * @method static static|array filters(array $filters = []) Create instance with filters stack or replace the whole filters stack if called on an instance.
 * @method static static|CarbonInterval interval($interval = null) Create instance with given date interval or modify the interval if called on an instance.
 * @method static static each($interval) Create instance with given date interval or modify the interval if called on an instance.
 * @method static static every($interval) Create instance with given date interval or modify the interval if called on an instance.
 * @method static static step($interval) Create instance with given date interval or modify the interval if called on an instance.
 * @method static static stepBy($interval) Create instance with given date interval or modify the interval if called on an instance.
 * @method static static invert() Create instance with inverted date interval or invert the interval if called on an instance.
 * @method static static years($years = 1) Create instance specifying a number of years for date interval or replace the interval by the given a number of years if called on an instance.
 * @method static static year($years = 1) Alias for years().
 * @method static static months($months = 1) Create instance specifying a number of months for date interval or replace the interval by the given a number of months if called on an instance.
 * @method static static month($months = 1) Alias for months().
 * @method static static weeks($weeks = 1) Create instance specifying a number of weeks for date interval or replace the interval by the given a number of weeks if called on an instance.
 * @method static static week($weeks = 1) Alias for weeks().
 * @method static static days($days = 1) Create instance specifying a number of days for date interval or replace the interval by the given a number of days if called on an instance.
 * @method static static dayz($days = 1) Alias for days().
 * @method static static day($days = 1) Alias for days().
 * @method static static hours($hours = 1) Create instance specifying a number of hours for date interval or replace the interval by the given a number of hours if called on an instance.
 * @method static static hour($hours = 1) Alias for hours().
 * @method static static minutes($minutes = 1) Create instance specifying a number of minutes for date interval or replace the interval by the given a number of minutes if called on an instance.
 * @method static static minute($minutes = 1) Alias for minutes().
 * @method static static seconds($seconds = 1) Create instance specifying a number of seconds for date interval or replace the interval by the given a number of seconds if called on an instance.
 * @method static static second($seconds = 1) Alias for seconds().
 * @method static static milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds for date interval or replace the interval by the given a number of milliseconds if called on an instance.
 * @method static static millisecond($milliseconds = 1) Alias for milliseconds().
 * @method static static microseconds($microseconds = 1) Create instance specifying a number of microseconds for date interval or replace the interval by the given a number of microseconds if called on an instance.
 * @method static static microsecond($microseconds = 1) Alias for microseconds().
 * @method $this roundYear(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
 * @method $this roundYears(float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
 * @method $this floorYear(float $precision = 1) Truncate the current instance year with given precision.
 * @method $this floorYears(float $precision = 1) Truncate the current instance year with given precision.
 * @method $this ceilYear(float $precision = 1) Ceil the current instance year with given precision.
 * @method $this ceilYears(float $precision = 1) Ceil the current instance year with given precision.
 * @method $this roundMonth(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
 * @method $this roundMonths(float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
 * @method $this floorMonth(float $precision = 1) Truncate the current instance month with given precision.
 * @method $this floorMonths(float $precision = 1) Truncate the current instance month with given precision.
 * @method $this ceilMonth(float $precision = 1) Ceil the current instance month with given precision.
 * @method $this ceilMonths(float $precision = 1) Ceil the current instance month with given precision.
 * @method $this roundWeek(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this roundWeeks(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this floorWeek(float $precision = 1) Truncate the current instance day with given precision.
 * @method $this floorWeeks(float $precision = 1) Truncate the current instance day with given precision.
 * @method $this ceilWeek(float $precision = 1) Ceil the current instance day with given precision.
 * @method $this ceilWeeks(float $precision = 1) Ceil the current instance day with given precision.
 * @method $this roundDay(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this roundDays(float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this floorDay(float $precision = 1) Truncate the current instance day with given precision.
 * @method $this floorDays(float $precision = 1) Truncate the current instance day with given precision.
 * @method $this ceilDay(float $precision = 1) Ceil the current instance day with given precision.
 * @method $this ceilDays(float $precision = 1) Ceil the current instance day with given precision.
 * @method $this roundHour(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
 * @method $this roundHours(float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
 * @method $this floorHour(float $precision = 1) Truncate the current instance hour with given precision.
 * @method $this floorHours(float $precision = 1) Truncate the current instance hour with given precision.
 * @method $this ceilHour(float $precision = 1) Ceil the current instance hour with given precision.
 * @method $this ceilHours(float $precision = 1) Ceil the current instance hour with given precision.
 * @method $this roundMinute(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
 * @method $this roundMinutes(float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
 * @method $this floorMinute(float $precision = 1) Truncate the current instance minute with given precision.
 * @method $this floorMinutes(float $precision = 1) Truncate the current instance minute with given precision.
 * @method $this ceilMinute(float $precision = 1) Ceil the current instance minute with given precision.
 * @method $this ceilMinutes(float $precision = 1) Ceil the current instance minute with given precision.
 * @method $this roundSecond(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
 * @method $this roundSeconds(float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
 * @method $this floorSecond(float $precision = 1) Truncate the current instance second with given precision.
 * @method $this floorSeconds(float $precision = 1) Truncate the current instance second with given precision.
 * @method $this ceilSecond(float $precision = 1) Ceil the current instance second with given precision.
 * @method $this ceilSeconds(float $precision = 1) Ceil the current instance second with given precision.
 * @method $this roundMillennium(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
 * @method $this roundMillennia(float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
 * @method $this floorMillennium(float $precision = 1) Truncate the current instance millennium with given precision.
 * @method $this floorMillennia(float $precision = 1) Truncate the current instance millennium with given precision.
 * @method $this ceilMillennium(float $precision = 1) Ceil the current instance millennium with given precision.
 * @method $this ceilMillennia(float $precision = 1) Ceil the current instance millennium with given precision.
 * @method $this roundCentury(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
 * @method $this roundCenturies(float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
 * @method $this floorCentury(float $precision = 1) Truncate the current instance century with given precision.
 * @method $this floorCenturies(float $precision = 1) Truncate the current instance century with given precision.
 * @method $this ceilCentury(float $precision = 1) Ceil the current instance century with given precision.
 * @method $this ceilCenturies(float $precision = 1) Ceil the current instance century with given precision.
 * @method $this roundDecade(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
 * @method $this roundDecades(float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
 * @method $this floorDecade(float $precision = 1) Truncate the current instance decade with given precision.
 * @method $this floorDecades(float $precision = 1) Truncate the current instance decade with given precision.
 * @method $this ceilDecade(float $precision = 1) Ceil the current instance decade with given precision.
 * @method $this ceilDecades(float $precision = 1) Ceil the current instance decade with given precision.
 * @method $this roundQuarter(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
 * @method $this roundQuarters(float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
 * @method $this floorQuarter(float $precision = 1) Truncate the current instance quarter with given precision.
 * @method $this floorQuarters(float $precision = 1) Truncate the current instance quarter with given precision.
 * @method $this ceilQuarter(float $precision = 1) Ceil the current instance quarter with given precision.
 * @method $this ceilQuarters(float $precision = 1) Ceil the current instance quarter with given precision.
 * @method $this roundMillisecond(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
 * @method $this roundMilliseconds(float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
 * @method $this floorMillisecond(float $precision = 1) Truncate the current instance millisecond with given precision.
 * @method $this floorMilliseconds(float $precision = 1) Truncate the current instance millisecond with given precision.
 * @method $this ceilMillisecond(float $precision = 1) Ceil the current instance millisecond with given precision.
 * @method $this ceilMilliseconds(float $precision = 1) Ceil the current instance millisecond with given precision.
 * @method $this roundMicrosecond(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
 * @method $this roundMicroseconds(float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
 * @method $this floorMicrosecond(float $precision = 1) Truncate the current instance microsecond with given precision.
 * @method $this floorMicroseconds(float $precision = 1) Truncate the current instance microsecond with given precision.
 * @method $this ceilMicrosecond(float $precision = 1) Ceil the current instance microsecond with given precision.
 * @method $this ceilMicroseconds(float $precision = 1) Ceil the current instance microsecond with given precision.
 *
 * @mixin DeprecatedPeriodProperties
 *
 * @SuppressWarnings(TooManyFields)
 * @SuppressWarnings(CamelCasePropertyName)
 * @SuppressWarnings(CouplingBetweenObjects)
 */
class CarbonPeriod extends DatePeriodBase implements Countable, JsonSerializable, UnitValue
{
    use LocalFactory;
    use IntervalRounding;
    use Mixin {
        Mixin::mixin as baseMixin;
    }
    use Options {
        Options::__debugInfo as baseDebugInfo;
    }
    use ToStringFormat;

    /**
     * Built-in filter for limit by recurrences.
     *
     * @var callable
     */
    public const RECURRENCES_FILTER = [self::class, 'filterRecurrences'];

    /**
     * Built-in filter for limit to an end.
     *
     * @var callable
     */
    public const END_DATE_FILTER = [self::class, 'filterEndDate'];

    /**
     * Special value which can be returned by filters to end iteration. Also a filter.
     *
     * @var callable
     */
    public const END_ITERATION = [self::class, 'endIteration'];

    /**
     * Exclude end date from iteration.
     *
     * @var int
     */
    public const EXCLUDE_END_DATE = 8;

    /**
     * Yield CarbonImmutable instances.
     *
     * @var int
     */
    public const IMMUTABLE = 4;

    /**
     * Number of maximum attempts before giving up on finding next valid date.
     *
     * @var int
     */
    public const NEXT_MAX_ATTEMPTS = 1000;

    /**
     * Number of maximum attempts before giving up on finding end date.
     *
     * @var int
     */
    public const END_MAX_ATTEMPTS = 10000;

    /**
     * Default date class of iteration items.
     *
     * @var string
     */
    protected const DEFAULT_DATE_CLASS = Carbon::class;

    /**
     * The registered macros.
     */
    protected static array $macros = [];

    /**
     * Date class of iteration items.
     */
    protected string $dateClass = Carbon::class;

    /**
     * Underlying date interval instance. Always present, one day by default.
     */
    protected ?CarbonInterval $dateInterval = null;

    /**
     * True once __construct is finished.
     */
    protected bool $constructed = false;

    /**
     * Whether current date interval was set by default.
     */
    protected bool $isDefaultInterval = false;

    /**
     * The filters stack.
     */
    protected array $filters = [];

    /**
     * Period start date. Applied on rewind. Always present, now by default.
     */
    protected ?CarbonInterface $startDate = null;

    /**
     * Period end date. For inverted interval should be before the start date. Applied via a filter.
     */
    protected ?CarbonInterface $endDate = null;

    /**
     * Limit for number of recurrences. Applied via a filter.
     */
    protected int|float|null $carbonRecurrences = null;

    /**
     * Iteration options.
     */
    protected ?int $options = null;

    /**
     * Index of current date. Always sequential, even if some dates are skipped by filters.
     * Equal to null only before the first iteration.
     */
    protected int $key = 0;

    /**
     * Current date. May temporarily hold unaccepted value when looking for a next valid date.
     * Equal to null only before the first iteration.
     */
    protected ?CarbonInterface $carbonCurrent = null;

    /**
     * Timezone of current date. Taken from the start date.
     */
    protected ?DateTimeZone $timezone = null;

    /**
     * The cached validation result for current date.
     */
    protected array|string|bool|null $validationResult = null;

    /**
     * Timezone handler for settings() method.
     */
    protected DateTimeZone|string|int|null $timezoneSetting = null;

    public function getIterator(): Generator
    {
        $this->rewind();

        while ($this->valid()) {
            $key = $this->key();
            $value = $this->current();

            yield $key => $value;

            $this->next();
        }
    }

    /**
     * Make a CarbonPeriod instance from given variable if possible.
     */
    public static function make(mixed $var): ?static
    {
        try {
            return static::instance($var);
        } catch (NotAPeriodException) {
            return static::create($var);
        }
    }

    /**
     * Create a new instance from a DatePeriod or CarbonPeriod object.
     */
    public static function instance(mixed $period): static
    {
        if ($period instanceof static) {
            return $period->copy();
        }

        if ($period instanceof self) {
            return new static(
                $period->getStartDate(),
                $period->getEndDate() ?? $period->getRecurrences(),
                $period->getDateInterval(),
                $period->getOptions(),
            );
        }

        if ($period instanceof DatePeriod) {
            return new static(
                $period->start,
                $period->end ?: ($period->recurrences - 1),
                $period->interval,
                $period->include_start_date ? 0 : static::EXCLUDE_START_DATE,
            );
        }

        $class = static::class;
        $type = \gettype($period);
        $chunks = explode('::', __METHOD__);

        throw new NotAPeriodException(
            'Argument 1 passed to '.$class.'::'.end($chunks).'() '.
            'must be an instance of DatePeriod or '.$class.', '.
            ($type === 'object' ? 'instance of '.\get_class($period) : $type).' given.',
        );
    }

    /**
     * Create a new instance.
     */
    public static function create(...$params): static
    {
        return static::createFromArray($params);
    }

    /**
     * Create a new instance from an array of parameters.
     */
    public static function createFromArray(array $params): static
    {
        return new static(...$params);
    }

    /**
     * Create CarbonPeriod from ISO 8601 string.
     */
    public static function createFromIso(string $iso, ?int $options = null): static
    {
        $params = static::parseIso8601($iso);

        $instance = static::createFromArray($params);

        $instance->options = ($instance instanceof CarbonPeriodImmutable ? static::IMMUTABLE : 0) | $options;
        $instance->handleChangedParameters();

        return $instance;
    }

    public static function createFromISO8601String(string $iso, ?int $options = null): static
    {
        return self::createFromIso($iso, $options);
    }

    /**
     * Return whether the given interval contains non-zero value of any time unit.
     */
    protected static function intervalHasTime(DateInterval $interval): bool
    {
        return $interval->h || $interval->i || $interval->s || $interval->f;
    }

    /**
     * Return whether given variable is an ISO 8601 specification.
     *
     * Note: Check is very basic, as actual validation will be done later when parsing.
     * We just want to ensure that variable is not any other type of valid parameter.
     */
    protected static function isIso8601(mixed $var): bool
    {
        if (!\is_string($var)) {
            return false;
        }

        // Match slash but not within a timezone name.
        $part = '[a-z]+(?:[_-][a-z]+)*';

        preg_match("#\b$part/$part\b|(/)#i", $var, $match);

        return isset($match[1]);
    }

    /**
     * Parse given ISO 8601 string into an array of arguments.
     *
     * @SuppressWarnings(ElseExpression)
     */
    protected static function parseIso8601(string $iso): array
    {
        $result = [];

        $interval = null;
        $start = null;
        $end = null;
        $dateClass = static::DEFAULT_DATE_CLASS;

        foreach (explode('/', $iso) as $key => $part) {
            if ($key === 0 && preg_match('/^R(\d*|INF)$/', $part, $match)) {
                $parsed = \strlen($match[1]) ? (($match[1] !== 'INF') ? (int) $match[1] : INF) : null;
            } elseif ($interval === null && $parsed = self::makeInterval($part)) {
                $interval = $part;
            } elseif ($start === null && $parsed = $dateClass::make($part)) {
                $start = $part;
            } elseif ($end === null && $parsed = $dateClass::make(static::addMissingParts($start ?? '', $part))) {
                $end = $part;
            } else {
                throw new InvalidPeriodParameterException("Invalid ISO 8601 specification: $iso.");
            }

            $result[] = $parsed;
        }

        return $result;
    }

    /**
     * Add missing parts of the target date from the source date.
     */
    protected static function addMissingParts(string $source, string $target): string
    {
        $pattern = '/'.preg_replace('/\d+/', '[0-9]+', preg_quote($target, '/')).'$/';

        $result = preg_replace($pattern, $target, $source, 1, $count);

        return $count ? $result : $target;
    }

    private static function makeInterval(mixed $input): ?CarbonInterval
    {
        try {
            return CarbonInterval::make($input);
        } catch (Throwable) {
            return null;
        }
    }

    private static function makeTimezone(mixed $input): ?CarbonTimeZone
    {
        if (!\is_string($input)) {
            return null;
        }

        try {
            return CarbonTimeZone::create($input);
        } catch (Throwable) {
            return null;
        }
    }

    /**
     * Register a custom macro.
     *
     * Pass null macro to remove it.
     *
     * @example
     * ```
     * CarbonPeriod::macro('middle', function () {
     *   return $this->getStartDate()->average($this->getEndDate());
     * });
     * echo CarbonPeriod::since('2011-05-12')->until('2011-06-03')->middle();
     * ```
     *
     * @param-closure-this  static  $macro
     */
    public static function macro(string $name, ?callable $macro): void
    {
        static::$macros[$name] = $macro;
    }

    /**
     * Register macros from a mixin object.
     *
     * @example
     * ```
     * CarbonPeriod::mixin(new class {
     *   public function addDays() {
     *     return function ($count = 1) {
     *       return $this->setStartDate(
     *         $this->getStartDate()->addDays($count)
     *       )->setEndDate(
     *         $this->getEndDate()->addDays($count)
     *       );
     *     };
     *   }
     *   public function subDays() {
     *     return function ($count = 1) {
     *       return $this->setStartDate(
     *         $this->getStartDate()->subDays($count)
     *       )->setEndDate(
     *         $this->getEndDate()->subDays($count)
     *       );
     *     };
     *   }
     * });
     * echo CarbonPeriod::create('2000-01-01', '2000-02-01')->addDays(5)->subDays(3);
     * ```
     *
     * @throws ReflectionException
     */
    public static function mixin(object|string $mixin): void
    {
        static::baseMixin($mixin);
    }

    /**
     * Check if macro is registered.
     */
    public static function hasMacro(string $name): bool
    {
        return isset(static::$macros[$name]);
    }

    /**
     * Provide static proxy for instance aliases.
     */
    public static function __callStatic(string $method, array $parameters): mixed
    {
        $date = new static();

        if (static::hasMacro($method)) {
            return static::bindMacroContext(null, static fn () => $date->callMacro($method, $parameters));
        }

        return $date->$method(...$parameters);
    }

    /**
     * CarbonPeriod constructor.
     *
     * @SuppressWarnings(ElseExpression)
     *
     * @throws InvalidArgumentException
     */
    public function __construct(...$arguments)
    {
        $raw = null;

        if (isset($arguments['raw'])) {
            $raw = $arguments['raw'];
            $this->isDefaultInterval = $arguments['isDefaultInterval'] ?? false;

            if (isset($arguments['dateClass'])) {
                $this->dateClass = $arguments['dateClass'];
            }

            $arguments = $raw;
        }

        // Parse and assign arguments one by one. First argument may be an ISO 8601 spec,
        // which will be first parsed into parts and then processed the same way.

        $argumentsCount = \count($arguments);

        if ($argumentsCount && static::isIso8601($iso = $arguments[0])) {
            array_splice($arguments, 0, 1, static::parseIso8601($iso));
        }

        if ($argumentsCount === 1) {
            if ($arguments[0] instanceof self) {
                $arguments = [
                    $arguments[0]->getStartDate(),
                    $arguments[0]->getEndDate() ?? $arguments[0]->getRecurrences(),
                    $arguments[0]->getDateInterval(),
                    $arguments[0]->getOptions(),
                ];
            } elseif ($arguments[0] instanceof DatePeriod) {
                $arguments = [
                    $arguments[0]->start,
                    $arguments[0]->end ?: ($arguments[0]->recurrences - 1),
                    $arguments[0]->interval,
                    $arguments[0]->include_start_date ? 0 : static::EXCLUDE_START_DATE,
                ];
            }
        }

        if (is_a($this->dateClass, DateTimeImmutable::class, true)) {
            $this->options = static::IMMUTABLE;
        }

        $optionsSet = false;
        $originalArguments = [];
        $sortedArguments = [];

        foreach ($arguments as $argument) {
            $parsedDate = null;

            if ($argument instanceof DateTimeZone) {
                $sortedArguments = $this->configureTimezone($argument, $sortedArguments, $originalArguments);
            } elseif (!isset($sortedArguments['interval']) &&
                (
                    (\is_string($argument) && preg_match(
                        '/^(-?\d(\d(?![\/-])|[^\d\/-]([\/-])?)*|P[T\d].*|(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+)$/i',
                        $argument,
                    )) ||
                    $argument instanceof DateInterval ||
                    $argument instanceof Closure ||
                    $argument instanceof Unit
                ) &&
                $parsedInterval = self::makeInterval($argument)
            ) {
                $sortedArguments['interval'] = $parsedInterval;
            } elseif (!isset($sortedArguments['start']) && $parsedDate = $this->makeDateTime($argument)) {
                $sortedArguments['start'] = $parsedDate;
                $originalArguments['start'] = $argument;
            } elseif (!isset($sortedArguments['end']) && ($parsedDate = $parsedDate ?? $this->makeDateTime($argument))) {
                $sortedArguments['end'] = $parsedDate;
                $originalArguments['end'] = $argument;
            } elseif (!isset($sortedArguments['recurrences']) &&
                !isset($sortedArguments['end']) &&
                (\is_int($argument) || \is_float($argument))
                && $argument >= 0
            ) {
                $sortedArguments['recurrences'] = $argument;
            } elseif (!$optionsSet && (\is_int($argument) || $argument === null)) {
                $optionsSet = true;
                $sortedArguments['options'] = (((int) $this->options) | ((int) $argument));
            } elseif ($parsedTimezone = self::makeTimezone($argument)) {
                $sortedArguments = $this->configureTimezone($parsedTimezone, $sortedArguments, $originalArguments);
            } else {
                throw new InvalidPeriodParameterException('Invalid constructor parameters.');
            }
        }

        if ($raw === null && isset($sortedArguments['start'])) {
            $end = $sortedArguments['end'] ?? max(1, $sortedArguments['recurrences'] ?? 1);

            if (\is_float($end)) {
                $end = $end === INF ? PHP_INT_MAX : (int) round($end);
            }

            $raw = [
                $sortedArguments['start'],
                $sortedArguments['interval'] ?? CarbonInterval::day(),
                $end,
            ];
        }

        $this->setFromAssociativeArray($sortedArguments);

        if ($this->startDate === null) {
            $dateClass = $this->dateClass;
            $this->setStartDate($dateClass::now());
        }

        if ($this->dateInterval === null) {
            $this->setDateInterval(CarbonInterval::day());

            $this->isDefaultInterval = true;
        }

        if ($this->options === null) {
            $this->setOptions(0);
        }

        parent::__construct(
            $this->startDate,
            $this->dateInterval,
            $this->endDate ?? max(1, min(2147483639, $this->recurrences ?? 1)),
            $this->options,
        );

        $this->constructed = true;
    }

    /**
     * Get a copy of the instance.
     */
    public function copy(): static
    {
        return clone $this;
    }

    /**
     * Prepare the instance to be set (self if mutable to be mutated,
     * copy if immutable to generate a new instance).
     */
    protected function copyIfImmutable(): static
    {
        return $this;
    }

    /**
     * Get the getter for a property allowing both `DatePeriod` snakeCase and camelCase names.
     */
    protected function getGetter(string $name): ?callable
    {
        return match (strtolower(preg_replace('/[A-Z]/', '_$0', $name))) {
            'start', 'start_date' => [$this, 'getStartDate'],
            'end', 'end_date' => [$this, 'getEndDate'],
            'interval', 'date_interval' => [$this, 'getDateInterval'],
            'recurrences' => [$this, 'getRecurrences'],
            'include_start_date' => [$this, 'isStartIncluded'],
            'include_end_date' => [$this, 'isEndIncluded'],
            'current' => [$this, 'current'],
            'locale' => [$this, 'locale'],
            'tzname', 'tz_name' => fn () => match (true) {
                $this->timezoneSetting === null => null,
                \is_string($this->timezoneSetting) => $this->timezoneSetting,
                $this->timezoneSetting instanceof DateTimeZone => $this->timezoneSetting->getName(),
                default => CarbonTimeZone::instance($this->timezoneSetting)->getName(),
            },
            default => null,
        };
    }

    /**
     * Get a property allowing both `DatePeriod` snakeCase and camelCase names.
     *
     * @param string $name
     *
     * @return bool|CarbonInterface|CarbonInterval|int|null
     */
    public function get(string $name)
    {
        $getter = $this->getGetter($name);

        if ($getter) {
            return $getter();
        }

        throw new UnknownGetterException($name);
    }

    /**
     * Get a property allowing both `DatePeriod` snakeCase and camelCase names.
     *
     * @param string $name
     *
     * @return bool|CarbonInterface|CarbonInterval|int|null
     */
    public function __get(string $name)
    {
        return $this->get($name);
    }

    /**
     * Check if an attribute exists on the object
     *
     * @param string $name
     *
     * @return bool
     */
    public function __isset(string $name): bool
    {
        return $this->getGetter($name) !== null;
    }

    /**
     * @alias copy
     *
     * Get a copy of the instance.
     *
     * @return static
     */
    public function clone()
    {
        return clone $this;
    }

    /**
     * Set the iteration item class.
     *
     * @param string $dateClass
     *
     * @return static
     */
    public function setDateClass(string $dateClass)
    {
        if (!is_a($dateClass, CarbonInterface::class, true)) {
            throw new NotACarbonClassException($dateClass);
        }

        $self = $this->copyIfImmutable();
        $self->dateClass = $dateClass;

        if (is_a($dateClass, Carbon::class, true)) {
            $self->options = $self->options & ~static::IMMUTABLE;
        } elseif (is_a($dateClass, CarbonImmutable::class, true)) {
            $self->options = $self->options | static::IMMUTABLE;
        }

        return $self;
    }

    /**
     * Returns iteration item date class.
     *
     * @return string
     */
    public function getDateClass(): string
    {
        return $this->dateClass;
    }

    /**
     * Change the period date interval.
     *
     * @param DateInterval|Unit|string|int $interval
     * @param Unit|string                  $unit     the unit of $interval if it's a number
     *
     * @throws InvalidIntervalException
     *
     * @return static
     */
    public function setDateInterval(mixed $interval, Unit|string|null $unit = null): static
    {
        if ($interval instanceof Unit) {
            $interval = $interval->interval();
        }

        if ($unit instanceof Unit) {
            $unit = $unit->name;
        }

        if (!$interval = CarbonInterval::make($interval, $unit)) {
            throw new InvalidIntervalException('Invalid interval.');
        }

        if ($interval->spec() === 'PT0S' && !$interval->f && !$interval->getStep()) {
            throw new InvalidIntervalException('Empty interval is not accepted.');
        }

        $self = $this->copyIfImmutable();
        $self->dateInterval = $interval;

        $self->isDefaultInterval = false;

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Reset the date interval to the default value.
     *
     * Difference with simply setting interval to 1-day is that P1D will not appear when calling toIso8601String()
     * and also next adding to the interval won't include the default 1-day.
     */
    public function resetDateInterval(): static
    {
        $self = $this->copyIfImmutable();
        $self->setDateInterval(CarbonInterval::day());

        $self->isDefaultInterval = true;

        return $self;
    }

    /**
     * Invert the period date interval.
     */
    public function invertDateInterval(): static
    {
        return $this->setDateInterval($this->dateInterval->invert());
    }

    /**
     * Set start and end date.
     *
     * @param DateTime|DateTimeInterface|string      $start
     * @param DateTime|DateTimeInterface|string|null $end
     *
     * @return static
     */
    public function setDates(mixed $start, mixed $end): static
    {
        return $this->setStartDate($start)->setEndDate($end);
    }

    /**
     * Change the period options.
     *
     * @param int|null $options
     *
     * @return static
     */
    public function setOptions(?int $options): static
    {
        $self = $this->copyIfImmutable();
        $self->options = $options ?? 0;

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Get the period options.
     */
    public function getOptions(): int
    {
        return $this->options ?? 0;
    }

    /**
     * Toggle given options on or off.
     *
     * @param int       $options
     * @param bool|null $state
     *
     * @throws InvalidArgumentException
     *
     * @return static
     */
    public function toggleOptions(int $options, ?bool $state = null): static
    {
        $self = $this->copyIfImmutable();

        if ($state === null) {
            $state = ($this->options & $options) !== $options;
        }

        return $self->setOptions(
            $state ?
            $this->options | $options :
            $this->options & ~$options,
        );
    }

    /**
     * Toggle EXCLUDE_START_DATE option.
     */
    public function excludeStartDate(bool $state = true): static
    {
        return $this->toggleOptions(static::EXCLUDE_START_DATE, $state);
    }

    /**
     * Toggle EXCLUDE_END_DATE option.
     */
    public function excludeEndDate(bool $state = true): static
    {
        return $this->toggleOptions(static::EXCLUDE_END_DATE, $state);
    }

    /**
     * Get the underlying date interval.
     */
    public function getDateInterval(): CarbonInterval
    {
        return $this->dateInterval->copy();
    }

    /**
     * Get start date of the period.
     *
     * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval.
     */
    public function getStartDate(?string $rounding = null): CarbonInterface
    {
        $date = $this->startDate->avoidMutation();

        return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
    }

    /**
     * Get end date of the period.
     *
     * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval.
     */
    public function getEndDate(?string $rounding = null): ?CarbonInterface
    {
        if (!$this->endDate) {
            return null;
        }

        $date = $this->endDate->avoidMutation();

        return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
    }

    /**
     * Get number of recurrences.
     */
    #[ReturnTypeWillChange]
    public function getRecurrences(): int|float|null
    {
        return $this->carbonRecurrences;
    }

    /**
     * Returns true if the start date should be excluded.
     */
    public function isStartExcluded(): bool
    {
        return ($this->options & static::EXCLUDE_START_DATE) !== 0;
    }

    /**
     * Returns true if the end date should be excluded.
     */
    public function isEndExcluded(): bool
    {
        return ($this->options & static::EXCLUDE_END_DATE) !== 0;
    }

    /**
     * Returns true if the start date should be included.
     */
    public function isStartIncluded(): bool
    {
        return !$this->isStartExcluded();
    }

    /**
     * Returns true if the end date should be included.
     */
    public function isEndIncluded(): bool
    {
        return !$this->isEndExcluded();
    }

    /**
     * Return the start if it's included by option, else return the start + 1 period interval.
     */
    public function getIncludedStartDate(): CarbonInterface
    {
        $start = $this->getStartDate();

        if ($this->isStartExcluded()) {
            return $start->add($this->getDateInterval());
        }

        return $start;
    }

    /**
     * Return the end if it's included by option, else return the end - 1 period interval.
     * Warning: if the period has no fixed end, this method will iterate the period to calculate it.
     */
    public function getIncludedEndDate(): CarbonInterface
    {
        $end = $this->getEndDate();

        if (!$end) {
            return $this->calculateEnd();
        }

        if ($this->isEndExcluded()) {
            return $end->sub($this->getDateInterval());
        }

        return $end;
    }

    /**
     * Add a filter to the stack.
     *
     * @SuppressWarnings(UnusedFormalParameter)
     */
    public function addFilter(callable|string $callback, ?string $name = null): static
    {
        $self = $this->copyIfImmutable();
        $tuple = $self->createFilterTuple(\func_get_args());

        $self->filters[] = $tuple;

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Prepend a filter to the stack.
     *
     * @SuppressWarnings(UnusedFormalParameter)
     */
    public function prependFilter(callable|string $callback, ?string $name = null): static
    {
        $self = $this->copyIfImmutable();
        $tuple = $self->createFilterTuple(\func_get_args());

        array_unshift($self->filters, $tuple);

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Remove a filter by instance or name.
     */
    public function removeFilter(callable|string $filter): static
    {
        $self = $this->copyIfImmutable();
        $key = \is_callable($filter) ? 0 : 1;

        $self->filters = array_values(array_filter(
            $this->filters,
            static fn ($tuple) => $tuple[$key] !== $filter,
        ));

        $self->updateInternalState();

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Return whether given instance or name is in the filter stack.
     */
    public function hasFilter(callable|string $filter): bool
    {
        $key = \is_callable($filter) ? 0 : 1;

        foreach ($this->filters as $tuple) {
            if ($tuple[$key] === $filter) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get filters stack.
     */
    public function getFilters(): array
    {
        return $this->filters;
    }

    /**
     * Set filters stack.
     */
    public function setFilters(array $filters): static
    {
        $self = $this->copyIfImmutable();
        $self->filters = $filters;

        $self->updateInternalState();

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Reset filters stack.
     */
    public function resetFilters(): static
    {
        $self = $this->copyIfImmutable();
        $self->filters = [];

        if ($self->endDate !== null) {
            $self->filters[] = [static::END_DATE_FILTER, null];
        }

        if ($self->carbonRecurrences !== null) {
            $self->filters[] = [static::RECURRENCES_FILTER, null];
        }

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Add a recurrences filter (set maximum number of recurrences).
     *
     * @throws InvalidArgumentException
     */
    public function setRecurrences(int|float|null $recurrences): static
    {
        if ($recurrences === null) {
            return $this->removeFilter(static::RECURRENCES_FILTER);
        }

        if ($recurrences < 0) {
            throw new InvalidPeriodParameterException('Invalid number of recurrences.');
        }

        /** @var self $self */
        $self = $this->copyIfImmutable();
        $self->carbonRecurrences = $recurrences === INF ? INF : (int) $recurrences;

        if (!$self->hasFilter(static::RECURRENCES_FILTER)) {
            return $self->addFilter(static::RECURRENCES_FILTER);
        }

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Change the period start date.
     *
     * @param DateTime|DateTimeInterface|string $date
     * @param bool|null                         $inclusive
     *
     * @throws InvalidPeriodDateException
     *
     * @return static
     */
    public function setStartDate(mixed $date, ?bool $inclusive = null): static
    {
        if (!$this->isInfiniteDate($date) && !($date = ([$this->dateClass, 'make'])($date, $this->timezone))) {
            throw new InvalidPeriodDateException('Invalid start date.');
        }

        $self = $this->copyIfImmutable();
        $self->startDate = $date;

        if ($inclusive !== null) {
            $self = $self->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive);
        }

        return $self;
    }

    /**
     * Change the period end date.
     *
     * @param DateTime|DateTimeInterface|string|null $date
     * @param bool|null                              $inclusive
     *
     * @throws \InvalidArgumentException
     *
     * @return static
     */
    public function setEndDate(mixed $date, ?bool $inclusive = null): static
    {
        if ($date !== null && !$this->isInfiniteDate($date) && !$date = ([$this->dateClass, 'make'])($date, $this->timezone)) {
            throw new InvalidPeriodDateException('Invalid end date.');
        }

        if (!$date) {
            return $this->removeFilter(static::END_DATE_FILTER);
        }

        $self = $this->copyIfImmutable();
        $self->endDate = $date;

        if ($inclusive !== null) {
            $self = $self->toggleOptions(static::EXCLUDE_END_DATE, !$inclusive);
        }

        if (!$self->hasFilter(static::END_DATE_FILTER)) {
            return $self->addFilter(static::END_DATE_FILTER);
        }

        $self->handleChangedParameters();

        return $self;
    }

    /**
     * Check if the current position is valid.
     */
    public function valid(): bool
    {
        return $this->validateCurrentDate() === true;
    }

    /**
     * Return the current key.
     */
    public function key(): ?int
    {
        return $this->valid()
            ? $this->key
            : null;
    }

    /**
     * Return the current date.
     */
    public function current(): ?CarbonInterface
    {
        return $this->valid()
            ? $this->prepareForReturn($this->carbonCurrent)
            : null;
    }

    /**
     * Move forward to the next date.
     *
     * @throws RuntimeException
     */
    public function next(): void
    {
        if ($this->carbonCurrent === null) {
            $this->rewind();
        }

        if ($this->validationResult !== static::END_ITERATION) {
            $this->key++;

            $this->incrementCurrentDateUntilValid();
        }
    }

    /**
     * Rewind to the start date.
     *
     * Iterating over a date in the UTC timezone avoids bug during backward DST change.
     *
     * @see https://bugs.php.net/bug.php?id=72255
     * @see https://bugs.php.net/bug.php?id=74274
     * @see https://wiki.php.net/rfc/datetime_and_daylight_saving_time
     *
     * @throws RuntimeException
     */
    public function rewind(): void
    {
        $this->key = 0;
        $this->carbonCurrent = ([$this->dateClass, 'make'])($this->startDate);
        $settings = $this->getSettings();

        if ($this->hasLocalTranslator()) {
            $settings['locale'] = $this->getTranslatorLocale();
        }

        $this->carbonCurrent->settings($settings);
        $this->timezone = static::intervalHasTime($this->dateInterval) ? $this->carbonCurrent->getTimezone() : null;

        if ($this->timezone) {
            $this->carbonCurrent = $this->carbonCurrent->utc();
        }

        $this->validationResult = null;

        if ($this->isStartExcluded() || $this->validateCurrentDate() === false) {
            $this->incrementCurrentDateUntilValid();
        }
    }

    /**
     * Skip iterations and returns iteration state (false if ended, true if still valid).
     *
     * @param int $count steps number to skip (1 by default)
     *
     * @return bool
     */
    public function skip(int $count = 1): bool
    {
        for ($i = $count; $this->valid() && $i > 0; $i--) {
            $this->next();
        }

        return $this->valid();
    }

    /**
     * Format the date period as ISO 8601.
     */
    public function toIso8601String(): string
    {
        $parts = [];

        if ($this->carbonRecurrences !== null) {
            $parts[] = 'R'.$this->carbonRecurrences;
        }

        $parts[] = $this->startDate->toIso8601String();

        if (!$this->isDefaultInterval) {
            $parts[] = $this->dateInterval->spec();
        }

        if ($this->endDate !== null) {
            $parts[] = $this->endDate->toIso8601String();
        }

        return implode('/', $parts);
    }

    /**
     * Convert the date period into a string.
     */
    public function toString(): string
    {
        $format = $this->localToStringFormat
            ?? $this->getFactory()->getSettings()['toStringFormat']
            ?? null;

        if ($format instanceof Closure) {
            return $format($this);
        }

        $translator = ([$this->dateClass, 'getTranslator'])();

        $parts = [];

        $format = $format ?? (
            !$this->startDate->isStartOfDay() || ($this->endDate && !$this->endDate->isStartOfDay())
                ? 'Y-m-d H:i:s'
                : 'Y-m-d'
        );

        if ($this->carbonRecurrences !== null) {
            $parts[] = $this->translate('period_recurrences', [], $this->carbonRecurrences, $translator);
        }

        $parts[] = $this->translate('period_interval', [':interval' => $this->dateInterval->forHumans([
            'join' => true,
        ])], null, $translator);

        $parts[] = $this->translate('period_start_date', [':date' => $this->startDate->rawFormat($format)], null, $translator);

        if ($this->endDate !== null) {
            $parts[] = $this->translate('period_end_date', [':date' => $this->endDate->rawFormat($format)], null, $translator);
        }

        $result = implode(' ', $parts);

        return mb_strtoupper(mb_substr($result, 0, 1)).mb_substr($result, 1);
    }

    /**
     * Format the date period as ISO 8601.
     */
    public function spec(): string
    {
        return $this->toIso8601String();
    }

    /**
     * Cast the current instance into the given class.
     *
     * @param string $className The $className::instance() method will be called to cast the current object.
     *
     * @return DatePeriod|object
     */
    public function cast(string $className): object
    {
        if (!method_exists($className, 'instance')) {
            if (is_a($className, DatePeriod::class, true)) {
                return new $className(
                    $this->rawDate($this->getStartDate()),
                    $this->getDateInterval(),
                    $this->getEndDate() ? $this->rawDate($this->getIncludedEndDate()) : $this->getRecurrences(),
                    $this->isStartExcluded() ? DatePeriod::EXCLUDE_START_DATE : 0,
                );
            }

            throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
        }

        return $className::instance($this);
    }

    /**
     * Return native DatePeriod PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(CarbonPeriod::create('2021-01-05', '2021-02-15')->toDatePeriod());
     * ```
     */
    public function toDatePeriod(): DatePeriod
    {
        return $this->cast(DatePeriod::class);
    }

    /**
     * Return `true` if the period has no custom filter and is guaranteed to be endless.
     *
     * Note that we can't check if a period is endless as soon as it has custom filters
     * because filters can emit `CarbonPeriod::END_ITERATION` to stop the iteration in
     * a way we can't predict without actually iterating the period.
     */
    public function isUnfilteredAndEndLess(): bool
    {
        foreach ($this->filters as $filter) {
            switch ($filter) {
                case [static::RECURRENCES_FILTER, null]:
                    if ($this->carbonRecurrences !== null && is_finite($this->carbonRecurrences)) {
                        return false;
                    }

                    break;

                case [static::END_DATE_FILTER, null]:
                    if ($this->endDate !== null && !$this->endDate->isEndOfTime()) {
                        return false;
                    }

                    break;

                default:
                    return false;
            }
        }

        return true;
    }

    /**
     * Convert the date period into an array without changing current iteration state.
     *
     * @return CarbonInterface[]
     */
    public function toArray(): array
    {
        if ($this->isUnfilteredAndEndLess()) {
            throw new EndLessPeriodException("Endless period can't be converted to array nor counted.");
        }

        $state = [
            $this->key,
            $this->carbonCurrent ? $this->carbonCurrent->avoidMutation() : null,
            $this->validationResult,
        ];

        $result = iterator_to_array($this);

        [$this->key, $this->carbonCurrent, $this->validationResult] = $state;

        return $result;
    }

    /**
     * Count dates in the date period.
     */
    public function count(): int
    {
        return \count($this->toArray());
    }

    /**
     * Return the first date in the date period.
     */
    public function first(): ?CarbonInterface
    {
        if ($this->isUnfilteredAndEndLess()) {
            foreach ($this as $date) {
                $this->rewind();

                return $date;
            }

            return null;
        }

        return ($this->toArray() ?: [])[0] ?? null;
    }

    /**
     * Return the last date in the date period.
     */
    public function last(): ?CarbonInterface
    {
        $array = $this->toArray();

        return $array ? $array[\count($array) - 1] : null;
    }

    /**
     * Convert the date period into a string.
     */
    public function __toString(): string
    {
        return $this->toString();
    }

    /**
     * Add aliases for setters.
     *
     * CarbonPeriod::days(3)->hours(5)->invert()
     *     ->sinceNow()->until('2010-01-10')
     *     ->filter(...)
     *     ->count()
     *
     * Note: We use magic method to let static and instance aliases with the same names.
     */
    public function __call(string $method, array $parameters): mixed
    {
        if (static::hasMacro($method)) {
            return static::bindMacroContext($this, fn () => $this->callMacro($method, $parameters));
        }

        $roundedValue = $this->callRoundMethod($method, $parameters);

        if ($roundedValue !== null) {
            return $roundedValue;
        }

        $count = \count($parameters);

        switch ($method) {
            case 'start':
            case 'since':
                if ($count === 0) {
                    return $this->getStartDate();
                }

                self::setDefaultParameters($parameters, [
                    [0, 'date', null],
                ]);

                return $this->setStartDate(...$parameters);

            case 'sinceNow':
                return $this->setStartDate(new Carbon(), ...$parameters);

            case 'end':
            case 'until':
                if ($count === 0) {
                    return $this->getEndDate();
                }

                self::setDefaultParameters($parameters, [
                    [0, 'date', null],
                ]);

                return $this->setEndDate(...$parameters);

            case 'untilNow':
                return $this->setEndDate(new Carbon(), ...$parameters);

            case 'dates':
            case 'between':
                self::setDefaultParameters($parameters, [
                    [0, 'start', null],
                    [1, 'end', null],
                ]);

                return $this->setDates(...$parameters);

            case 'recurrences':
            case 'times':
                if ($count === 0) {
                    return $this->getRecurrences();
                }

                self::setDefaultParameters($parameters, [
                    [0, 'recurrences', null],
                ]);

                return $this->setRecurrences(...$parameters);

            case 'options':
                if ($count === 0) {
                    return $this->getOptions();
                }

                self::setDefaultParameters($parameters, [
                    [0, 'options', null],
                ]);

                return $this->setOptions(...$parameters);

            case 'toggle':
                self::setDefaultParameters($parameters, [
                    [0, 'options', null],
                ]);

                return $this->toggleOptions(...$parameters);

            case 'filter':
            case 'push':
                return $this->addFilter(...$parameters);

            case 'prepend':
                return $this->prependFilter(...$parameters);

            case 'filters':
                if ($count === 0) {
                    return $this->getFilters();
                }

                self::setDefaultParameters($parameters, [
                    [0, 'filters', []],
                ]);

                return $this->setFilters(...$parameters);

            case 'interval':
            case 'each':
            case 'every':
            case 'step':
            case 'stepBy':
                if ($count === 0) {
                    return $this->getDateInterval();
                }

                return $this->setDateInterval(...$parameters);

            case 'invert':
                return $this->invertDateInterval();

            case 'years':
            case 'year':
            case 'months':
            case 'month':
            case 'weeks':
            case 'week':
            case 'days':
            case 'dayz':
            case 'day':
            case 'hours':
            case 'hour':
            case 'minutes':
            case 'minute':
            case 'seconds':
            case 'second':
            case 'milliseconds':
            case 'millisecond':
            case 'microseconds':
            case 'microsecond':
                return $this->setDateInterval((
                    // Override default P1D when instantiating via fluent setters.
                    [$this->isDefaultInterval ? new CarbonInterval('PT0S') : $this->dateInterval, $method]
                )(...$parameters));
        }

        $dateClass = $this->dateClass;

        if ($this->localStrictModeEnabled ?? $dateClass::isStrictModeEnabled()) {
            throw new UnknownMethodException($method);
        }

        return $this;
    }

    /**
     * Set the instance's timezone from a string or object and apply it to start/end.
     */
    public function setTimezone(DateTimeZone|string|int $timezone): static
    {
        $self = $this->copyIfImmutable();
        $self->timezoneSetting = $timezone;
        $self->timezone = CarbonTimeZone::instance($timezone);

        if ($self->startDate) {
            $self = $self->setStartDate($self->startDate->setTimezone($timezone));
        }

        if ($self->endDate) {
            $self = $self->setEndDate($self->endDate->setTimezone($timezone));
        }

        return $self;
    }

    /**
     * Set the instance's timezone from a string or object and add/subtract the offset difference to start/end.
     */
    public function shiftTimezone(DateTimeZone|string|int $timezone): static
    {
        $self = $this->copyIfImmutable();
        $self->timezoneSetting = $timezone;
        $self->timezone = CarbonTimeZone::instance($timezone);

        if ($self->startDate) {
            $self = $self->setStartDate($self->startDate->shiftTimezone($timezone));
        }

        if ($self->endDate) {
            $self = $self->setEndDate($self->endDate->shiftTimezone($timezone));
        }

        return $self;
    }

    /**
     * Returns the end is set, else calculated from start and recurrences.
     *
     * @param string|null $rounding Optional rounding 'floor', 'ceil', 'round' using the period interval.
     *
     * @return CarbonInterface
     */
    public function calculateEnd(?string $rounding = null): CarbonInterface
    {
        if ($end = $this->getEndDate($rounding)) {
            return $end;
        }

        if ($this->dateInterval->isEmpty()) {
            return $this->getStartDate($rounding);
        }

        $date = $this->getEndFromRecurrences() ?? $this->iterateUntilEnd();

        if ($date && $rounding) {
            $date = $date->avoidMutation()->round($this->getDateInterval(), $rounding);
        }

        return $date;
    }

    private function getEndFromRecurrences(): ?CarbonInterface
    {
        if ($this->carbonRecurrences === null) {
            throw new UnreachableException(
                "Could not calculate period end without either explicit end or recurrences.\n".
                "If you're looking for a forever-period, use ->setRecurrences(INF).",
            );
        }

        if ($this->carbonRecurrences === INF) {
            $start = $this->getStartDate();

            return $start < $start->avoidMutation()->add($this->getDateInterval())
                ? CarbonImmutable::endOfTime()
                : CarbonImmutable::startOfTime();
        }

        if ($this->filters === [[static::RECURRENCES_FILTER, null]]) {
            return $this->getStartDate()->avoidMutation()->add(
                $this->getDateInterval()->times(
                    $this->carbonRecurrences - ($this->isStartExcluded() ? 0 : 1),
                ),
            );
        }

        return null;
    }

    private function iterateUntilEnd(): ?CarbonInterface
    {
        $attempts = 0;
        $date = null;

        foreach ($this as $date) {
            if (++$attempts > static::END_MAX_ATTEMPTS) {
                throw new UnreachableException(
                    'Could not calculate period end after iterating '.static::END_MAX_ATTEMPTS.' times.',
                );
            }
        }

        return $date;
    }

    /**
     * Returns true if the current period overlaps the given one (if 1 parameter passed)
     * or the period between 2 dates (if 2 parameters passed).
     *
     * @param CarbonPeriod|\DateTimeInterface|Carbon|CarbonImmutable|string $rangeOrRangeStart
     * @param \DateTimeInterface|Carbon|CarbonImmutable|string|null         $rangeEnd
     *
     * @return bool
     */
    public function overlaps(mixed $rangeOrRangeStart, mixed $rangeEnd = null): bool
    {
        $range = $rangeEnd ? static::create($rangeOrRangeStart, $rangeEnd) : $rangeOrRangeStart;

        if (!($range instanceof self)) {
            $range = static::create($range);
        }

        [$start, $end] = $this->orderCouple($this->getStartDate(), $this->calculateEnd());
        [$rangeStart, $rangeEnd] = $this->orderCouple($range->getStartDate(), $range->calculateEnd());

        return $end > $rangeStart && $rangeEnd > $start;
    }

    /**
     * Execute a given function on each date of the period.
     *
     * @example
     * ```
     * Carbon::create('2020-11-29')->daysUntil('2020-12-24')->forEach(function (Carbon $date) {
     *   echo $date->diffInDays('2020-12-25')." days before Christmas!\n";
     * });
     * ```
     */
    public function forEach(callable $callback): void
    {
        foreach ($this as $date) {
            $callback($date);
        }
    }

    /**
     * Execute a given function on each date of the period and yield the result of this function.
     *
     * @example
     * ```
     * $period = Carbon::create('2020-11-29')->daysUntil('2020-12-24');
     * echo implode("\n", iterator_to_array($period->map(function (Carbon $date) {
     *   return $date->diffInDays('2020-12-25').' days before Christmas!';
     * })));
     * ```
     */
    public function map(callable $callback): Generator
    {
        foreach ($this as $date) {
            yield $callback($date);
        }
    }

    /**
     * Determines if the instance is equal to another.
     * Warning: if options differ, instances will never be equal.
     *
     * @see equalTo()
     */
    public function eq(mixed $period): bool
    {
        return $this->equalTo($period);
    }

    /**
     * Determines if the instance is equal to another.
     * Warning: if options differ, instances will never be equal.
     */
    public function equalTo(mixed $period): bool
    {
        if (!($period instanceof self)) {
            $period = self::make($period);
        }

        $end = $this->getEndDate();

        return $period !== null
            && $this->getDateInterval()->eq($period->getDateInterval())
            && $this->getStartDate()->eq($period->getStartDate())
            && ($end ? $end->eq($period->getEndDate()) : $this->getRecurrences() === $period->getRecurrences())
            && ($this->getOptions() & (~static::IMMUTABLE)) === ($period->getOptions() & (~static::IMMUTABLE));
    }

    /**
     * Determines if the instance is not equal to another.
     * Warning: if options differ, instances will never be equal.
     *
     * @see notEqualTo()
     */
    public function ne(mixed $period): bool
    {
        return $this->notEqualTo($period);
    }

    /**
     * Determines if the instance is not equal to another.
     * Warning: if options differ, instances will never be equal.
     */
    public function notEqualTo(mixed $period): bool
    {
        return !$this->eq($period);
    }

    /**
     * Determines if the start date is before another given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function startsBefore(mixed $date = null): bool
    {
        return $this->getStartDate()->lessThan($this->resolveCarbon($date));
    }

    /**
     * Determines if the start date is before or the same as a given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function startsBeforeOrAt(mixed $date = null): bool
    {
        return $this->getStartDate()->lessThanOrEqualTo($this->resolveCarbon($date));
    }

    /**
     * Determines if the start date is after another given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function startsAfter(mixed $date = null): bool
    {
        return $this->getStartDate()->greaterThan($this->resolveCarbon($date));
    }

    /**
     * Determines if the start date is after or the same as a given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function startsAfterOrAt(mixed $date = null): bool
    {
        return $this->getStartDate()->greaterThanOrEqualTo($this->resolveCarbon($date));
    }

    /**
     * Determines if the start date is the same as a given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function startsAt(mixed $date = null): bool
    {
        return $this->getStartDate()->equalTo($this->resolveCarbon($date));
    }

    /**
     * Determines if the end date is before another given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function endsBefore(mixed $date = null): bool
    {
        return $this->calculateEnd()->lessThan($this->resolveCarbon($date));
    }

    /**
     * Determines if the end date is before or the same as a given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function endsBeforeOrAt(mixed $date = null): bool
    {
        return $this->calculateEnd()->lessThanOrEqualTo($this->resolveCarbon($date));
    }

    /**
     * Determines if the end date is after another given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function endsAfter(mixed $date = null): bool
    {
        return $this->calculateEnd()->greaterThan($this->resolveCarbon($date));
    }

    /**
     * Determines if the end date is after or the same as a given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function endsAfterOrAt(mixed $date = null): bool
    {
        return $this->calculateEnd()->greaterThanOrEqualTo($this->resolveCarbon($date));
    }

    /**
     * Determines if the end date is the same as a given date.
     * (Rather start/end are included by options is ignored.)
     */
    public function endsAt(mixed $date = null): bool
    {
        return $this->calculateEnd()->equalTo($this->resolveCarbon($date));
    }

    /**
     * Return true if start date is now or later.
     * (Rather start/end are included by options is ignored.)
     */
    public function isStarted(): bool
    {
        return $this->startsBeforeOrAt();
    }

    /**
     * Return true if end date is now or later.
     * (Rather start/end are included by options is ignored.)
     */
    public function isEnded(): bool
    {
        return $this->endsBeforeOrAt();
    }

    /**
     * Return true if now is between start date (included) and end date (excluded).
     * (Rather start/end are included by options is ignored.)
     */
    public function isInProgress(): bool
    {
        return $this->isStarted() && !$this->isEnded();
    }

    /**
     * Round the current instance at the given unit with given precision if specified and the given function.
     */
    public function roundUnit(
        string $unit,
        DateInterval|float|int|string|null $precision = 1,
        callable|string $function = 'round',
    ): static {
        $self = $this->copyIfImmutable();
        $self = $self->setStartDate($self->getStartDate()->roundUnit($unit, $precision, $function));

        if ($self->endDate) {
            $self = $self->setEndDate($self->getEndDate()->roundUnit($unit, $precision, $function));
        }

        return $self->setDateInterval($self->getDateInterval()->roundUnit($unit, $precision, $function));
    }

    /**
     * Truncate the current instance at the given unit with given precision if specified.
     */
    public function floorUnit(string $unit, DateInterval|float|int|string|null $precision = 1): static
    {
        return $this->roundUnit($unit, $precision, 'floor');
    }

    /**
     * Ceil the current instance at the given unit with given precision if specified.
     */
    public function ceilUnit(string $unit, DateInterval|float|int|string|null $precision = 1): static
    {
        return $this->roundUnit($unit, $precision, 'ceil');
    }

    /**
     * Round the current instance second with given precision if specified (else period interval is used).
     */
    public function round(
        DateInterval|float|int|string|null $precision = null,
        callable|string $function = 'round',
    ): static {
        return $this->roundWith(
            $precision ?? $this->getDateInterval()->setLocalTranslator(TranslatorImmutable::get('en'))->forHumans(),
            $function
        );
    }

    /**
     * Round the current instance second with given precision if specified (else period interval is used).
     */
    public function floor(DateInterval|float|int|string|null $precision = null): static
    {
        return $this->round($precision, 'floor');
    }

    /**
     * Ceil the current instance second with given precision if specified (else period interval is used).
     */
    public function ceil(DateInterval|float|int|string|null $precision = null): static
    {
        return $this->round($precision, 'ceil');
    }

    /**
     * Specify data which should be serialized to JSON.
     *
     * @link https://php.net/manual/en/jsonserializable.jsonserialize.php
     *
     * @return CarbonInterface[]
     */
    public function jsonSerialize(): array
    {
        return $this->toArray();
    }

    /**
     * Return true if the given date is between start and end.
     */
    public function contains(mixed $date = null): bool
    {
        $startMethod = 'startsBefore'.($this->isStartIncluded() ? 'OrAt' : '');
        $endMethod = 'endsAfter'.($this->isEndIncluded() ? 'OrAt' : '');

        return $this->$startMethod($date) && $this->$endMethod($date);
    }

    /**
     * Return true if the current period follows a given other period (with no overlap).
     * For instance, [2019-08-01 -> 2019-08-12] follows [2019-07-29 -> 2019-07-31]
     * Note than in this example, follows() would be false if 2019-08-01 or 2019-07-31 was excluded by options.
     */
    public function follows(mixed $period, mixed ...$arguments): bool
    {
        $period = $this->resolveCarbonPeriod($period, ...$arguments);

        return $this->getIncludedStartDate()->equalTo($period->getIncludedEndDate()->add($period->getDateInterval()));
    }

    /**
     * Return true if the given other period follows the current one (with no overlap).
     * For instance, [2019-07-29 -> 2019-07-31] is followed by [2019-08-01 -> 2019-08-12]
     * Note than in this example, isFollowedBy() would be false if 2019-08-01 or 2019-07-31 was excluded by options.
     */
    public function isFollowedBy(mixed $period, mixed ...$arguments): bool
    {
        $period = $this->resolveCarbonPeriod($period, ...$arguments);

        return $period->follows($this);
    }

    /**
     * Return true if the given period either follows or is followed by the current one.
     *
     * @see follows()
     * @see isFollowedBy()
     */
    public function isConsecutiveWith(mixed $period, mixed ...$arguments): bool
    {
        return $this->follows($period, ...$arguments) || $this->isFollowedBy($period, ...$arguments);
    }

    public function __debugInfo(): array
    {
        $info = $this->baseDebugInfo();
        unset(
            $info['start'],
            $info['end'],
            $info['interval'],
            $info['include_start_date'],
            $info['include_end_date'],
            $info['constructed'],
            $info["\0*\0constructed"],
        );

        return $info;
    }

    public function __unserialize(array $data): void
    {
        try {
            $values = array_combine(
                array_map(
                    static fn (string $key): string => preg_replace('/^\0\*\0/', '', $key),
                    array_keys($data),
                ),
                $data,
            );

            $this->initializeSerialization($values);

            foreach ($values as $key => $value) {
                if ($value === null) {
                    continue;
                }

                $property = match ($key) {
                    'tzName' => $this->setTimezone(...),
                    'options' => $this->setOptions(...),
                    'recurrences' => $this->setRecurrences(...),
                    'current' => function (mixed $current): void {
                        if (!($current instanceof CarbonInterface)) {
                            $current = $this->resolveCarbon($current);
                        }

                        $this->carbonCurrent = $current;
                    },
                    'start' => 'startDate',
                    'interval' => $this->setDateInterval(...),
                    'end' => 'endDate',
                    'key' => null,
                    'include_start_date' => function (bool $included): void {
                        $this->excludeStartDate(!$included);
                    },
                    'include_end_date' => function (bool $included): void {
                        $this->excludeEndDate(!$included);
                    },
                    default => $key,
                };

                if ($property === null) {
                    continue;
                }

                if (\is_callable($property)) {
                    $property($value);

                    continue;
                }

                if ($value instanceof DateTimeInterface && !($value instanceof CarbonInterface)) {
                    $value = ($value instanceof DateTime)
                        ? Carbon::instance($value)
                        : CarbonImmutable::instance($value);
                }

                try {
                    $this->$property = $value;
                } catch (Throwable) {
                    // Must be ignored for backward-compatibility
                }
            }

            if (\array_key_exists('carbonRecurrences', $values)) {
                $this->carbonRecurrences = $values['carbonRecurrences'];
            } elseif (((int) ($values['recurrences'] ?? 0)) <= 1 && $this->endDate !== null) {
                $this->carbonRecurrences = null;
            }
        } catch (Throwable $e) {
            // @codeCoverageIgnoreStart
            if (!method_exists(parent::class, '__unserialize')) {
                throw $e;
            }

            parent::__unserialize($data);
            // @codeCoverageIgnoreEnd
        }
    }

    /**
     * Update properties after removing built-in filters.
     */
    protected function updateInternalState(): void
    {
        if (!$this->hasFilter(static::END_DATE_FILTER)) {
            $this->endDate = null;
        }

        if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
            $this->carbonRecurrences = null;
        }
    }

    /**
     * Create a filter tuple from raw parameters.
     *
     * Will create an automatic filter callback for one of Carbon's is* methods.
     */
    protected function createFilterTuple(array $parameters): array
    {
        $method = array_shift($parameters);

        if (!$this->isCarbonPredicateMethod($method)) {
            return [$method, array_shift($parameters)];
        }

        return [static fn ($date) => ([$date, $method])(...$parameters), $method];
    }

    /**
     * Return whether given callable is a string pointing to one of Carbon's is* methods
     * and should be automatically converted to a filter callback.
     */
    protected function isCarbonPredicateMethod(callable|string $callable): bool
    {
        return \is_string($callable) && str_starts_with($callable, 'is') &&
            (method_exists($this->dateClass, $callable) || ([$this->dateClass, 'hasMacro'])($callable));
    }

    /**
     * Recurrences filter callback (limits number of recurrences).
     *
     * @SuppressWarnings(UnusedFormalParameter)
     */
    protected function filterRecurrences(CarbonInterface $current, int $key): bool|callable
    {
        if ($key < $this->carbonRecurrences) {
            return true;
        }

        return static::END_ITERATION;
    }

    /**
     * End date filter callback.
     *
     * @return bool|static::END_ITERATION
     */
    protected function filterEndDate(CarbonInterface $current): bool|callable
    {
        if (!$this->isEndExcluded() && $current == $this->endDate) {
            return true;
        }

        if ($this->dateInterval->invert ? $current > $this->endDate : $current < $this->endDate) {
            return true;
        }

        return static::END_ITERATION;
    }

    /**
     * End iteration filter callback.
     *
     * @return static::END_ITERATION
     */
    protected function endIteration(): callable
    {
        return static::END_ITERATION;
    }

    /**
     * Handle change of the parameters.
     */
    protected function handleChangedParameters(): void
    {
        if (($this->getOptions() & static::IMMUTABLE) && $this->dateClass === Carbon::class) {
            $this->dateClass = CarbonImmutable::class;
        } elseif (!($this->getOptions() & static::IMMUTABLE) && $this->dateClass === CarbonImmutable::class) {
            $this->dateClass = Carbon::class;
        }

        $this->validationResult = null;
    }

    /**
     * Validate current date and stop iteration when necessary.
     *
     * Returns true when current date is valid, false if it is not, or static::END_ITERATION
     * when iteration should be stopped.
     *
     * @return bool|static::END_ITERATION
     */
    protected function validateCurrentDate(): bool|callable
    {
        if ($this->carbonCurrent === null) {
            $this->rewind();
        }

        // Check after the first rewind to avoid repeating the initial validation.
        return $this->validationResult ?? ($this->validationResult = $this->checkFilters());
    }

    /**
     * Check whether current value and key pass all the filters.
     *
     * @return bool|static::END_ITERATION
     */
    protected function checkFilters(): bool|callable
    {
        $current = $this->prepareForReturn($this->carbonCurrent);

        foreach ($this->filters as $tuple) {
            $result = \call_user_func($tuple[0], $current->avoidMutation(), $this->key, $this);

            if ($result === static::END_ITERATION) {
                return static::END_ITERATION;
            }

            if (!$result) {
                return false;
            }
        }

        return true;
    }

    /**
     * Prepare given date to be returned to the external logic.
     *
     * @param CarbonInterface $date
     *
     * @return CarbonInterface
     */
    protected function prepareForReturn(CarbonInterface $date)
    {
        $date = ([$this->dateClass, 'make'])($date);

        if ($this->timezone) {
            return $date->setTimezone($this->timezone);
        }

        return $date;
    }

    /**
     * Keep incrementing the current date until a valid date is found or the iteration is ended.
     *
     * @throws RuntimeException
     */
    protected function incrementCurrentDateUntilValid(): void
    {
        $attempts = 0;

        do {
            $this->carbonCurrent = $this->carbonCurrent->add($this->dateInterval);

            $this->validationResult = null;

            if (++$attempts > static::NEXT_MAX_ATTEMPTS) {
                throw new UnreachableException('Could not find next valid date.');
            }
        } while ($this->validateCurrentDate() === false);
    }

    /**
     * Call given macro.
     */
    protected function callMacro(string $name, array $parameters): mixed
    {
        $macro = static::$macros[$name];

        if ($macro instanceof Closure) {
            $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);

            return ($boundMacro ?: $macro)(...$parameters);
        }

        return $macro(...$parameters);
    }

    /**
     * Return the Carbon instance passed through, a now instance in the same timezone
     * if null given or parse the input if string given.
     *
     * @param \Carbon\Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|\DateTimeInterface|string|null $date
     *
     * @return \Carbon\CarbonInterface
     */
    protected function resolveCarbon($date = null)
    {
        return $this->getStartDate()->nowWithSameTz()->carbonize($date);
    }

    /**
     * Resolve passed arguments or DatePeriod to a CarbonPeriod object.
     */
    protected function resolveCarbonPeriod(mixed $period, mixed ...$arguments): self
    {
        if ($period instanceof self) {
            return $period;
        }

        return $period instanceof DatePeriod
            ? static::instance($period)
            : static::create($period, ...$arguments);
    }

    private function orderCouple($first, $second): array
    {
        return $first > $second ? [$second, $first] : [$first, $second];
    }

    private function makeDateTime($value): ?DateTimeInterface
    {
        if ($value instanceof DateTimeInterface) {
            return $value;
        }

        if ($value instanceof WeekDay || $value instanceof Month) {
            $dateClass = $this->dateClass;

            return new $dateClass($value, $this->timezoneSetting);
        }

        if (\is_string($value)) {
            $value = trim($value);

            if (!preg_match('/^P[\dT]/', $value) &&
                !preg_match('/^R\d/', $value) &&
                preg_match('/[a-z\d]/i', $value)
            ) {
                $dateClass = $this->dateClass;

                return $dateClass::parse($value, $this->timezoneSetting);
            }
        }

        return null;
    }

    private function isInfiniteDate($date): bool
    {
        return $date instanceof CarbonInterface && ($date->isEndOfTime() || $date->isStartOfTime());
    }

    private function rawDate($date): ?DateTimeInterface
    {
        if ($date === false || $date === null) {
            return null;
        }

        if ($date instanceof CarbonInterface) {
            return $date->isMutable()
                ? $date->toDateTime()
                : $date->toDateTimeImmutable();
        }

        if (\in_array(\get_class($date), [DateTime::class, DateTimeImmutable::class], true)) {
            return $date;
        }

        $class = $date instanceof DateTime ? DateTime::class : DateTimeImmutable::class;

        return new $class($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
    }

    private static function setDefaultParameters(array &$parameters, array $defaults): void
    {
        foreach ($defaults as [$index, $name, $value]) {
            if (!\array_key_exists($index, $parameters) && !\array_key_exists($name, $parameters)) {
                $parameters[$index] = $value;
            }
        }
    }

    private function setFromAssociativeArray(array $parameters): void
    {
        if (isset($parameters['start'])) {
            $this->setStartDate($parameters['start']);
        }

        if (isset($parameters['start'])) {
            $this->setStartDate($parameters['start']);
        }

        if (isset($parameters['end'])) {
            $this->setEndDate($parameters['end']);
        }

        if (isset($parameters['recurrences'])) {
            $this->setRecurrences($parameters['recurrences']);
        }

        if (isset($parameters['interval'])) {
            $this->setDateInterval($parameters['interval']);
        }

        if (isset($parameters['options'])) {
            $this->setOptions($parameters['options']);
        }
    }

    private function configureTimezone(DateTimeZone $timezone, array $sortedArguments, array $originalArguments): array
    {
        $this->setTimezone($timezone);

        if (\is_string($originalArguments['start'] ?? null)) {
            $sortedArguments['start'] = $this->makeDateTime($originalArguments['start']);
        }

        if (\is_string($originalArguments['end'] ?? null)) {
            $sortedArguments['end'] = $this->makeDateTime($originalArguments['end']);
        }

        return $sortedArguments;
    }

    private function initializeSerialization(array $values): void
    {
        $serializationBase = [
            'start' => $values['start'] ?? $values['startDate'] ?? null,
            'current' => $values['current'] ?? $values['carbonCurrent'] ?? null,
            'end' => $values['end'] ?? $values['endDate'] ?? null,
            'interval' => $values['interval'] ?? $values['dateInterval'] ?? null,
            'recurrences' => max(1, (int) ($values['recurrences'] ?? $values['carbonRecurrences'] ?? 1)),
            'include_start_date' => $values['include_start_date'] ?? true,
            'include_end_date' => $values['include_end_date'] ?? false,
        ];

        foreach (['start', 'current', 'end'] as $dateProperty) {
            if ($serializationBase[$dateProperty] instanceof Carbon) {
                $serializationBase[$dateProperty] = $serializationBase[$dateProperty]->toDateTime();
            } elseif ($serializationBase[$dateProperty] instanceof CarbonInterface) {
                $serializationBase[$dateProperty] = $serializationBase[$dateProperty]->toDateTimeImmutable();
            }
        }

        if ($serializationBase['interval'] instanceof CarbonInterval) {
            $serializationBase['interval'] = $serializationBase['interval']->toDateInterval();
        }

        // @codeCoverageIgnoreStart
        if (method_exists(parent::class, '__unserialize')) {
            parent::__unserialize($serializationBase);

            return;
        }

        $excludeStart = !($values['include_start_date'] ?? true);
        $includeEnd = $values['include_end_date'] ?? true;

        parent::__construct(
            $serializationBase['start'],
            $serializationBase['interval'],
            $serializationBase['end'] ?? $serializationBase['recurrences'],
            ($excludeStart ? self::EXCLUDE_START_DATE : 0) | ($includeEnd && \defined('DatePeriod::INCLUDE_END_DATE') ? self::INCLUDE_END_DATE : 0),
        );
        // @codeCoverageIgnoreEnd
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Constants\UnitValue;
use Carbon\Exceptions\BadFluentConstructorException;
use Carbon\Exceptions\BadFluentSetterException;
use Carbon\Exceptions\InvalidCastException;
use Carbon\Exceptions\InvalidFormatException;
use Carbon\Exceptions\InvalidIntervalException;
use Carbon\Exceptions\OutOfRangeException;
use Carbon\Exceptions\ParseErrorException;
use Carbon\Exceptions\UnitNotConfiguredException;
use Carbon\Exceptions\UnknownGetterException;
use Carbon\Exceptions\UnknownSetterException;
use Carbon\Exceptions\UnknownUnitException;
use Carbon\Traits\IntervalRounding;
use Carbon\Traits\IntervalStep;
use Carbon\Traits\LocalFactory;
use Carbon\Traits\MagicParameter;
use Carbon\Traits\Mixin;
use Carbon\Traits\Options;
use Carbon\Traits\ToStringFormat;
use Closure;
use DateInterval;
use DateTime;
use DateTimeInterface;
use DateTimeZone;
use Exception;
use InvalidArgumentException;
use ReflectionException;
use ReturnTypeWillChange;
use RuntimeException;
use Symfony\Contracts\Translation\TranslatorInterface;
use Throwable;

/**
 * A simple API extension for DateInterval.
 * The implementation provides helpers to handle weeks but only days are saved.
 * Weeks are calculated based on the total days of the current instance.
 *
 * @property int $years Year component of the current interval. (For P2Y6M, the value will be 2)
 * @property int $months Month component of the current interval. (For P1Y6M10D, the value will be 6)
 * @property int $weeks Week component of the current interval calculated from the days. (For P1Y6M17D, the value will be 2)
 * @property int $dayz Day component of the current interval (weeks * 7 + days). (For P6M17DT20H, the value will be 17)
 * @property int $hours Hour component of the current interval. (For P7DT20H5M, the value will be 20)
 * @property int $minutes Minute component of the current interval. (For PT20H5M30S, the value will be 5)
 * @property int $seconds Second component of the current interval. (CarbonInterval::minutes(2)->seconds(34)->microseconds(567_890)->seconds = 34)
 * @property int $milliseconds Milliseconds component of the current interval. (CarbonInterval::seconds(34)->microseconds(567_890)->milliseconds = 567)
 * @property int $microseconds Microseconds component of the current interval. (CarbonInterval::seconds(34)->microseconds(567_890)->microseconds = 567_890)
 * @property int $microExcludeMilli Remaining microseconds without the milliseconds.
 * @property int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
 * @property int $daysExcludeWeeks alias of dayzExcludeWeeks
 * @property-read float $totalYears Number of years equivalent to the interval. (For P1Y6M, the value will be 1.5)
 * @property-read float $totalMonths Number of months equivalent to the interval. (For P1Y6M10D, the value will be ~12.357)
 * @property-read float $totalWeeks Number of weeks equivalent to the interval. (For P6M17DT20H, the value will be ~26.548)
 * @property-read float $totalDays Number of days equivalent to the interval. (For P17DT20H, the value will be ~17.833)
 * @property-read float $totalDayz Alias for totalDays.
 * @property-read float $totalHours Number of hours equivalent to the interval. (For P1DT20H5M, the value will be ~44.083)
 * @property-read float $totalMinutes Number of minutes equivalent to the interval. (For PT20H5M30S, the value will be 1205.5)
 * @property-read float $totalSeconds Number of seconds equivalent to the interval. (CarbonInterval::minutes(2)->seconds(34)->microseconds(567_890)->totalSeconds = 154.567_890)
 * @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval. (CarbonInterval::seconds(34)->microseconds(567_890)->totalMilliseconds = 34567.890)
 * @property-read float $totalMicroseconds Number of microseconds equivalent to the interval. (CarbonInterval::seconds(34)->microseconds(567_890)->totalMicroseconds = 34567890)
 * @property-read string $locale locale of the current instance
 *
 * @method static CarbonInterval years($years = 1) Create instance specifying a number of years or modify the number of years if called on an instance.
 * @method static CarbonInterval year($years = 1) Alias for years()
 * @method static CarbonInterval months($months = 1) Create instance specifying a number of months or modify the number of months if called on an instance.
 * @method static CarbonInterval month($months = 1) Alias for months()
 * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks or modify the number of weeks if called on an instance.
 * @method static CarbonInterval week($weeks = 1) Alias for weeks()
 * @method static CarbonInterval days($days = 1) Create instance specifying a number of days or modify the number of days if called on an instance.
 * @method static CarbonInterval dayz($days = 1) Alias for days()
 * @method static CarbonInterval daysExcludeWeeks($days = 1) Create instance specifying a number of days or modify the number of days (keeping the current number of weeks) if called on an instance.
 * @method static CarbonInterval dayzExcludeWeeks($days = 1) Alias for daysExcludeWeeks()
 * @method static CarbonInterval day($days = 1) Alias for days()
 * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours or modify the number of hours if called on an instance.
 * @method static CarbonInterval hour($hours = 1) Alias for hours()
 * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes or modify the number of minutes if called on an instance.
 * @method static CarbonInterval minute($minutes = 1) Alias for minutes()
 * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds or modify the number of seconds if called on an instance.
 * @method static CarbonInterval second($seconds = 1) Alias for seconds()
 * @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds or modify the number of milliseconds if called on an instance.
 * @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds()
 * @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds or modify the number of microseconds if called on an instance.
 * @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds()
 * @method $this addYears(int $years) Add given number of years to the current interval
 * @method $this subYears(int $years) Subtract given number of years to the current interval
 * @method $this addMonths(int $months) Add given number of months to the current interval
 * @method $this subMonths(int $months) Subtract given number of months to the current interval
 * @method $this addWeeks(int|float $weeks) Add given number of weeks to the current interval
 * @method $this subWeeks(int|float $weeks) Subtract given number of weeks to the current interval
 * @method $this addDays(int|float $days) Add given number of days to the current interval
 * @method $this subDays(int|float $days) Subtract given number of days to the current interval
 * @method $this addHours(int|float $hours) Add given number of hours to the current interval
 * @method $this subHours(int|float $hours) Subtract given number of hours to the current interval
 * @method $this addMinutes(int|float $minutes) Add given number of minutes to the current interval
 * @method $this subMinutes(int|float $minutes) Subtract given number of minutes to the current interval
 * @method $this addSeconds(int|float $seconds) Add given number of seconds to the current interval
 * @method $this subSeconds(int|float $seconds) Subtract given number of seconds to the current interval
 * @method $this addMilliseconds(int|float $milliseconds) Add given number of milliseconds to the current interval
 * @method $this subMilliseconds(int|float $milliseconds) Subtract given number of milliseconds to the current interval
 * @method $this addMicroseconds(int|float $microseconds) Add given number of microseconds to the current interval
 * @method $this subMicroseconds(int|float $microseconds) Subtract given number of microseconds to the current interval
 * @method $this roundYear(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
 * @method $this roundYears(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
 * @method $this floorYear(int|float $precision = 1) Truncate the current instance year with given precision.
 * @method $this floorYears(int|float $precision = 1) Truncate the current instance year with given precision.
 * @method $this ceilYear(int|float $precision = 1) Ceil the current instance year with given precision.
 * @method $this ceilYears(int|float $precision = 1) Ceil the current instance year with given precision.
 * @method $this roundMonth(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
 * @method $this roundMonths(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
 * @method $this floorMonth(int|float $precision = 1) Truncate the current instance month with given precision.
 * @method $this floorMonths(int|float $precision = 1) Truncate the current instance month with given precision.
 * @method $this ceilMonth(int|float $precision = 1) Ceil the current instance month with given precision.
 * @method $this ceilMonths(int|float $precision = 1) Ceil the current instance month with given precision.
 * @method $this roundWeek(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this roundWeeks(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this floorWeek(int|float $precision = 1) Truncate the current instance day with given precision.
 * @method $this floorWeeks(int|float $precision = 1) Truncate the current instance day with given precision.
 * @method $this ceilWeek(int|float $precision = 1) Ceil the current instance day with given precision.
 * @method $this ceilWeeks(int|float $precision = 1) Ceil the current instance day with given precision.
 * @method $this roundDay(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this roundDays(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
 * @method $this floorDay(int|float $precision = 1) Truncate the current instance day with given precision.
 * @method $this floorDays(int|float $precision = 1) Truncate the current instance day with given precision.
 * @method $this ceilDay(int|float $precision = 1) Ceil the current instance day with given precision.
 * @method $this ceilDays(int|float $precision = 1) Ceil the current instance day with given precision.
 * @method $this roundHour(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
 * @method $this roundHours(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
 * @method $this floorHour(int|float $precision = 1) Truncate the current instance hour with given precision.
 * @method $this floorHours(int|float $precision = 1) Truncate the current instance hour with given precision.
 * @method $this ceilHour(int|float $precision = 1) Ceil the current instance hour with given precision.
 * @method $this ceilHours(int|float $precision = 1) Ceil the current instance hour with given precision.
 * @method $this roundMinute(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
 * @method $this roundMinutes(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
 * @method $this floorMinute(int|float $precision = 1) Truncate the current instance minute with given precision.
 * @method $this floorMinutes(int|float $precision = 1) Truncate the current instance minute with given precision.
 * @method $this ceilMinute(int|float $precision = 1) Ceil the current instance minute with given precision.
 * @method $this ceilMinutes(int|float $precision = 1) Ceil the current instance minute with given precision.
 * @method $this roundSecond(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
 * @method $this roundSeconds(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
 * @method $this floorSecond(int|float $precision = 1) Truncate the current instance second with given precision.
 * @method $this floorSeconds(int|float $precision = 1) Truncate the current instance second with given precision.
 * @method $this ceilSecond(int|float $precision = 1) Ceil the current instance second with given precision.
 * @method $this ceilSeconds(int|float $precision = 1) Ceil the current instance second with given precision.
 * @method $this roundMillennium(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
 * @method $this roundMillennia(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
 * @method $this floorMillennium(int|float $precision = 1) Truncate the current instance millennium with given precision.
 * @method $this floorMillennia(int|float $precision = 1) Truncate the current instance millennium with given precision.
 * @method $this ceilMillennium(int|float $precision = 1) Ceil the current instance millennium with given precision.
 * @method $this ceilMillennia(int|float $precision = 1) Ceil the current instance millennium with given precision.
 * @method $this roundCentury(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
 * @method $this roundCenturies(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
 * @method $this floorCentury(int|float $precision = 1) Truncate the current instance century with given precision.
 * @method $this floorCenturies(int|float $precision = 1) Truncate the current instance century with given precision.
 * @method $this ceilCentury(int|float $precision = 1) Ceil the current instance century with given precision.
 * @method $this ceilCenturies(int|float $precision = 1) Ceil the current instance century with given precision.
 * @method $this roundDecade(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
 * @method $this roundDecades(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
 * @method $this floorDecade(int|float $precision = 1) Truncate the current instance decade with given precision.
 * @method $this floorDecades(int|float $precision = 1) Truncate the current instance decade with given precision.
 * @method $this ceilDecade(int|float $precision = 1) Ceil the current instance decade with given precision.
 * @method $this ceilDecades(int|float $precision = 1) Ceil the current instance decade with given precision.
 * @method $this roundQuarter(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
 * @method $this roundQuarters(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
 * @method $this floorQuarter(int|float $precision = 1) Truncate the current instance quarter with given precision.
 * @method $this floorQuarters(int|float $precision = 1) Truncate the current instance quarter with given precision.
 * @method $this ceilQuarter(int|float $precision = 1) Ceil the current instance quarter with given precision.
 * @method $this ceilQuarters(int|float $precision = 1) Ceil the current instance quarter with given precision.
 * @method $this roundMillisecond(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
 * @method $this roundMilliseconds(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
 * @method $this floorMillisecond(int|float $precision = 1) Truncate the current instance millisecond with given precision.
 * @method $this floorMilliseconds(int|float $precision = 1) Truncate the current instance millisecond with given precision.
 * @method $this ceilMillisecond(int|float $precision = 1) Ceil the current instance millisecond with given precision.
 * @method $this ceilMilliseconds(int|float $precision = 1) Ceil the current instance millisecond with given precision.
 * @method $this roundMicrosecond(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
 * @method $this roundMicroseconds(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
 * @method $this floorMicrosecond(int|float $precision = 1) Truncate the current instance microsecond with given precision.
 * @method $this floorMicroseconds(int|float $precision = 1) Truncate the current instance microsecond with given precision.
 * @method $this ceilMicrosecond(int|float $precision = 1) Ceil the current instance microsecond with given precision.
 * @method $this ceilMicroseconds(int|float $precision = 1) Ceil the current instance microsecond with given precision.
 */
class CarbonInterval extends DateInterval implements CarbonConverterInterface, UnitValue
{
    use LocalFactory;
    use IntervalRounding;
    use IntervalStep;
    use MagicParameter;
    use Mixin {
        Mixin::mixin as baseMixin;
    }
    use Options;
    use ToStringFormat;

    /**
     * Unlimited parts for forHumans() method.
     *
     * INF constant can be used instead.
     */
    public const NO_LIMIT = -1;

    public const POSITIVE = 1;
    public const NEGATIVE = -1;

    /**
     * Interval spec period designators
     */
    public const PERIOD_PREFIX = 'P';
    public const PERIOD_YEARS = 'Y';
    public const PERIOD_MONTHS = 'M';
    public const PERIOD_DAYS = 'D';
    public const PERIOD_TIME_PREFIX = 'T';
    public const PERIOD_HOURS = 'H';
    public const PERIOD_MINUTES = 'M';
    public const PERIOD_SECONDS = 'S';

    public const SPECIAL_TRANSLATIONS = [
        1 => [
            'option' => CarbonInterface::ONE_DAY_WORDS,
            'future' => 'diff_tomorrow',
            'past' => 'diff_yesterday',
        ],
        2 => [
            'option' => CarbonInterface::TWO_DAY_WORDS,
            'future' => 'diff_after_tomorrow',
            'past' => 'diff_before_yesterday',
        ],
    ];

    protected static ?array $cascadeFactors = null;

    protected static array $formats = [
        'y' => 'y',
        'Y' => 'y',
        'o' => 'y',
        'm' => 'm',
        'n' => 'm',
        'W' => 'weeks',
        'd' => 'd',
        'j' => 'd',
        'z' => 'd',
        'h' => 'h',
        'g' => 'h',
        'H' => 'h',
        'G' => 'h',
        'i' => 'i',
        's' => 's',
        'u' => 'micro',
        'v' => 'milli',
    ];

    private static ?array $flipCascadeFactors = null;

    private static bool $floatSettersEnabled = false;

    /**
     * The registered macros.
     */
    protected static array $macros = [];

    /**
     * Timezone handler for settings() method.
     */
    protected DateTimeZone|string|int|null $timezoneSetting = null;

    /**
     * The input used to create the interval.
     */
    protected mixed $originalInput = null;

    /**
     * Start date if interval was created from a difference between 2 dates.
     */
    protected ?CarbonInterface $startDate = null;

    /**
     * End date if interval was created from a difference between 2 dates.
     */
    protected ?CarbonInterface $endDate = null;

    /**
     * End date if interval was created from a difference between 2 dates.
     */
    protected ?DateInterval $rawInterval = null;

    /**
     * Flag if the interval was made from a diff with absolute flag on.
     */
    protected bool $absolute = false;

    protected ?array $initialValues = null;

    /**
     * Set the instance's timezone from a string or object.
     */
    public function setTimezone(DateTimeZone|string|int $timezone): static
    {
        $this->timezoneSetting = $timezone;
        $this->checkStartAndEnd();

        if ($this->startDate) {
            $this->startDate = $this->startDate
                ->avoidMutation()
                ->setTimezone($timezone);
            $this->rawInterval = null;
        }

        if ($this->endDate) {
            $this->endDate = $this->endDate
                ->avoidMutation()
                ->setTimezone($timezone);
            $this->rawInterval = null;
        }

        return $this;
    }

    /**
     * Set the instance's timezone from a string or object and add/subtract the offset difference.
     */
    public function shiftTimezone(DateTimeZone|string|int $timezone): static
    {
        $this->timezoneSetting = $timezone;
        $this->checkStartAndEnd();

        if ($this->startDate) {
            $this->startDate = $this->startDate
                ->avoidMutation()
                ->shiftTimezone($timezone);
            $this->rawInterval = null;
        }

        if ($this->endDate) {
            $this->endDate = $this->endDate
                ->avoidMutation()
                ->shiftTimezone($timezone);
            $this->rawInterval = null;
        }

        return $this;
    }

    /**
     * Mapping of units and factors for cascading.
     *
     * Should only be modified by changing the factors or referenced constants.
     */
    public static function getCascadeFactors(): array
    {
        return static::$cascadeFactors ?: static::getDefaultCascadeFactors();
    }

    protected static function getDefaultCascadeFactors(): array
    {
        return [
            'milliseconds' => [CarbonInterface::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
            'seconds' => [CarbonInterface::MILLISECONDS_PER_SECOND, 'milliseconds'],
            'minutes' => [CarbonInterface::SECONDS_PER_MINUTE, 'seconds'],
            'hours' => [CarbonInterface::MINUTES_PER_HOUR, 'minutes'],
            'dayz' => [CarbonInterface::HOURS_PER_DAY, 'hours'],
            'weeks' => [CarbonInterface::DAYS_PER_WEEK, 'dayz'],
            'months' => [CarbonInterface::WEEKS_PER_MONTH, 'weeks'],
            'years' => [CarbonInterface::MONTHS_PER_YEAR, 'months'],
        ];
    }

    /**
     * Set default cascading factors for ->cascade() method.
     *
     * @param array $cascadeFactors
     */
    public static function setCascadeFactors(array $cascadeFactors)
    {
        self::$flipCascadeFactors = null;
        static::$cascadeFactors = $cascadeFactors;
    }

    /**
     * This option allow you to opt-in for the Carbon 3 behavior where float
     * values will no longer be cast to integer (so truncated).
     *
     * ⚠️ This settings will be applied globally, which mean your whole application
     * code including the third-party dependencies that also may use Carbon will
     * adopt the new behavior.
     */
    public static function enableFloatSetters(bool $floatSettersEnabled = true): void
    {
        self::$floatSettersEnabled = $floatSettersEnabled;
    }

    ///////////////////////////////////////////////////////////////////
    //////////////////////////// CONSTRUCTORS /////////////////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Create a new CarbonInterval instance.
     *
     * @param Closure|DateInterval|string|int|null $years
     * @param int|float|null                       $months
     * @param int|float|null                       $weeks
     * @param int|float|null                       $days
     * @param int|float|null                       $hours
     * @param int|float|null                       $minutes
     * @param int|float|null                       $seconds
     * @param int|float|null                       $microseconds
     *
     * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
     */
    public function __construct($years = null, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
    {
        $this->originalInput = \func_num_args() === 1 ? $years : \func_get_args();

        if ($years instanceof Closure) {
            $this->step = $years;
            $years = null;
        }

        if ($years instanceof DateInterval) {
            parent::__construct(static::getDateIntervalSpec($years));
            $this->f = $years->f;
            self::copyNegativeUnits($years, $this);

            return;
        }

        $spec = $years;
        $isStringSpec = (\is_string($spec) && !preg_match('/^[\d.]/', $spec));

        if (!$isStringSpec || (float) $years) {
            $spec = static::PERIOD_PREFIX;

            $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
            $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';

            $specDays = 0;
            $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
            $specDays += $days > 0 ? $days : 0;

            $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';

            if ($hours > 0 || $minutes > 0 || $seconds > 0) {
                $spec .= static::PERIOD_TIME_PREFIX;
                $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
                $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
                $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
            }

            if ($spec === static::PERIOD_PREFIX) {
                // Allow the zero interval.
                $spec .= '0'.static::PERIOD_YEARS;
            }
        }

        try {
            parent::__construct($spec);
        } catch (Throwable $exception) {
            try {
                parent::__construct('PT0S');

                if ($isStringSpec) {
                    if (!preg_match('/^P
                        (?:(?<year>[+-]?\d*(?:\.\d+)?)Y)?
                        (?:(?<month>[+-]?\d*(?:\.\d+)?)M)?
                        (?:(?<week>[+-]?\d*(?:\.\d+)?)W)?
                        (?:(?<day>[+-]?\d*(?:\.\d+)?)D)?
                        (?:T
                            (?:(?<hour>[+-]?\d*(?:\.\d+)?)H)?
                            (?:(?<minute>[+-]?\d*(?:\.\d+)?)M)?
                            (?:(?<second>[+-]?\d*(?:\.\d+)?)S)?
                        )?
                    $/x', $spec, $match)) {
                        throw new InvalidArgumentException("Invalid duration: $spec");
                    }

                    $years = (float) ($match['year'] ?? 0);
                    $this->assertSafeForInteger('year', $years);
                    $months = (float) ($match['month'] ?? 0);
                    $this->assertSafeForInteger('month', $months);
                    $weeks = (float) ($match['week'] ?? 0);
                    $this->assertSafeForInteger('week', $weeks);
                    $days = (float) ($match['day'] ?? 0);
                    $this->assertSafeForInteger('day', $days);
                    $hours = (float) ($match['hour'] ?? 0);
                    $this->assertSafeForInteger('hour', $hours);
                    $minutes = (float) ($match['minute'] ?? 0);
                    $this->assertSafeForInteger('minute', $minutes);
                    $seconds = (float) ($match['second'] ?? 0);
                    $this->assertSafeForInteger('second', $seconds);
                    $microseconds = (int) str_pad(
                        substr(explode('.', $match['second'] ?? '0.0')[1] ?? '0', 0, 6),
                        6,
                        '0',
                    );
                }

                $totalDays = (($weeks * static::getDaysPerWeek()) + $days);
                $this->assertSafeForInteger('days total (including weeks)', $totalDays);

                $this->y = (int) $years;
                $this->m = (int) $months;
                $this->d = (int) $totalDays;
                $this->h = (int) $hours;
                $this->i = (int) $minutes;
                $this->s = (int) $seconds;
                $secondFloatPart = (float) ($microseconds / CarbonInterface::MICROSECONDS_PER_SECOND);
                $this->f = $secondFloatPart;
                $intervalMicroseconds = (int) ($this->f * CarbonInterface::MICROSECONDS_PER_SECOND);
                $intervalSeconds = $seconds - $secondFloatPart;

                if (
                    ((float) $this->y) !== $years ||
                    ((float) $this->m) !== $months ||
                    ((float) $this->d) !== $totalDays ||
                    ((float) $this->h) !== $hours ||
                    ((float) $this->i) !== $minutes ||
                    ((float) $this->s) !== $intervalSeconds ||
                    $intervalMicroseconds !== ((int) $microseconds)
                ) {
                    $this->add(static::fromString(
                        ($years - $this->y).' years '.
                        ($months - $this->m).' months '.
                        ($totalDays - $this->d).' days '.
                        ($hours - $this->h).' hours '.
                        ($minutes - $this->i).' minutes '.
                        number_format($intervalSeconds - $this->s, 6, '.', '').' seconds '.
                        ($microseconds - $intervalMicroseconds).' microseconds ',
                    ));
                }
            } catch (Throwable $secondException) {
                throw $secondException instanceof OutOfRangeException ? $secondException : $exception;
            }
        }

        if ($microseconds !== null) {
            $this->f = $microseconds / CarbonInterface::MICROSECONDS_PER_SECOND;
        }

        foreach (['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'] as $unit) {
            if ($$unit < 0) {
                $this->set($unit, $$unit);
            }
        }
    }

    /**
     * Returns the factor for a given source-to-target couple.
     *
     * @param string $source
     * @param string $target
     *
     * @return int|float|null
     */
    public static function getFactor($source, $target)
    {
        $source = self::standardizeUnit($source);
        $target = self::standardizeUnit($target);
        $factors = self::getFlipCascadeFactors();

        if (isset($factors[$source])) {
            [$to, $factor] = $factors[$source];

            if ($to === $target) {
                return $factor;
            }

            return $factor * static::getFactor($to, $target);
        }

        return null;
    }

    /**
     * Returns the factor for a given source-to-target couple if set,
     * else try to find the appropriate constant as the factor, such as Carbon::DAYS_PER_WEEK.
     *
     * @param string $source
     * @param string $target
     *
     * @return int|float|null
     */
    public static function getFactorWithDefault($source, $target)
    {
        $factor = self::getFactor($source, $target);

        if ($factor) {
            return $factor;
        }

        static $defaults = [
            'month' => ['year' => Carbon::MONTHS_PER_YEAR],
            'week' => ['month' => Carbon::WEEKS_PER_MONTH],
            'day' => ['week' => Carbon::DAYS_PER_WEEK],
            'hour' => ['day' => Carbon::HOURS_PER_DAY],
            'minute' => ['hour' => Carbon::MINUTES_PER_HOUR],
            'second' => ['minute' => Carbon::SECONDS_PER_MINUTE],
            'millisecond' => ['second' => Carbon::MILLISECONDS_PER_SECOND],
            'microsecond' => ['millisecond' => Carbon::MICROSECONDS_PER_MILLISECOND],
        ];

        return $defaults[$source][$target] ?? null;
    }

    /**
     * Returns current config for days per week.
     *
     * @return int|float
     */
    public static function getDaysPerWeek()
    {
        return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
    }

    /**
     * Returns current config for hours per day.
     *
     * @return int|float
     */
    public static function getHoursPerDay()
    {
        return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
    }

    /**
     * Returns current config for minutes per hour.
     *
     * @return int|float
     */
    public static function getMinutesPerHour()
    {
        return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
    }

    /**
     * Returns current config for seconds per minute.
     *
     * @return int|float
     */
    public static function getSecondsPerMinute()
    {
        return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
    }

    /**
     * Returns current config for microseconds per second.
     *
     * @return int|float
     */
    public static function getMillisecondsPerSecond()
    {
        return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
    }

    /**
     * Returns current config for microseconds per second.
     *
     * @return int|float
     */
    public static function getMicrosecondsPerMillisecond()
    {
        return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
    }

    /**
     * Create a new CarbonInterval instance from specific values.
     * This is an alias for the constructor that allows better fluent
     * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
     * (new CarbonInterval(1))->fn().
     *
     * @param int $years
     * @param int $months
     * @param int $weeks
     * @param int $days
     * @param int $hours
     * @param int $minutes
     * @param int $seconds
     * @param int $microseconds
     *
     * @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
     *
     * @return static
     */
    public static function create($years = null, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
    {
        return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
    }

    /**
     * Parse a string into a new CarbonInterval object according to the specified format.
     *
     * @example
     * ```
     * echo Carboninterval::createFromFormat('H:i', '1:30');
     * ```
     *
     * @param string      $format   Format of the $interval input string
     * @param string|null $interval Input string to convert into an interval
     *
     * @throws \Carbon\Exceptions\ParseErrorException when the $interval cannot be parsed as an interval.
     *
     * @return static
     */
    public static function createFromFormat(string $format, ?string $interval): static
    {
        $instance = new static(0);
        $length = mb_strlen($format);

        if (preg_match('/s([,.])([uv])$/', $format, $match)) {
            $interval = explode($match[1], $interval);
            $index = \count($interval) - 1;
            $interval[$index] = str_pad($interval[$index], $match[2] === 'v' ? 3 : 6, '0');
            $interval = implode($match[1], $interval);
        }

        $interval ??= '';

        for ($index = 0; $index < $length; $index++) {
            $expected = mb_substr($format, $index, 1);
            $nextCharacter = mb_substr($interval, 0, 1);
            $unit = static::$formats[$expected] ?? null;

            if ($unit) {
                if (!preg_match('/^-?\d+/', $interval, $match)) {
                    throw new ParseErrorException('number', $nextCharacter);
                }

                $interval = mb_substr($interval, mb_strlen($match[0]));
                self::incrementUnit($instance, $unit, (int) ($match[0]));

                continue;
            }

            if ($nextCharacter !== $expected) {
                throw new ParseErrorException(
                    "'$expected'",
                    $nextCharacter,
                    'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
                    'See https://php.net/manual/en/function.date.php for their meaning',
                );
            }

            $interval = mb_substr($interval, 1);
        }

        if ($interval !== '') {
            throw new ParseErrorException(
                'end of string',
                $interval,
            );
        }

        return $instance;
    }

    /**
     * Return the original source used to create the current interval.
     *
     * @return array|int|string|DateInterval|mixed|null
     */
    public function original()
    {
        return $this->originalInput;
    }

    /**
     * Return the start date if interval was created from a difference between 2 dates.
     *
     * @return CarbonInterface|null
     */
    public function start(): ?CarbonInterface
    {
        $this->checkStartAndEnd();

        return $this->startDate;
    }

    /**
     * Return the end date if interval was created from a difference between 2 dates.
     *
     * @return CarbonInterface|null
     */
    public function end(): ?CarbonInterface
    {
        $this->checkStartAndEnd();

        return $this->endDate;
    }

    /**
     * Get rid of the original input, start date and end date that may be kept in memory.
     *
     * @return $this
     */
    public function optimize(): static
    {
        $this->originalInput = null;
        $this->startDate = null;
        $this->endDate = null;
        $this->rawInterval = null;
        $this->absolute = false;

        return $this;
    }

    /**
     * Get a copy of the instance.
     *
     * @return static
     */
    public function copy(): static
    {
        $date = new static(0);
        $date->copyProperties($this);
        $date->step = $this->step;

        return $date;
    }

    /**
     * Get a copy of the instance.
     *
     * @return static
     */
    public function clone(): static
    {
        return $this->copy();
    }

    /**
     * Provide static helpers to create instances.  Allows CarbonInterval::years(3).
     *
     * Note: This is done using the magic method to allow static and instance methods to
     *       have the same names.
     *
     * @param string $method     magic method name called
     * @param array  $parameters parameters list
     *
     * @return static|mixed|null
     */
    public static function __callStatic(string $method, array $parameters)
    {
        try {
            $interval = new static(0);
            $localStrictModeEnabled = $interval->localStrictModeEnabled;
            $interval->localStrictModeEnabled = true;

            $result = static::hasMacro($method)
                ? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) {
                    return $interval->callMacro($method, $parameters);
                })
                : $interval->$method(...$parameters);

            $interval->localStrictModeEnabled = $localStrictModeEnabled;

            return $result;
        } catch (BadFluentSetterException $exception) {
            if (Carbon::isStrictModeEnabled()) {
                throw new BadFluentConstructorException($method, 0, $exception);
            }

            return null;
        }
    }

    /**
     * Evaluate the PHP generated by var_export() and recreate the exported CarbonInterval instance.
     *
     * @param array $dump data as exported by var_export()
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public static function __set_state($dump)
    {
        /** @noinspection PhpVoidFunctionResultUsedInspection */
        /** @var DateInterval $dateInterval */
        $dateInterval = parent::__set_state($dump);

        return static::instance($dateInterval);
    }

    /**
     * Return the current context from inside a macro callee or a new one if static.
     *
     * @return static
     */
    protected static function this(): static
    {
        return end(static::$macroContextStack) ?: new static(0);
    }

    /**
     * Creates a CarbonInterval from string.
     *
     * Format:
     *
     * Suffix | Unit    | Example | DateInterval expression
     * -------|---------|---------|------------------------
     * y      | years   |   1y    | P1Y
     * mo     | months  |   3mo   | P3M
     * w      | weeks   |   2w    | P2W
     * d      | days    |  28d    | P28D
     * h      | hours   |   4h    | PT4H
     * m      | minutes |  12m    | PT12M
     * s      | seconds |  59s    | PT59S
     *
     * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
     *
     * Special cases:
     *  - An empty string will return a zero interval
     *  - Fractions are allowed for weeks, days, hours and minutes and will be converted
     *    and rounded to the next smaller value (caution: 0.5w = 4d)
     *
     * @param string $intervalDefinition
     *
     * @throws InvalidIntervalException
     *
     * @return static
     */
    public static function fromString(string $intervalDefinition): static
    {
        if (empty($intervalDefinition)) {
            return self::withOriginal(new static(0), $intervalDefinition);
        }

        $years = 0;
        $months = 0;
        $weeks = 0;
        $days = 0;
        $hours = 0;
        $minutes = 0;
        $seconds = 0;
        $milliseconds = 0;
        $microseconds = 0;

        $pattern = '/(-?\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
        preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);

        while ([$part, $value, $unit] = array_shift($parts)) {
            $intValue = (int) $value;
            $fraction = (float) $value - $intValue;

            // Fix calculation precision
            switch (round($fraction, 6)) {
                case 1:
                    $fraction = 0;
                    $intValue++;

                    break;
                case 0:
                    $fraction = 0;

                    break;
            }

            switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
                case 'millennia':
                case 'millennium':
                    $years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;

                    break;

                case 'century':
                case 'centuries':
                    $years += $intValue * CarbonInterface::YEARS_PER_CENTURY;

                    break;

                case 'decade':
                case 'decades':
                    $years += $intValue * CarbonInterface::YEARS_PER_DECADE;

                    break;

                case 'year':
                case 'years':
                case 'y':
                case 'yr':
                case 'yrs':
                    $years += $intValue;

                    break;

                case 'quarter':
                case 'quarters':
                    $months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;

                    break;

                case 'month':
                case 'months':
                case 'mo':
                case 'mos':
                    $months += $intValue;

                    break;

                case 'week':
                case 'weeks':
                case 'w':
                    $weeks += $intValue;

                    if ($fraction) {
                        $parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
                    }

                    break;

                case 'day':
                case 'days':
                case 'd':
                    $days += $intValue;

                    if ($fraction) {
                        $parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
                    }

                    break;

                case 'hour':
                case 'hours':
                case 'h':
                    $hours += $intValue;

                    if ($fraction) {
                        $parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
                    }

                    break;

                case 'minute':
                case 'minutes':
                case 'm':
                    $minutes += $intValue;

                    if ($fraction) {
                        $parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
                    }

                    break;

                case 'second':
                case 'seconds':
                case 's':
                    $seconds += $intValue;

                    if ($fraction) {
                        $parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
                    }

                    break;

                case 'millisecond':
                case 'milliseconds':
                case 'milli':
                case 'ms':
                    $milliseconds += $intValue;

                    if ($fraction) {
                        $microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
                    }

                    break;

                case 'microsecond':
                case 'microseconds':
                case 'micro':
                case 'µs':
                    $microseconds += $intValue;

                    break;

                default:
                    throw new InvalidIntervalException(
                        "Invalid part $part in definition $intervalDefinition",
                    );
            }
        }

        return self::withOriginal(
            new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds),
            $intervalDefinition,
        );
    }

    /**
     * Creates a CarbonInterval from string using a different locale.
     *
     * @param string      $interval interval string in the given language (may also contain English).
     * @param string|null $locale   if locale is null or not specified, current global locale will be used instead.
     *
     * @return static
     */
    public static function parseFromLocale(string $interval, ?string $locale = null): static
    {
        return static::fromString(Carbon::translateTimeString($interval, $locale ?: static::getLocale(), CarbonInterface::DEFAULT_LOCALE));
    }

    /**
     * Create an interval from the difference between 2 dates.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $start
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $end
     *
     * @return static
     */
    public static function diff($start, $end = null, bool $absolute = false, array $skip = []): static
    {
        $start = $start instanceof CarbonInterface ? $start : Carbon::make($start);
        $end = $end instanceof CarbonInterface ? $end : Carbon::make($end);
        $rawInterval = $start->diffAsDateInterval($end, $absolute);
        $interval = static::instance($rawInterval, $skip);

        $interval->absolute = $absolute;
        $interval->rawInterval = $rawInterval;
        $interval->startDate = $start;
        $interval->endDate = $end;
        $interval->initialValues = $interval->getInnerValues();

        return $interval;
    }

    /**
     * Invert the interval if it's inverted.
     *
     * @param bool $absolute do nothing if set to false
     *
     * @return $this
     */
    public function abs(bool $absolute = false): static
    {
        if ($absolute && $this->invert) {
            $this->invert();
        }

        return $this;
    }

    /**
     * @alias abs
     *
     * Invert the interval if it's inverted.
     *
     * @param bool $absolute do nothing if set to false
     *
     * @return $this
     */
    public function absolute(bool $absolute = true): static
    {
        return $this->abs($absolute);
    }

    /**
     * Cast the current instance into the given class.
     *
     * @template T of DateInterval
     *
     * @psalm-param class-string<T> $className The $className::instance() method will be called to cast the current object.
     *
     * @return T
     */
    public function cast(string $className): mixed
    {
        return self::castIntervalToClass($this, $className);
    }

    /**
     * Create a CarbonInterval instance from a DateInterval one.  Can not instance
     * DateInterval objects created from DateTime::diff() as you can't externally
     * set the $days field.
     *
     * @param DateInterval $interval
     * @param bool         $skipCopy set to true to return the passed object
     *                               (without copying it) if it's already of the
     *                               current class
     *
     * @return static
     */
    public static function instance(DateInterval $interval, array $skip = [], bool $skipCopy = false): static
    {
        if ($skipCopy && $interval instanceof static) {
            return $interval;
        }

        return self::castIntervalToClass($interval, static::class, $skip);
    }

    /**
     * Make a CarbonInterval instance from given variable if possible.
     *
     * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
     * and recurrences). Throw an exception for invalid format, but otherwise return null.
     *
     * @param mixed|int|DateInterval|string|Closure|Unit|null $interval interval or number of the given $unit
     * @param Unit|string|null                                $unit     if specified, $interval must be an integer
     * @param bool                                            $skipCopy set to true to return the passed object
     *                                                                  (without copying it) if it's already of the
     *                                                                  current class
     *
     * @return static|null
     */
    public static function make($interval, $unit = null, bool $skipCopy = false): ?self
    {
        if ($interval instanceof Unit) {
            $interval = $interval->interval();
        }

        if ($unit instanceof Unit) {
            $unit = $unit->value;
        }

        if ($unit) {
            $interval = "$interval $unit";
        }

        if ($interval instanceof DateInterval) {
            return static::instance($interval, [], $skipCopy);
        }

        if ($interval instanceof Closure) {
            return self::withOriginal(new static($interval), $interval);
        }

        if (!\is_string($interval)) {
            return null;
        }

        return static::makeFromString($interval);
    }

    protected static function makeFromString(string $interval): ?self
    {
        $interval = preg_replace('/\s+/', ' ', trim($interval));

        if (preg_match('/^P[T\d]/', $interval)) {
            return new static($interval);
        }

        if (preg_match('/^(?:\h*-?\d+(?:\.\d+)?\h*[a-z]+)+$/i', $interval)) {
            return static::fromString($interval);
        }

        $intervalInstance = static::createFromDateString($interval);

        return $intervalInstance->isEmpty() ? null : $intervalInstance;
    }

    protected function resolveInterval($interval): ?self
    {
        if (!($interval instanceof self)) {
            return self::make($interval);
        }

        return $interval;
    }

    /**
     * Sets up a DateInterval from the relative parts of the string.
     *
     * @param string $datetime
     *
     * @return static
     *
     * @link https://php.net/manual/en/dateinterval.createfromdatestring.php
     */
    public static function createFromDateString(string $datetime): static
    {
        $string = strtr($datetime, [
            ',' => ' ',
            ' and ' => ' ',
        ]);
        $previousException = null;

        try {
            $interval = parent::createFromDateString($string);
        } catch (Throwable $exception) {
            $interval = null;
            $previousException = $exception;
        }

        $interval ?: throw new InvalidFormatException(
            'Could not create interval from: '.var_export($datetime, true),
            previous: $previousException,
        );

        if (!($interval instanceof static)) {
            $interval = static::instance($interval);
        }

        return self::withOriginal($interval, $datetime);
    }

    ///////////////////////////////////////////////////////////////////
    ///////////////////////// GETTERS AND SETTERS /////////////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Get a part of the CarbonInterval object.
     */
    public function get(Unit|string $name): int|float|string|null
    {
        $name = Unit::toName($name);

        if (str_starts_with($name, 'total')) {
            return $this->total(substr($name, 5));
        }

        $resolvedUnit = Carbon::singularUnit(rtrim($name, 'z'));

        return match ($resolvedUnit) {
            'tzname', 'tz_name' => match (true) {
                ($this->timezoneSetting === null) => null,
                \is_string($this->timezoneSetting) => $this->timezoneSetting,
                ($this->timezoneSetting instanceof DateTimeZone) => $this->timezoneSetting->getName(),
                default => CarbonTimeZone::instance($this->timezoneSetting)->getName(),
            },
            'year' => $this->y,
            'month' => $this->m,
            'day' => $this->d,
            'hour' => $this->h,
            'minute' => $this->i,
            'second' => $this->s,
            'milli', 'millisecond' => (int) (round($this->f * Carbon::MICROSECONDS_PER_SECOND) /
                Carbon::MICROSECONDS_PER_MILLISECOND),
            'micro', 'microsecond' => (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND),
            'microexcludemilli' => (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND) %
                Carbon::MICROSECONDS_PER_MILLISECOND,
            'week' => (int) ($this->d / (int) static::getDaysPerWeek()),
            'daysexcludeweek', 'dayzexcludeweek' => $this->d % (int) static::getDaysPerWeek(),
            'locale' => $this->getTranslatorLocale(),
            default => throw new UnknownGetterException($name, previous: new UnknownGetterException($resolvedUnit)),
        };
    }

    /**
     * Get a part of the CarbonInterval object.
     */
    public function __get(string $name): int|float|string|null
    {
        return $this->get($name);
    }

    /**
     * Set a part of the CarbonInterval object.
     *
     * @param Unit|string|array $name
     * @param int               $value
     *
     * @throws UnknownSetterException
     *
     * @return $this
     */
    public function set($name, $value = null): static
    {
        $properties = \is_array($name) ? $name : [$name => $value];

        foreach ($properties as $key => $value) {
            switch (Carbon::singularUnit($key instanceof Unit ? $key->value : rtrim((string) $key, 'z'))) {
                case 'year':
                    $this->checkIntegerValue($key, $value);
                    $this->y = $value;
                    $this->handleDecimalPart('year', $value, $this->y);

                    break;

                case 'month':
                    $this->checkIntegerValue($key, $value);
                    $this->m = $value;
                    $this->handleDecimalPart('month', $value, $this->m);

                    break;

                case 'week':
                    $this->checkIntegerValue($key, $value);
                    $days = $value * (int) static::getDaysPerWeek();
                    $this->assertSafeForInteger('days total (including weeks)', $days);
                    $this->d = $days;
                    $this->handleDecimalPart('day', $days, $this->d);

                    break;

                case 'day':
                    if ($value === false) {
                        break;
                    }

                    $this->checkIntegerValue($key, $value);
                    $this->d = $value;
                    $this->handleDecimalPart('day', $value, $this->d);

                    break;

                case 'daysexcludeweek':
                case 'dayzexcludeweek':
                    $this->checkIntegerValue($key, $value);
                    $days = $this->weeks * (int) static::getDaysPerWeek() + $value;
                    $this->assertSafeForInteger('days total (including weeks)', $days);
                    $this->d = $days;
                    $this->handleDecimalPart('day', $days, $this->d);

                    break;

                case 'hour':
                    $this->checkIntegerValue($key, $value);
                    $this->h = $value;
                    $this->handleDecimalPart('hour', $value, $this->h);

                    break;

                case 'minute':
                    $this->checkIntegerValue($key, $value);
                    $this->i = $value;
                    $this->handleDecimalPart('minute', $value, $this->i);

                    break;

                case 'second':
                    $this->checkIntegerValue($key, $value);
                    $this->s = $value;
                    $this->handleDecimalPart('second', $value, $this->s);

                    break;

                case 'milli':
                case 'millisecond':
                    $this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;

                    break;

                case 'micro':
                case 'microsecond':
                    $this->f = $value / Carbon::MICROSECONDS_PER_SECOND;

                    break;

                default:
                    if (str_starts_with($key, ' * ')) {
                        return $this->setSetting(substr($key, 3), $value);
                    }

                    if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
                        throw new UnknownSetterException($key);
                    }

                    $this->$key = $value;
            }
        }

        return $this;
    }

    /**
     * Set a part of the CarbonInterval object.
     *
     * @param string $name
     * @param int    $value
     *
     * @throws UnknownSetterException
     */
    public function __set(string $name, $value)
    {
        $this->set($name, $value);
    }

    /**
     * Allow setting of weeks and days to be cumulative.
     *
     * @param int $weeks Number of weeks to set
     * @param int $days  Number of days to set
     *
     * @return static
     */
    public function weeksAndDays(int $weeks, int $days): static
    {
        $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;

        return $this;
    }

    /**
     * Returns true if the interval is empty for each unit.
     *
     * @return bool
     */
    public function isEmpty(): bool
    {
        return $this->years === 0 &&
            $this->months === 0 &&
            $this->dayz === 0 &&
            !$this->days &&
            $this->hours === 0 &&
            $this->minutes === 0 &&
            $this->seconds === 0 &&
            $this->microseconds === 0;
    }

    /**
     * Register a custom macro.
     *
     * Pass null macro to remove it.
     *
     * @example
     * ```
     * CarbonInterval::macro('twice', function () {
     *   return $this->times(2);
     * });
     * echo CarbonInterval::hours(2)->twice();
     * ```
     *
     * @param-closure-this static $macro
     */
    public static function macro(string $name, ?callable $macro): void
    {
        static::$macros[$name] = $macro;
    }

    /**
     * Register macros from a mixin object.
     *
     * @example
     * ```
     * CarbonInterval::mixin(new class {
     *   public function daysToHours() {
     *     return function () {
     *       $this->hours += $this->days;
     *       $this->days = 0;
     *
     *       return $this;
     *     };
     *   }
     *   public function hoursToDays() {
     *     return function () {
     *       $this->days += $this->hours;
     *       $this->hours = 0;
     *
     *       return $this;
     *     };
     *   }
     * });
     * echo CarbonInterval::hours(5)->hoursToDays() . "\n";
     * echo CarbonInterval::days(5)->daysToHours() . "\n";
     * ```
     *
     * @param object|string $mixin
     *
     * @throws ReflectionException
     *
     * @return void
     */
    public static function mixin($mixin): void
    {
        static::baseMixin($mixin);
    }

    /**
     * Check if macro is registered.
     *
     * @param string $name
     *
     * @return bool
     */
    public static function hasMacro(string $name): bool
    {
        return isset(static::$macros[$name]);
    }

    /**
     * Call given macro.
     *
     * @param string $name
     * @param array  $parameters
     *
     * @return mixed
     */
    protected function callMacro(string $name, array $parameters)
    {
        $macro = static::$macros[$name];

        if ($macro instanceof Closure) {
            $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);

            return ($boundMacro ?: $macro)(...$parameters);
        }

        return $macro(...$parameters);
    }

    /**
     * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
     *
     * Note: This is done using the magic method to allow static and instance methods to
     *       have the same names.
     *
     * @param string $method     magic method name called
     * @param array  $parameters parameters list
     *
     * @throws BadFluentSetterException|Throwable
     *
     * @return static|int|float|string
     */
    public function __call(string $method, array $parameters)
    {
        if (static::hasMacro($method)) {
            return static::bindMacroContext($this, function () use (&$method, &$parameters) {
                return $this->callMacro($method, $parameters);
            });
        }

        $roundedValue = $this->callRoundMethod($method, $parameters);

        if ($roundedValue !== null) {
            return $roundedValue;
        }

        if (preg_match('/^(?<method>add|sub)(?<unit>[A-Z].*)$/', $method, $match)) {
            $value = $this->getMagicParameter($parameters, 0, Carbon::pluralUnit($match['unit']), 0);

            return $this->{$match['method']}($value, $match['unit']);
        }

        $value = $this->getMagicParameter($parameters, 0, Carbon::pluralUnit($method), 1);

        try {
            $this->set($method, $value);
        } catch (UnknownSetterException $exception) {
            if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
                throw new BadFluentSetterException($method, 0, $exception);
            }
        }

        return $this;
    }

    protected function getForHumansInitialVariables($syntax, $short): array
    {
        if (\is_array($syntax)) {
            return $syntax;
        }

        if (\is_int($short)) {
            return [
                'parts' => $short,
                'short' => false,
            ];
        }

        if (\is_bool($syntax)) {
            return [
                'short' => $syntax,
                'syntax' => CarbonInterface::DIFF_ABSOLUTE,
            ];
        }

        return [];
    }

    /**
     * @param mixed $syntax
     * @param mixed $short
     * @param mixed $parts
     * @param mixed $options
     *
     * @return array
     */
    protected function getForHumansParameters($syntax = null, $short = false, $parts = self::NO_LIMIT, $options = null): array
    {
        $optionalSpace = ' ';
        $default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
        /** @var bool|string $join */
        $join = $default === '' ? '' : ' ';
        /** @var bool|array|string $altNumbers */
        $altNumbers = false;
        $aUnit = false;
        $minimumUnit = 's';
        $skip = [];
        extract($this->getForHumansInitialVariables($syntax, $short));
        $skip = array_map(
            static fn ($unit) => $unit instanceof Unit ? $unit->value : $unit,
            (array) $skip,
        );
        $skip = array_map(
            'strtolower',
            array_filter($skip, static fn ($unit) => \is_string($unit) && $unit !== ''),
        );

        $syntax ??= CarbonInterface::DIFF_ABSOLUTE;

        if ($parts === self::NO_LIMIT) {
            $parts = INF;
        }

        $options ??= static::getHumanDiffOptions();

        if ($join === false) {
            $join = ' ';
        } elseif ($join === true) {
            $join = [
                $default,
                $this->getTranslationMessage('list.1') ?? $default,
            ];
        }

        if ($altNumbers && $altNumbers !== true) {
            $language = new Language($this->locale);
            $altNumbers = \in_array($language->getCode(), (array) $altNumbers, true);
        }

        if (\is_array($join)) {
            [$default, $last] = $join;

            if ($default !== ' ') {
                $optionalSpace = '';
            }

            $join = function ($list) use ($default, $last) {
                if (\count($list) < 2) {
                    return implode('', $list);
                }

                $end = array_pop($list);

                return implode($default, $list).$last.$end;
            };
        }

        if (\is_string($join)) {
            if ($join !== ' ') {
                $optionalSpace = '';
            }

            $glue = $join;
            $join = static fn ($list) => implode($glue, $list);
        }

        $interpolations = [
            ':optional-space' => $optionalSpace,
        ];

        $translator ??= isset($locale) ? Translator::get($locale) : null;

        return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip, $translator];
    }

    protected static function getRoundingMethodFromOptions(int $options): ?string
    {
        if ($options & CarbonInterface::ROUND) {
            return 'round';
        }

        if ($options & CarbonInterface::CEIL) {
            return 'ceil';
        }

        if ($options & CarbonInterface::FLOOR) {
            return 'floor';
        }

        return null;
    }

    /**
     * Returns interval values as an array where key are the unit names and values the counts.
     *
     * @return int[]
     */
    public function toArray(): array
    {
        return [
            'years' => $this->years,
            'months' => $this->months,
            'weeks' => $this->weeks,
            'days' => $this->daysExcludeWeeks,
            'hours' => $this->hours,
            'minutes' => $this->minutes,
            'seconds' => $this->seconds,
            'microseconds' => $this->microseconds,
        ];
    }

    /**
     * Returns interval non-zero values as an array where key are the unit names and values the counts.
     *
     * @return int[]
     */
    public function getNonZeroValues(): array
    {
        return array_filter($this->toArray(), 'intval');
    }

    /**
     * Returns interval values as an array where key are the unit names and values the counts
     * from the biggest non-zero one the the smallest non-zero one.
     *
     * @return int[]
     */
    public function getValuesSequence(): array
    {
        $nonZeroValues = $this->getNonZeroValues();

        if ($nonZeroValues === []) {
            return [];
        }

        $keys = array_keys($nonZeroValues);
        $firstKey = $keys[0];
        $lastKey = $keys[\count($keys) - 1];
        $values = [];
        $record = false;

        foreach ($this->toArray() as $unit => $count) {
            if ($unit === $firstKey) {
                $record = true;
            }

            if ($record) {
                $values[$unit] = $count;
            }

            if ($unit === $lastKey) {
                $record = false;
            }
        }

        return $values;
    }

    /**
     * Get the current interval in a human readable format in the current locale.
     *
     * @example
     * ```
     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
     * echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
     * echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
     * echo CarbonInterval::fromString('1d 24h')->forHumans(['minimumUnit' => 'hour']) . "\n";
     * ```
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contain:
     *                           ⦿ 'syntax' entry (see below)
     *                           ⦿ 'short' entry (see below)
     *                           ⦿ 'parts' entry (see below)
     *                           ⦿ 'options' entry (see below)
     *                           ⦿ 'skip' entry, list of units to skip (array of strings or a single string,
     *                           ` it can be the unit name (singular or plural) or its shortcut
     *                           ` (y, m, w, d, h, min, s, ms, µs).
     *                           ⦿ 'aUnit' entry, prefer "an hour" over "1 hour" if true
     *                           ⦿ 'altNumbers' entry, use alternative numbers if available
     *                           ` (from the current language if true is passed, from the given language(s)
     *                           ` if array or string is passed)
     *                           ⦿ 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           ⦿ 'minimumUnit' entry determines the smallest unit of time to display can be long or
     *                           `  short form of the units, e.g. 'hour' or 'h' (default value: s)
     *                           ⦿ 'locale' language in which the diff should be output (has no effect if 'translator' key is set)
     *                           ⦿ 'translator' a custom translator to use to translator the output.
     *                           if int passed, it adds modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: -1: no limits)
     * @param int       $options human diff options
     *
     * @throws Exception
     *
     * @return string
     */
    public function forHumans($syntax = null, $short = false, $parts = self::NO_LIMIT, $options = null): string
    {
        /* @var TranslatorInterface|null $translator */
        [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit, $skip, $translator] = $this
            ->getForHumansParameters($syntax, $short, $parts, $options);

        $interval = [];

        $syntax = (int) ($syntax ?? CarbonInterface::DIFF_ABSOLUTE);
        $absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
        $relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
        $count = 1;
        $unit = $short ? 's' : 'second';
        $isFuture = $this->invert === 1;
        $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
        $declensionMode = null;

        $translator ??= $this->getLocalTranslator();

        $handleDeclensions = function ($unit, $count, $index = 0, $parts = 1) use ($interpolations, $transId, $translator, $altNumbers, $absolute, &$declensionMode) {
            if (!$absolute) {
                $declensionMode = $declensionMode ?? $this->translate($transId.'_mode');

                if ($this->needsDeclension($declensionMode, $index, $parts)) {
                    // Some languages have special pluralization for past and future tense.
                    $key = $unit.'_'.$transId;
                    $result = $this->translate($key, $interpolations, $count, $translator, $altNumbers);

                    if ($result !== $key) {
                        return $result;
                    }
                }
            }

            $result = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);

            if ($result !== $unit) {
                return $result;
            }

            return null;
        };

        $intervalValues = $this;
        $method = static::getRoundingMethodFromOptions($options);

        if ($method) {
            $previousCount = INF;

            while (
                \count($intervalValues->getNonZeroValues()) > $parts &&
                ($count = \count($keys = array_keys($intervalValues->getValuesSequence()))) > 1
            ) {
                $index = min($count, $previousCount - 1) - 2;

                if ($index < 0) {
                    break;
                }

                $intervalValues = $this->copy()->roundUnit(
                    $keys[$index],
                    1,
                    $method,
                );
                $previousCount = $count;
            }
        }

        $diffIntervalArray = [
            ['value' => $intervalValues->years,             'unit' => 'year',        'unitShort' => 'y'],
            ['value' => $intervalValues->months,            'unit' => 'month',       'unitShort' => 'm'],
            ['value' => $intervalValues->weeks,             'unit' => 'week',        'unitShort' => 'w'],
            ['value' => $intervalValues->daysExcludeWeeks,  'unit' => 'day',         'unitShort' => 'd'],
            ['value' => $intervalValues->hours,             'unit' => 'hour',        'unitShort' => 'h'],
            ['value' => $intervalValues->minutes,           'unit' => 'minute',      'unitShort' => 'min'],
            ['value' => $intervalValues->seconds,           'unit' => 'second',      'unitShort' => 's'],
            ['value' => $intervalValues->milliseconds,      'unit' => 'millisecond', 'unitShort' => 'ms'],
            ['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'],
        ];

        if (!empty($skip)) {
            foreach ($diffIntervalArray as $index => &$unitData) {
                $nextIndex = $index + 1;

                if ($unitData['value'] &&
                    isset($diffIntervalArray[$nextIndex]) &&
                    \count(array_intersect([$unitData['unit'], $unitData['unit'].'s', $unitData['unitShort']], $skip))
                ) {
                    $diffIntervalArray[$nextIndex]['value'] += $unitData['value'] *
                        self::getFactorWithDefault($diffIntervalArray[$nextIndex]['unit'], $unitData['unit']);
                    $unitData['value'] = 0;
                }
            }
        }

        $transChoice = function ($short, $unitData, $index, $parts) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
            $count = $unitData['value'];

            if ($short) {
                $result = $handleDeclensions($unitData['unitShort'], $count, $index, $parts);

                if ($result !== null) {
                    return $result;
                }
            } elseif ($aUnit) {
                $result = $handleDeclensions('a_'.$unitData['unit'], $count, $index, $parts);

                if ($result !== null) {
                    return $result;
                }
            }

            if (!$absolute) {
                return $handleDeclensions($unitData['unit'], $count, $index, $parts);
            }

            return $this->translate($unitData['unit'], $interpolations, $count, $translator, $altNumbers);
        };

        $fallbackUnit = ['second', 's'];

        foreach ($diffIntervalArray as $diffIntervalData) {
            if ($diffIntervalData['value'] > 0) {
                $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
                $count = $diffIntervalData['value'];
                $interval[] = [$short, $diffIntervalData];
            } elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && \count($interval) > 0) {
                break;
            }

            // break the loop after we get the required number of parts in array
            if (\count($interval) >= $parts) {
                break;
            }

            // break the loop after we have reached the minimum unit
            if (\in_array($minimumUnit, [$diffIntervalData['unit'], $diffIntervalData['unitShort']], true)) {
                $fallbackUnit = [$diffIntervalData['unit'], $diffIntervalData['unitShort']];

                break;
            }
        }

        $actualParts = \count($interval);

        foreach ($interval as $index => &$item) {
            $item = $transChoice($item[0], $item[1], $index, $actualParts);
        }

        if (\count($interval) === 0) {
            if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
                $key = 'diff_now';
                $translation = $this->translate($key, $interpolations, null, $translator);

                if ($translation !== $key) {
                    return $translation;
                }
            }

            $count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
            $unit = $fallbackUnit[$short ? 1 : 0];
            $interval[] = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
        }

        // join the interval parts by a space
        $time = $join($interval);

        unset($diffIntervalArray, $interval);

        if ($absolute) {
            return $time;
        }

        $isFuture = $this->invert === 1;

        $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');

        if ($parts === 1) {
            if ($relativeToNow && $unit === 'day') {
                $specialTranslations = static::SPECIAL_TRANSLATIONS[$count] ?? null;

                if ($specialTranslations && $options & $specialTranslations['option']) {
                    $key = $specialTranslations[$isFuture ? 'future' : 'past'];
                    $translation = $this->translate($key, $interpolations, null, $translator);

                    if ($translation !== $key) {
                        return $translation;
                    }
                }
            }

            $aTime = $aUnit ? $handleDeclensions('a_'.$unit, $count) : null;

            $time = $aTime ?: $handleDeclensions($unit, $count) ?: $time;
        }

        $time = [':time' => $time];

        return $this->translate($transId, array_merge($time, $interpolations, $time), null, $translator);
    }

    public function format(string $format): string
    {
        $output = parent::format($format);

        if (!str_contains($format, '%a') || !isset($this->startDate, $this->endDate)) {
            return $output;
        }

        $this->rawInterval ??= $this->startDate->diffAsDateInterval($this->endDate);

        return str_replace('(unknown)', $this->rawInterval->format('%a'), $output);
    }

    /**
     * Format the instance as a string using the forHumans() function.
     *
     * @throws Exception
     *
     * @return string
     */
    public function __toString(): string
    {
        $format = $this->localToStringFormat
            ?? $this->getFactory()->getSettings()['toStringFormat']
            ?? null;

        if (!$format) {
            return $this->forHumans();
        }

        if ($format instanceof Closure) {
            return $format($this);
        }

        return $this->format($format);
    }

    /**
     * Return native DateInterval PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(CarbonInterval::hours(2)->toDateInterval());
     * ```
     *
     * @return DateInterval
     */
    public function toDateInterval(): DateInterval
    {
        return self::castIntervalToClass($this, DateInterval::class);
    }

    /**
     * Convert the interval to a CarbonPeriod.
     *
     * @param DateTimeInterface|string|int ...$params Start date, [end date or recurrences] and optional settings.
     *
     * @return CarbonPeriod
     */
    public function toPeriod(...$params): CarbonPeriod
    {
        if ($this->timezoneSetting) {
            $timeZone = \is_string($this->timezoneSetting)
                ? new DateTimeZone($this->timezoneSetting)
                : $this->timezoneSetting;

            if ($timeZone instanceof DateTimeZone) {
                array_unshift($params, $timeZone);
            }
        }

        $class = ($params[0] ?? null) instanceof DateTime ? CarbonPeriod::class : CarbonPeriodImmutable::class;

        return $class::create($this, ...$params);
    }

    /**
     * Decompose the current interval into
     *
     * @param mixed|int|DateInterval|string|Closure|Unit|null $interval interval or number of the given $unit
     * @param Unit|string|null                                $unit     if specified, $interval must be an integer
     *
     * @return CarbonPeriod
     */
    public function stepBy($interval, Unit|string|null $unit = null): CarbonPeriod
    {
        $this->checkStartAndEnd();
        $start = $this->startDate ?? CarbonImmutable::make('now');
        $end = $this->endDate ?? $start->copy()->add($this);

        try {
            $step = static::make($interval, $unit);
        } catch (InvalidFormatException $exception) {
            if ($unit || (\is_string($interval) ? preg_match('/(\s|\d)/', $interval) : !($interval instanceof Unit))) {
                throw $exception;
            }

            $step = static::make(1, $interval);
        }

        $class = $start instanceof DateTime ? CarbonPeriod::class : CarbonPeriodImmutable::class;

        return $class::create($step, $start, $end);
    }

    /**
     * Invert the interval.
     *
     * @param bool|int $inverted if a parameter is passed, the passed value cast as 1 or 0 is used
     *                           as the new value of the ->invert property.
     *
     * @return $this
     */
    public function invert($inverted = null): static
    {
        $this->invert = (\func_num_args() === 0 ? !$this->invert : $inverted) ? 1 : 0;

        return $this;
    }

    protected function solveNegativeInterval(): static
    {
        if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
            $this->years *= self::NEGATIVE;
            $this->months *= self::NEGATIVE;
            $this->dayz *= self::NEGATIVE;
            $this->hours *= self::NEGATIVE;
            $this->minutes *= self::NEGATIVE;
            $this->seconds *= self::NEGATIVE;
            $this->microseconds *= self::NEGATIVE;
            $this->invert();
        }

        return $this;
    }

    /**
     * Add the passed interval to the current instance.
     *
     * @param string|DateInterval $unit
     * @param int|float           $value
     *
     * @return $this
     */
    public function add($unit, $value = 1): static
    {
        if (is_numeric($unit)) {
            [$value, $unit] = [$unit, $value];
        }

        if (\is_string($unit) && !preg_match('/^\s*-?\d/', $unit)) {
            $unit = "$value $unit";
            $value = 1;
        }

        $interval = static::make($unit);

        if (!$interval) {
            throw new InvalidIntervalException('This type of data cannot be added/subtracted.');
        }

        if ($value !== 1) {
            $interval->times($value);
        }

        $sign = ($this->invert === 1) !== ($interval->invert === 1) ? self::NEGATIVE : self::POSITIVE;
        $this->years += $interval->y * $sign;
        $this->months += $interval->m * $sign;
        $this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
        $this->hours += $interval->h * $sign;
        $this->minutes += $interval->i * $sign;
        $this->seconds += $interval->s * $sign;
        $this->microseconds += $interval->microseconds * $sign;

        $this->solveNegativeInterval();

        return $this;
    }

    /**
     * Subtract the passed interval to the current instance.
     *
     * @param string|DateInterval $unit
     * @param int|float           $value
     *
     * @return $this
     */
    public function sub($unit, $value = 1): static
    {
        if (is_numeric($unit)) {
            [$value, $unit] = [$unit, $value];
        }

        return $this->add($unit, -(float) $value);
    }

    /**
     * Subtract the passed interval to the current instance.
     *
     * @param string|DateInterval $unit
     * @param int|float           $value
     *
     * @return $this
     */
    public function subtract($unit, $value = 1): static
    {
        return $this->sub($unit, $value);
    }

    /**
     * Add given parameters to the current interval.
     *
     * @param int       $years
     * @param int       $months
     * @param int|float $weeks
     * @param int|float $days
     * @param int|float $hours
     * @param int|float $minutes
     * @param int|float $seconds
     * @param int|float $microseconds
     *
     * @return $this
     */
    public function plus(
        $years = 0,
        $months = 0,
        $weeks = 0,
        $days = 0,
        $hours = 0,
        $minutes = 0,
        $seconds = 0,
        $microseconds = 0
    ): static {
        return $this->add("
            $years years $months months $weeks weeks $days days
            $hours hours $minutes minutes $seconds seconds $microseconds microseconds
        ");
    }

    /**
     * Add given parameters to the current interval.
     *
     * @param int       $years
     * @param int       $months
     * @param int|float $weeks
     * @param int|float $days
     * @param int|float $hours
     * @param int|float $minutes
     * @param int|float $seconds
     * @param int|float $microseconds
     *
     * @return $this
     */
    public function minus(
        $years = 0,
        $months = 0,
        $weeks = 0,
        $days = 0,
        $hours = 0,
        $minutes = 0,
        $seconds = 0,
        $microseconds = 0
    ): static {
        return $this->sub("
            $years years $months months $weeks weeks $days days
            $hours hours $minutes minutes $seconds seconds $microseconds microseconds
        ");
    }

    /**
     * Multiply current instance given number of times. times() is naive, it multiplies each unit
     * (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
     * separately for each unit.
     *
     * Use times() when you want a fast and approximated calculation that does not cascade units.
     *
     * For a precise and cascaded calculation,
     *
     * @see multiply()
     *
     * @param float|int $factor
     *
     * @return $this
     */
    public function times($factor): static
    {
        if ($factor < 0) {
            $this->invert = $this->invert ? 0 : 1;
            $factor = -$factor;
        }

        $this->years = (int) round($this->years * $factor);
        $this->months = (int) round($this->months * $factor);
        $this->dayz = (int) round($this->dayz * $factor);
        $this->hours = (int) round($this->hours * $factor);
        $this->minutes = (int) round($this->minutes * $factor);
        $this->seconds = (int) round($this->seconds * $factor);
        $this->microseconds = (int) round($this->microseconds * $factor);

        return $this;
    }

    /**
     * Divide current instance by a given divider. shares() is naive, it divides each unit separately
     * and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
     * and 7 minutes.
     *
     * Use shares() when you want a fast and approximated calculation that does not cascade units.
     *
     * For a precise and cascaded calculation,
     *
     * @see divide()
     *
     * @param float|int $divider
     *
     * @return $this
     */
    public function shares($divider): static
    {
        return $this->times(1 / $divider);
    }

    protected function copyProperties(self $interval, $ignoreSign = false): static
    {
        $this->years = $interval->years;
        $this->months = $interval->months;
        $this->dayz = $interval->dayz;
        $this->hours = $interval->hours;
        $this->minutes = $interval->minutes;
        $this->seconds = $interval->seconds;
        $this->microseconds = $interval->microseconds;

        if (!$ignoreSign) {
            $this->invert = $interval->invert;
        }

        return $this;
    }

    /**
     * Multiply and cascade current instance by a given factor.
     *
     * @param float|int $factor
     *
     * @return $this
     */
    public function multiply($factor): static
    {
        if ($factor < 0) {
            $this->invert = $this->invert ? 0 : 1;
            $factor = -$factor;
        }

        $yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision

        if ($yearPart) {
            $this->years -= $yearPart / $factor;
        }

        return $this->copyProperties(
            static::create($yearPart)
                ->microseconds(abs($this->totalMicroseconds) * $factor)
                ->cascade(),
            true,
        );
    }

    /**
     * Divide and cascade current instance by a given divider.
     *
     * @param float|int $divider
     *
     * @return $this
     */
    public function divide($divider): static
    {
        return $this->multiply(1 / $divider);
    }

    /**
     * Get the interval_spec string of a date interval.
     *
     * @param DateInterval $interval
     *
     * @return string
     */
    public static function getDateIntervalSpec(DateInterval $interval, bool $microseconds = false, array $skip = []): string
    {
        $date = array_filter([
            static::PERIOD_YEARS => abs($interval->y),
            static::PERIOD_MONTHS => abs($interval->m),
            static::PERIOD_DAYS => abs($interval->d),
        ]);

        $skip = array_map([Unit::class, 'toNameIfUnit'], $skip);

        if (
            $interval->days >= CarbonInterface::DAYS_PER_WEEK * CarbonInterface::WEEKS_PER_MONTH &&
            (!isset($date[static::PERIOD_YEARS]) || \count(array_intersect(['y', 'year', 'years'], $skip))) &&
            (!isset($date[static::PERIOD_MONTHS]) || \count(array_intersect(['m', 'month', 'months'], $skip)))
        ) {
            $date = [
                static::PERIOD_DAYS => abs($interval->days),
            ];
        }

        $seconds = abs($interval->s);
        if ($microseconds && $interval->f > 0) {
            $seconds = \sprintf('%d.%06d', $seconds, abs($interval->f) * 1000000);
        }

        $time = array_filter([
            static::PERIOD_HOURS => abs($interval->h),
            static::PERIOD_MINUTES => abs($interval->i),
            static::PERIOD_SECONDS => $seconds,
        ]);

        $specString = static::PERIOD_PREFIX;

        foreach ($date as $key => $value) {
            $specString .= $value.$key;
        }

        if (\count($time) > 0) {
            $specString .= static::PERIOD_TIME_PREFIX;
            foreach ($time as $key => $value) {
                $specString .= $value.$key;
            }
        }

        return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
    }

    /**
     * Get the interval_spec string.
     *
     * @return string
     */
    public function spec(bool $microseconds = false): string
    {
        return static::getDateIntervalSpec($this, $microseconds);
    }

    /**
     * Comparing 2 date intervals.
     *
     * @param DateInterval $first
     * @param DateInterval $second
     *
     * @return int 0, 1 or -1
     */
    public static function compareDateIntervals(DateInterval $first, DateInterval $second): int
    {
        $current = Carbon::now();
        $passed = $current->avoidMutation()->add($second);
        $current->add($first);

        return $current <=> $passed;
    }

    /**
     * Comparing with passed interval.
     *
     * @param DateInterval $interval
     *
     * @return int 0, 1 or -1
     */
    public function compare(DateInterval $interval): int
    {
        return static::compareDateIntervals($this, $interval);
    }

    /**
     * Convert overflowed values into bigger units.
     *
     * @return $this
     */
    public function cascade(): static
    {
        return $this->doCascade(false);
    }

    public function hasNegativeValues(): bool
    {
        foreach ($this->toArray() as $value) {
            if ($value < 0) {
                return true;
            }
        }

        return false;
    }

    public function hasPositiveValues(): bool
    {
        foreach ($this->toArray() as $value) {
            if ($value > 0) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get amount of given unit equivalent to the interval.
     *
     * @param string $unit
     *
     * @throws UnknownUnitException|UnitNotConfiguredException
     *
     * @return float
     */
    public function total(string $unit): float
    {
        $realUnit = $unit = strtolower($unit);

        if (\in_array($unit, ['days', 'weeks'])) {
            $realUnit = 'dayz';
        } elseif (!\in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
            throw new UnknownUnitException($unit);
        }

        $this->checkStartAndEnd();

        if ($this->startDate && $this->endDate) {
            $diff = $this->startDate->diffInUnit($unit, $this->endDate);

            return $this->absolute ? abs($diff) : $diff;
        }

        $result = 0;
        $cumulativeFactor = 0;
        $unitFound = false;
        $factors = self::getFlipCascadeFactors();
        $daysPerWeek = (int) static::getDaysPerWeek();

        $values = [
            'years' => $this->years,
            'months' => $this->months,
            'weeks' => (int) ($this->d / $daysPerWeek),
            'dayz' => fmod($this->d, $daysPerWeek),
            'hours' => $this->hours,
            'minutes' => $this->minutes,
            'seconds' => $this->seconds,
            'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
            'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND,
        ];

        if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {
            $values['dayz'] += $values['weeks'] * $daysPerWeek;
            $values['weeks'] = 0;
        }

        foreach ($factors as $source => [$target, $factor]) {
            if ($source === $realUnit) {
                $unitFound = true;
                $value = $values[$source];
                $result += $value;
                $cumulativeFactor = 1;
            }

            if ($factor === false) {
                if ($unitFound) {
                    break;
                }

                $result = 0;
                $cumulativeFactor = 0;

                continue;
            }

            if ($target === $realUnit) {
                $unitFound = true;
            }

            if ($cumulativeFactor) {
                $cumulativeFactor *= $factor;
                $result += $values[$target] * $cumulativeFactor;

                continue;
            }

            $value = $values[$source];

            $result = ($result + $value) / $factor;
        }

        if (isset($target) && !$cumulativeFactor) {
            $result += $values[$target];
        }

        if (!$unitFound) {
            throw new UnitNotConfiguredException($unit);
        }

        if ($this->invert) {
            $result *= self::NEGATIVE;
        }

        if ($unit === 'weeks') {
            $result /= $daysPerWeek;
        }

        // Cast as int numbers with no decimal part
        return fmod($result, 1) === 0.0 ? (int) $result : $result;
    }

    /**
     * Determines if the instance is equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @see equalTo()
     *
     * @return bool
     */
    public function eq($interval): bool
    {
        return $this->equalTo($interval);
    }

    /**
     * Determines if the instance is equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @return bool
     */
    public function equalTo($interval): bool
    {
        $interval = $this->resolveInterval($interval);

        if ($interval === null) {
            return false;
        }

        $step = $this->getStep();

        if ($step) {
            return $step === $interval->getStep();
        }

        if ($this->isEmpty()) {
            return $interval->isEmpty();
        }

        $cascadedInterval = $this->copy()->cascade();
        $comparedInterval = $interval->copy()->cascade();

        return $cascadedInterval->invert === $comparedInterval->invert &&
            $cascadedInterval->getNonZeroValues() === $comparedInterval->getNonZeroValues();
    }

    /**
     * Determines if the instance is not equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @see notEqualTo()
     *
     * @return bool
     */
    public function ne($interval): bool
    {
        return $this->notEqualTo($interval);
    }

    /**
     * Determines if the instance is not equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @return bool
     */
    public function notEqualTo($interval): bool
    {
        return !$this->eq($interval);
    }

    /**
     * Determines if the instance is greater (longer) than another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @see greaterThan()
     *
     * @return bool
     */
    public function gt($interval): bool
    {
        return $this->greaterThan($interval);
    }

    /**
     * Determines if the instance is greater (longer) than another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @return bool
     */
    public function greaterThan($interval): bool
    {
        $interval = $this->resolveInterval($interval);

        return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
    }

    /**
     * Determines if the instance is greater (longer) than or equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @see greaterThanOrEqualTo()
     *
     * @return bool
     */
    public function gte($interval): bool
    {
        return $this->greaterThanOrEqualTo($interval);
    }

    /**
     * Determines if the instance is greater (longer) than or equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @return bool
     */
    public function greaterThanOrEqualTo($interval): bool
    {
        return $this->greaterThan($interval) || $this->equalTo($interval);
    }

    /**
     * Determines if the instance is less (shorter) than another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @see lessThan()
     *
     * @return bool
     */
    public function lt($interval): bool
    {
        return $this->lessThan($interval);
    }

    /**
     * Determines if the instance is less (shorter) than another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @return bool
     */
    public function lessThan($interval): bool
    {
        $interval = $this->resolveInterval($interval);

        return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
    }

    /**
     * Determines if the instance is less (shorter) than or equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @see lessThanOrEqualTo()
     *
     * @return bool
     */
    public function lte($interval): bool
    {
        return $this->lessThanOrEqualTo($interval);
    }

    /**
     * Determines if the instance is less (shorter) than or equal to another
     *
     * @param CarbonInterval|DateInterval|mixed $interval
     *
     * @return bool
     */
    public function lessThanOrEqualTo($interval): bool
    {
        return $this->lessThan($interval) || $this->equalTo($interval);
    }

    /**
     * Determines if the instance is between two others.
     *
     * The third argument allow you to specify if bounds are included or not (true by default)
     * but for when you including/excluding bounds may produce different results in your application,
     * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
     *
     * @example
     * ```
     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
     * CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
     * ```
     *
     * @param CarbonInterval|DateInterval|mixed $interval1
     * @param CarbonInterval|DateInterval|mixed $interval2
     * @param bool                              $equal     Indicates if an equal to comparison should be done
     *
     * @return bool
     */
    public function between($interval1, $interval2, bool $equal = true): bool
    {
        return $equal
            ? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
            : $this->greaterThan($interval1) && $this->lessThan($interval2);
    }

    /**
     * Determines if the instance is between two others, bounds excluded.
     *
     * @example
     * ```
     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // true
     * ```
     *
     * @param CarbonInterval|DateInterval|mixed $interval1
     * @param CarbonInterval|DateInterval|mixed $interval2
     *
     * @return bool
     */
    public function betweenIncluded($interval1, $interval2): bool
    {
        return $this->between($interval1, $interval2, true);
    }

    /**
     * Determines if the instance is between two others, bounds excluded.
     *
     * @example
     * ```
     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
     * CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
     * ```
     *
     * @param CarbonInterval|DateInterval|mixed $interval1
     * @param CarbonInterval|DateInterval|mixed $interval2
     *
     * @return bool
     */
    public function betweenExcluded($interval1, $interval2): bool
    {
        return $this->between($interval1, $interval2, false);
    }

    /**
     * Determines if the instance is between two others
     *
     * @example
     * ```
     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
     * CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
     * ```
     *
     * @param CarbonInterval|DateInterval|mixed $interval1
     * @param CarbonInterval|DateInterval|mixed $interval2
     * @param bool                              $equal     Indicates if an equal to comparison should be done
     *
     * @return bool
     */
    public function isBetween($interval1, $interval2, bool $equal = true): bool
    {
        return $this->between($interval1, $interval2, $equal);
    }

    /**
     * Round the current instance at the given unit with given precision if specified and the given function.
     *
     * @throws Exception
     */
    public function roundUnit(string $unit, DateInterval|string|int|float $precision = 1, string $function = 'round'): static
    {
        if (static::getCascadeFactors() !== static::getDefaultCascadeFactors()) {
            $value = $function($this->total($unit) / $precision) * $precision;
            $inverted = $value < 0;

            return $this->copyProperties(self::fromString(
                number_format(abs($value), 12, '.', '').' '.$unit
            )->invert($inverted)->cascade());
        }

        $base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC')
            ->roundUnit($unit, $precision, $function);
        $next = $base->add($this);
        $inverted = $next < $base;

        if ($inverted) {
            $next = $base->sub($this);
        }

        $this->copyProperties(
            $next
                ->roundUnit($unit, $precision, $function)
                ->diff($base),
        );

        return $this->invert($inverted);
    }

    /**
     * Truncate the current instance at the given unit with given precision if specified.
     *
     * @param string                             $unit
     * @param float|int|string|DateInterval|null $precision
     *
     * @throws Exception
     *
     * @return $this
     */
    public function floorUnit(string $unit, $precision = 1): static
    {
        return $this->roundUnit($unit, $precision, 'floor');
    }

    /**
     * Ceil the current instance at the given unit with given precision if specified.
     *
     * @param string                             $unit
     * @param float|int|string|DateInterval|null $precision
     *
     * @throws Exception
     *
     * @return $this
     */
    public function ceilUnit(string $unit, $precision = 1): static
    {
        return $this->roundUnit($unit, $precision, 'ceil');
    }

    /**
     * Round the current instance second with given precision if specified.
     *
     * @param float|int|string|DateInterval|null $precision
     * @param string                             $function
     *
     * @throws Exception
     *
     * @return $this
     */
    public function round($precision = 1, string $function = 'round'): static
    {
        return $this->roundWith($precision, $function);
    }

    /**
     * Round the current instance second with given precision if specified.
     *
     * @throws Exception
     *
     * @return $this
     */
    public function floor(DateInterval|string|float|int $precision = 1): static
    {
        return $this->round($precision, 'floor');
    }

    /**
     * Ceil the current instance second with given precision if specified.
     *
     * @throws Exception
     *
     * @return $this
     */
    public function ceil(DateInterval|string|float|int $precision = 1): static
    {
        return $this->round($precision, 'ceil');
    }

    public function __unserialize(array $data): void
    {
        $properties = array_combine(
            array_map(
                static fn (mixed $key) => \is_string($key)
                    ? str_replace('tzName', 'timezoneSetting', $key)
                    : $key,
                array_keys($data),
            ),
            $data,
        );

        if (method_exists(parent::class, '__unserialize')) {
            // PHP >= 8.2
            parent::__unserialize($properties);

            return;
        }

        // PHP <= 8.1
        // @codeCoverageIgnoreStart
        $properties = array_combine(
            array_map(
                static fn (string $property) => preg_replace('/^\0.+\0/', '', $property),
                array_keys($data),
            ),
            $data,
        );
        $localStrictMode = $this->localStrictModeEnabled;
        $this->localStrictModeEnabled = false;
        $days = $properties['days'] ?? false;
        $this->days = $days === false ? false : (int) $days;
        $this->y = (int) ($properties['y'] ?? 0);
        $this->m = (int) ($properties['m'] ?? 0);
        $this->d = (int) ($properties['d'] ?? 0);
        $this->h = (int) ($properties['h'] ?? 0);
        $this->i = (int) ($properties['i'] ?? 0);
        $this->s = (int) ($properties['s'] ?? 0);
        $this->f = (float) ($properties['f'] ?? 0.0);
        // @phpstan-ignore-next-line
        $this->weekday = (int) ($properties['weekday'] ?? 0);
        // @phpstan-ignore-next-line
        $this->weekday_behavior = (int) ($properties['weekday_behavior'] ?? 0);
        // @phpstan-ignore-next-line
        $this->first_last_day_of = (int) ($properties['first_last_day_of'] ?? 0);
        $this->invert = (int) ($properties['invert'] ?? 0);
        // @phpstan-ignore-next-line
        $this->special_type = (int) ($properties['special_type'] ?? 0);
        // @phpstan-ignore-next-line
        $this->special_amount = (int) ($properties['special_amount'] ?? 0);
        // @phpstan-ignore-next-line
        $this->have_weekday_relative = (int) ($properties['have_weekday_relative'] ?? 0);
        // @phpstan-ignore-next-line
        $this->have_special_relative = (int) ($properties['have_special_relative'] ?? 0);
        parent::__construct(self::getDateIntervalSpec($this));

        foreach ($properties as $property => $value) {
            if ($property === 'localStrictModeEnabled') {
                continue;
            }

            $this->$property = $value;
        }

        $this->localStrictModeEnabled = $properties['localStrictModeEnabled'] ?? $localStrictMode;
        // @codeCoverageIgnoreEnd
    }

    /**
     * @template T
     *
     * @param T     $interval
     * @param mixed $original
     *
     * @return T
     */
    private static function withOriginal(mixed $interval, mixed $original): mixed
    {
        if ($interval instanceof self) {
            $interval->originalInput = $original;
        }

        return $interval;
    }

    private static function standardizeUnit(string $unit): string
    {
        $unit = rtrim($unit, 'sz').'s';

        return $unit === 'days' ? 'dayz' : $unit;
    }

    private static function getFlipCascadeFactors(): array
    {
        if (!self::$flipCascadeFactors) {
            self::$flipCascadeFactors = [];

            foreach (self::getCascadeFactors() as $to => [$factor, $from]) {
                self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
            }
        }

        return self::$flipCascadeFactors;
    }

    /**
     * @template T of DateInterval
     *
     * @param DateInterval $interval
     *
     * @psalm-param class-string<T> $className
     *
     * @return T
     */
    private static function castIntervalToClass(DateInterval $interval, string $className, array $skip = []): object
    {
        $mainClass = DateInterval::class;

        if (!is_a($className, $mainClass, true)) {
            throw new InvalidCastException("$className is not a sub-class of $mainClass.");
        }

        $microseconds = $interval->f;
        $instance = self::buildInstance($interval, $className, $skip);

        if ($instance instanceof self) {
            $instance->originalInput = $interval;
        }

        if ($microseconds) {
            $instance->f = $microseconds;
        }

        if ($interval instanceof self && is_a($className, self::class, true)) {
            self::copyStep($interval, $instance);
        }

        self::copyNegativeUnits($interval, $instance);

        return self::withOriginal($instance, $interval);
    }

    /**
     * @template T of DateInterval
     *
     * @param DateInterval $interval
     *
     * @psalm-param class-string<T> $className
     *
     * @return T
     */
    private static function buildInstance(
        DateInterval $interval,
        string $className,
        array $skip = [],
    ): object {
        $serialization = self::buildSerializationString($interval, $className, $skip);

        return match ($serialization) {
            null => new $className(static::getDateIntervalSpec($interval, false, $skip)),
            default => unserialize($serialization),
        };
    }

    /**
     * As demonstrated by rlanvin (https://github.com/rlanvin) in
     * https://github.com/briannesbitt/Carbon/issues/3018#issuecomment-2888538438
     *
     * Modifying the output of serialize() to change the class name and unserializing
     * the tweaked string allows creating new interval instances where the ->days
     * property can be set. It's not possible neither with `new` nto with `__set_state`.
     *
     * It has a non-negligible performance cost, so we'll use this method only if
     * $interval->days !== false.
     */
    private static function buildSerializationString(
        DateInterval $interval,
        string $className,
        array $skip = [],
    ): ?string {
        if ($interval->days === false || PHP_VERSION_ID < 8_02_00 || $skip !== []) {
            return null;
        }

        // De-enhance CarbonInterval objects to be serializable back to DateInterval
        if ($interval instanceof self && !is_a($className, self::class, true)) {
            $interval = clone $interval;
            unset($interval->timezoneSetting);
            unset($interval->originalInput);
            unset($interval->startDate);
            unset($interval->endDate);
            unset($interval->rawInterval);
            unset($interval->absolute);
            unset($interval->initialValues);
            unset($interval->clock);
            unset($interval->step);
            unset($interval->localMonthsOverflow);
            unset($interval->localYearsOverflow);
            unset($interval->localStrictModeEnabled);
            unset($interval->localHumanDiffOptions);
            unset($interval->localToStringFormat);
            unset($interval->localSerializer);
            unset($interval->localMacros);
            unset($interval->localGenericMacros);
            unset($interval->localFormatFunction);
            unset($interval->localTranslator);
        }

        $serialization = serialize($interval);
        $inputClass = $interval::class;
        $expectedStart = 'O:'.\strlen($inputClass).':"'.$inputClass.'":';

        if (!str_starts_with($serialization, $expectedStart)) {
            return null; // @codeCoverageIgnore
        }

        return 'O:'.\strlen($className).':"'.$className.'":'.substr($serialization, \strlen($expectedStart));
    }

    private static function copyStep(self $from, self $to): void
    {
        $to->setStep($from->getStep());
    }

    private static function copyNegativeUnits(DateInterval $from, DateInterval $to): void
    {
        $to->invert = $from->invert;

        foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
            if ($from->$unit < 0) {
                self::setIntervalUnit($to, $unit, $to->$unit * self::NEGATIVE);
            }
        }
    }

    private function invertCascade(array $values): static
    {
        return $this->set(array_map(function ($value) {
            return -$value;
        }, $values))->doCascade(true)->invert();
    }

    private function doCascade(bool $deep): static
    {
        $originalData = $this->toArray();
        $originalData['milliseconds'] = (int) ($originalData['microseconds'] / static::getMicrosecondsPerMillisecond());
        $originalData['microseconds'] = $originalData['microseconds'] % static::getMicrosecondsPerMillisecond();
        $originalData['weeks'] = (int) ($this->d / static::getDaysPerWeek());
        $originalData['daysExcludeWeeks'] = fmod($this->d, static::getDaysPerWeek());
        unset($originalData['days']);
        $newData = $originalData;
        $previous = [];

        foreach (self::getFlipCascadeFactors() as $source => [$target, $factor]) {
            foreach (['source', 'target'] as $key) {
                if ($$key === 'dayz') {
                    $$key = 'daysExcludeWeeks';
                }
            }

            $value = $newData[$source];
            $modulo = fmod($factor + fmod($value, $factor), $factor);
            $newData[$source] = $modulo;
            $newData[$target] += ($value - $modulo) / $factor;

            $decimalPart = fmod($newData[$source], 1);

            if ($decimalPart !== 0.0) {
                $unit = $source;

                foreach ($previous as [$subUnit, $subFactor]) {
                    $newData[$unit] -= $decimalPart;
                    $newData[$subUnit] += $decimalPart * $subFactor;
                    $decimalPart = fmod($newData[$subUnit], 1);

                    if ($decimalPart === 0.0) {
                        break;
                    }

                    $unit = $subUnit;
                }
            }

            array_unshift($previous, [$source, $factor]);
        }

        $positive = null;

        if (!$deep) {
            foreach ($newData as $value) {
                if ($value) {
                    if ($positive === null) {
                        $positive = ($value > 0);

                        continue;
                    }

                    if (($value > 0) !== $positive) {
                        return $this->invertCascade($originalData)
                            ->solveNegativeInterval();
                    }
                }
            }
        }

        return $this->set($newData)
            ->solveNegativeInterval();
    }

    private function needsDeclension(string $mode, int $index, int $parts): bool
    {
        return match ($mode) {
            'last' => $index === $parts - 1,
            default => true,
        };
    }

    private function checkIntegerValue(string $name, mixed $value): void
    {
        if (\is_int($value)) {
            return;
        }

        $this->assertSafeForInteger($name, $value);

        if (\is_float($value) && (((float) (int) $value) === $value)) {
            return;
        }

        if (!self::$floatSettersEnabled) {
            $type = \gettype($value);
            @trigger_error(
                "Since 2.70.0, it's deprecated to pass $type value for $name.\n".
                "It's truncated when stored as an integer interval unit.\n".
                "From 3.0.0, decimal part will no longer be truncated and will be cascaded to smaller units.\n".
                "- To maintain the current behavior, use explicit cast: $name((int) \$value)\n".
                "- To adopt the new behavior globally, call CarbonInterval::enableFloatSetters()\n",
                \E_USER_DEPRECATED,
            );
        }
    }

    /**
     * Throw an exception if precision loss when storing the given value as an integer would be >= 1.0.
     */
    private function assertSafeForInteger(string $name, mixed $value): void
    {
        if ($value && !\is_int($value) && ($value >= 0x7fffffffffffffff || $value <= -0x7fffffffffffffff)) {
            throw new OutOfRangeException($name, -0x7fffffffffffffff, 0x7fffffffffffffff, $value);
        }
    }

    private function handleDecimalPart(string $unit, mixed $value, mixed $integerValue): void
    {
        if (self::$floatSettersEnabled) {
            $floatValue = (float) $value;
            $base = (float) $integerValue;

            if ($floatValue === $base) {
                return;
            }

            $units = [
                'y' => 'year',
                'm' => 'month',
                'd' => 'day',
                'h' => 'hour',
                'i' => 'minute',
                's' => 'second',
            ];
            $upper = true;

            foreach ($units as $property => $name) {
                if ($name === $unit) {
                    $upper = false;

                    continue;
                }

                if (!$upper && $this->$property !== 0) {
                    throw new RuntimeException(
                        "You cannot set $unit to a float value as $name would be overridden, ".
                        'set it first to 0 explicitly if you really want to erase its value'
                    );
                }
            }

            $this->add($unit, $floatValue - $base);
        }
    }

    private function getInnerValues(): array
    {
        return [$this->y, $this->m, $this->d, $this->h, $this->i, $this->s, $this->f, $this->invert, $this->days];
    }

    private function checkStartAndEnd(): void
    {
        if (
            $this->initialValues !== null
            && ($this->startDate !== null || $this->endDate !== null)
            && $this->initialValues !== $this->getInnerValues()
        ) {
            $this->absolute = false;
            $this->startDate = null;
            $this->endDate = null;
            $this->rawInterval = null;
        }
    }

    /** @return $this */
    private function setSetting(string $setting, mixed $value): self
    {
        switch ($setting) {
            case 'timezoneSetting':
                return $value === null ? $this : $this->setTimezone($value);

            case 'step':
                $this->setStep($value);

                return $this;

            case 'localMonthsOverflow':
                return $value === null ? $this : $this->settings(['monthOverflow' => $value]);

            case 'localYearsOverflow':
                return $value === null ? $this : $this->settings(['yearOverflow' => $value]);

            case 'localStrictModeEnabled':
            case 'localHumanDiffOptions':
            case 'localToStringFormat':
            case 'localSerializer':
            case 'localMacros':
            case 'localGenericMacros':
            case 'localFormatFunction':
            case 'localTranslator':
                $this->$setting = $value;

                return $this;

            default:
                // Drop unknown settings
                return $this;
        }
    }

    private static function incrementUnit(DateInterval $instance, string $unit, int $value): void
    {
        if ($value === 0) {
            return;
        }

        // @codeCoverageIgnoreStart
        if (PHP_VERSION_ID !== 8_03_20) {
            $instance->$unit += $value;

            return;
        }

        // Cannot use +=, nor set to a negative value directly as it segfaults in PHP 8.3.20
        self::setIntervalUnit($instance, $unit, ($instance->$unit ?? 0) + $value);
        // @codeCoverageIgnoreEnd
    }

    /** @codeCoverageIgnore */
    private static function setIntervalUnit(DateInterval $instance, string $unit, mixed $value): void
    {
        switch ($unit) {
            case 'y':
                $instance->y = $value;

                break;

            case 'm':
                $instance->m = $value;

                break;

            case 'd':
                $instance->d = $value;

                break;

            case 'h':
                $instance->h = $value;

                break;

            case 'i':
                $instance->i = $value;

                break;

            case 's':
                $instance->s = $value;

                break;

            default:
                $instance->$unit = $value;
        }
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Cli;

class Invoker
{
    public const CLI_CLASS_NAME = 'Carbon\\Cli';

    protected function runWithCli(string $className, array $parameters): bool
    {
        $cli = new $className();

        return $cli(...$parameters);
    }

    public function __invoke(...$parameters): bool
    {
        if (class_exists(self::CLI_CLASS_NAME)) {
            return $this->runWithCli(self::CLI_CLASS_NAME, $parameters);
        }

        $function = (($parameters[1] ?? '') === 'install' ? ($parameters[2] ?? null) : null) ?: 'shell_exec';
        $function('composer require carbon-cli/carbon-cli --no-interaction');

        echo 'Installation succeeded.';

        return true;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Laravel;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Events\Dispatcher;
use Illuminate\Events\EventDispatcher;
use Illuminate\Support\Carbon as IlluminateCarbon;
use Illuminate\Support\Facades\Date;
use Throwable;

class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
    /** @var callable|null */
    protected $appGetter = null;

    /** @var callable|null */
    protected $localeGetter = null;

    /** @var callable|null */
    protected $fallbackLocaleGetter = null;

    public function setAppGetter(?callable $appGetter): void
    {
        $this->appGetter = $appGetter;
    }

    public function setLocaleGetter(?callable $localeGetter): void
    {
        $this->localeGetter = $localeGetter;
    }

    public function setFallbackLocaleGetter(?callable $fallbackLocaleGetter): void
    {
        $this->fallbackLocaleGetter = $fallbackLocaleGetter;
    }

    public function boot()
    {
        $this->updateLocale();
        $this->updateFallbackLocale();

        if (!$this->app->bound('events')) {
            return;
        }

        $service = $this;
        $events = $this->app['events'];

        if ($this->isEventDispatcher($events)) {
            $events->listen(class_exists('Illuminate\Foundation\Events\LocaleUpdated') ? 'Illuminate\Foundation\Events\LocaleUpdated' : 'locale.changed', function () use ($service) {
                $service->updateLocale();
            });
        }
    }

    public function updateLocale()
    {
        $locale = $this->getLocale();

        if ($locale === null) {
            return;
        }

        Carbon::setLocale($locale);
        CarbonImmutable::setLocale($locale);
        CarbonPeriod::setLocale($locale);
        CarbonInterval::setLocale($locale);

        if (class_exists(IlluminateCarbon::class)) {
            IlluminateCarbon::setLocale($locale);
        }

        if (class_exists(Date::class)) {
            try {
                $root = Date::getFacadeRoot();
                $root->setLocale($locale);
            } catch (Throwable) {
                // Non Carbon class in use in Date facade
            }
        }
    }

    public function updateFallbackLocale()
    {
        $locale = $this->getFallbackLocale();

        if ($locale === null) {
            return;
        }

        Carbon::setFallbackLocale($locale);
        CarbonImmutable::setFallbackLocale($locale);
        CarbonPeriod::setFallbackLocale($locale);
        CarbonInterval::setFallbackLocale($locale);

        if (class_exists(IlluminateCarbon::class) && method_exists(IlluminateCarbon::class, 'setFallbackLocale')) {
            IlluminateCarbon::setFallbackLocale($locale);
        }

        if (class_exists(Date::class)) {
            try {
                $root = Date::getFacadeRoot();
                $root->setFallbackLocale($locale);
            } catch (Throwable) { // @codeCoverageIgnore
                // Non Carbon class in use in Date facade
            }
        }
    }

    public function register()
    {
        // Needed for Laravel < 5.3 compatibility
    }

    protected function getLocale()
    {
        if ($this->localeGetter) {
            return ($this->localeGetter)();
        }

        $app = $this->getApp();
        $app = $app && method_exists($app, 'getLocale')
            ? $app
            : $this->getGlobalApp('translator');

        return $app ? $app->getLocale() : null;
    }

    protected function getFallbackLocale()
    {
        if ($this->fallbackLocaleGetter) {
            return ($this->fallbackLocaleGetter)();
        }

        $app = $this->getApp();

        return $app && method_exists($app, 'getFallbackLocale')
            ? $app->getFallbackLocale()
            : $this->getGlobalApp('translator')?->getFallback();
    }

    protected function getApp()
    {
        if ($this->appGetter) {
            return ($this->appGetter)();
        }

        return $this->app ?? $this->getGlobalApp();
    }

    protected function getGlobalApp(...$args)
    {
        return \function_exists('app') ? \app(...$args) : null;
    }

    protected function isEventDispatcher($instance)
    {
        return $instance instanceof EventDispatcher
            || $instance instanceof Dispatcher
            || $instance instanceof DispatcherContract;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use ReflectionMethod;
use Symfony\Component\Translation;
use Symfony\Contracts\Translation\TranslatorInterface;

$transMethod = new ReflectionMethod(
    class_exists(TranslatorInterface::class)
        ? TranslatorInterface::class
        : Translation\Translator::class,
    'trans',
);

require $transMethod->hasReturnType()
    ? __DIR__.'/../../lazy/Carbon/TranslatorStrongType.php'
    : __DIR__.'/../../lazy/Carbon/TranslatorWeakType.php';

class Translator extends LazyTranslator
{
    // Proxy dynamically loaded LazyTranslator in a static way
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Closure;
use DateTimeInterface;
use DateTimeZone;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\Clock\NativeClock;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * A factory to generate CarbonImmutable instances with common settings.
 *
 * <autodoc generated by `composer phpdoc`>
 *
 * @method bool                canBeCreatedFromFormat(?string $date, string $format)                                                                                Checks if the (date)time string is in a given format and valid to create a
 *                                                                                                                                                                  new instance.
 * @method ?CarbonImmutable    create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null)                                       Create a new Carbon instance from a specific date and time.
 *                                                                                                                                                                  If any of $year, $month or $day are set to null their now() values will
 *                                                                                                                                                                  be used.
 *                                                                                                                                                                  If $hour is null it will be set to its now() value and the default
 *                                                                                                                                                                  values for $minute and $second will be their now() values.
 *                                                                                                                                                                  If $hour is not null then the default values for $minute and $second
 *                                                                                                                                                                  will be 0.
 * @method CarbonImmutable     createFromDate($year = null, $month = null, $day = null, $timezone = null)                                                           Create a Carbon instance from just a date. The time portion is set to now.
 * @method ?CarbonImmutable    createFromFormat($format, $time, $timezone = null)                                                                                   Create a Carbon instance from a specific format.
 * @method ?CarbonImmutable    createFromIsoFormat(string $format, string $time, $timezone = null, ?string $locale = 'en', ?TranslatorInterface $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
 * @method ?CarbonImmutable    createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null)                                               Create a Carbon instance from a specific format and a string in a given language.
 * @method ?CarbonImmutable    createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null)                                            Create a Carbon instance from a specific ISO format and a string in a given language.
 * @method CarbonImmutable     createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null)                                                                Create a Carbon instance from just a time. The date portion is set to today.
 * @method CarbonImmutable     createFromTimeString(string $time, DateTimeZone|string|int|null $timezone = null)                                                    Create a Carbon instance from a time string. The date portion is set to today.
 * @method CarbonImmutable     createFromTimestamp(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null)                                      Create a Carbon instance from a timestamp and set the timezone (UTC by default).
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method CarbonImmutable     createFromTimestampMs(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null)                                    Create a Carbon instance from a timestamp in milliseconds.
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method CarbonImmutable     createFromTimestampMsUTC($timestamp)                                                                                                 Create a Carbon instance from a timestamp in milliseconds.
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method CarbonImmutable     createFromTimestampUTC(string|int|float $timestamp)                                                                                  Create a Carbon instance from a timestamp keeping the timezone to UTC.
 *                                                                                                                                                                  Timestamp input can be given as int, float or a string containing one or more numbers.
 * @method CarbonImmutable     createMidnightDate($year = null, $month = null, $day = null, $timezone = null)                                                       Create a Carbon instance from just a date. The time portion is set to midnight.
 * @method ?CarbonImmutable    createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null)                 Create a new safe Carbon instance from a specific date and time.
 *                                                                                                                                                                  If any of $year, $month or $day are set to null their now() values will
 *                                                                                                                                                                  be used.
 *                                                                                                                                                                  If $hour is null it will be set to its now() value and the default
 *                                                                                                                                                                  values for $minute and $second will be their now() values.
 *                                                                                                                                                                  If $hour is not null then the default values for $minute and $second
 *                                                                                                                                                                  will be 0.
 *                                                                                                                                                                  If one of the set values is not valid, an InvalidDateException
 *                                                                                                                                                                  will be thrown.
 * @method CarbonImmutable     createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null)   Create a new Carbon instance from a specific date and time using strict validation.
 * @method mixed               executeWithLocale(string $locale, callable $func)                                                                                    Set the current locale to the given, execute the passed function, reset the locale to previous one,
 *                                                                                                                                                                  then return the result of the closure (or null if the closure was void).
 * @method CarbonImmutable     fromSerialized($value, array $options = [])                                                                                          Create an instance from a serialized string.
 *                                                                                                                                                                  If $value is not from a trusted source, consider using the allowed_classes option to limit
 *                                                                                                                                                                  the types of objects that can be built, for instance:
 * @method array               getAvailableLocales()                                                                                                                Returns the list of internally available locales and already loaded custom locales.
 *                                                                                                                                                                  (It will ignore custom translator dynamic loading.)
 * @method Language[]          getAvailableLocalesInfo()                                                                                                            Returns list of Language object for each available locale. This object allow you to get the ISO name, native
 *                                                                                                                                                                  name, region and variant of the locale.
 * @method array               getDays()                                                                                                                            Get the days of the week.
 * @method ?string             getFallbackLocale()                                                                                                                  Get the fallback locale.
 * @method array               getFormatsToIsoReplacements()                                                                                                        List of replacements from date() format to isoFormat().
 * @method array               getIsoUnits()                                                                                                                        Returns list of locale units for ISO formatting.
 * @method array|false         getLastErrors()                                                                                                                      {@inheritdoc}
 * @method string              getLocale()                                                                                                                          Get the current translator locale.
 * @method int                 getMidDayAt()                                                                                                                        get midday/noon hour
 * @method string              getTimeFormatByPrecision(string $unitPrecision)                                                                                      Return a format from H:i to H:i:s.u according to given unit precision.
 * @method string|Closure|null getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)                                 Returns raw translation message for a given key.
 * @method int                 getWeekEndsAt(?string $locale = null)                                                                                                Get the last day of week.
 * @method int                 getWeekStartsAt(?string $locale = null)                                                                                              Get the first day of week.
 * @method bool                hasRelativeKeywords(?string $time)                                                                                                   Determine if a time string will produce a relative date.
 * @method CarbonImmutable     instance(DateTimeInterface $date)                                                                                                    Create a Carbon instance from a DateTime one.
 * @method bool                isImmutable()                                                                                                                        Returns true if the current class/instance is immutable.
 * @method bool                isModifiableUnit($unit)                                                                                                              Returns true if a property can be changed via setter.
 * @method bool                isMutable()                                                                                                                          Returns true if the current class/instance is mutable.
 * @method bool                localeHasDiffOneDayWords(string $locale)                                                                                             Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
 *                                                                                                                                                                  Support is considered enabled if the 3 words are translated in the given locale.
 * @method bool                localeHasDiffSyntax(string $locale)                                                                                                  Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
 *                                                                                                                                                                  Support is considered enabled if the 4 sentences are translated in the given locale.
 * @method bool                localeHasDiffTwoDayWords(string $locale)                                                                                             Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
 *                                                                                                                                                                  Support is considered enabled if the 2 words are translated in the given locale.
 * @method bool                localeHasPeriodSyntax($locale)                                                                                                       Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
 *                                                                                                                                                                  Support is considered enabled if the 4 sentences are translated in the given locale.
 * @method bool                localeHasShortUnits(string $locale)                                                                                                  Returns true if the given locale is internally supported and has short-units support.
 *                                                                                                                                                                  Support is considered enabled if either year, day or hour has a short variant translated.
 * @method ?CarbonImmutable    make($var, DateTimeZone|string|null $timezone = null)                                                                                Make a Carbon instance from given variable if possible.
 *                                                                                                                                                                  Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
 *                                                                                                                                                                  and recurrences). Throw an exception for invalid format, but otherwise return null.
 * @method void                mixin(object|string $mixin)                                                                                                          Mix another object into the class.
 * @method CarbonImmutable     parse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null)                    Create a carbon instance from a string.
 *                                                                                                                                                                  This is an alias for the constructor that allows better fluent syntax
 *                                                                                                                                                                  as it allows you to do Carbon::parse('Monday next week')->fn() rather
 *                                                                                                                                                                  than (new Carbon('Monday next week'))->fn().
 * @method CarbonImmutable     parseFromLocale(string $time, ?string $locale = null, DateTimeZone|string|int|null $timezone = null)                                 Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
 * @method string              pluralUnit(string $unit)                                                                                                             Returns standardized plural of a given singular/plural unit name (in English).
 * @method ?CarbonImmutable    rawCreateFromFormat(string $format, string $time, $timezone = null)                                                                  Create a Carbon instance from a specific format.
 * @method CarbonImmutable     rawParse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null)                 Create a carbon instance from a string.
 *                                                                                                                                                                  This is an alias for the constructor that allows better fluent syntax
 *                                                                                                                                                                  as it allows you to do Carbon::parse('Monday next week')->fn() rather
 *                                                                                                                                                                  than (new Carbon('Monday next week'))->fn().
 * @method void                setFallbackLocale(string $locale)                                                                                                    Set the fallback locale.
 * @method void                setLocale(string $locale)                                                                                                            Set the current translator locale and indicate if the source locale file exists.
 *                                                                                                                                                                  Pass 'auto' as locale to use the closest language to the current LC_TIME locale.
 * @method void                setMidDayAt($hour)                                                                                                                   @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
 *                                                                                                                                                                              You should rather consider mid-day is always 12pm, then if you need to test if it's an other
 *                                                                                                                                                                              hour, test it explicitly:
 *                                                                                                                                                                                  $date->format('G') == 13
 *                                                                                                                                                                              or to set explicitly to a given hour:
 *                                                                                                                                                                                  $date->setTime(13, 0, 0, 0)
 *                                                                                                                                                                  Set midday/noon hour
 * @method string              singularUnit(string $unit)                                                                                                           Returns standardized singular of a given singular/plural unit name (in English).
 * @method CarbonImmutable     today(DateTimeZone|string|int|null $timezone = null)                                                                                 Create a Carbon instance for today.
 * @method CarbonImmutable     tomorrow(DateTimeZone|string|int|null $timezone = null)                                                                              Create a Carbon instance for tomorrow.
 * @method string              translateTimeString(string $timeString, ?string $from = null, ?string $to = null, int $mode = CarbonInterface::TRANSLATE_ALL)        Translate a time string from a locale to an other.
 * @method string              translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null)                                  Translate using translation string or callback available.
 * @method CarbonImmutable     yesterday(DateTimeZone|string|int|null $timezone = null)                                                                             Create a Carbon instance for yesterday.
 *
 * </autodoc>
 */
class FactoryImmutable extends Factory implements ClockInterface
{
    protected string $className = CarbonImmutable::class;

    private static ?self $defaultInstance = null;

    private static ?WrapperClock $currentClock = null;

    /**
     * @internal Instance used for static calls, such as Carbon::getTranslator(), CarbonImmutable::setTestNow(), etc.
     */
    public static function getDefaultInstance(): self
    {
        return self::$defaultInstance ??= new self();
    }

    /**
     * @internal Instance used for static calls possibly called by non-static methods.
     */
    public static function getInstance(): Factory
    {
        return self::$currentClock?->getFactory() ?? self::getDefaultInstance();
    }

    /**
     * @internal Set instance before creating new dates.
     */
    public static function setCurrentClock(ClockInterface|Factory|DateTimeInterface|null $currentClock): void
    {
        if ($currentClock && !($currentClock instanceof WrapperClock)) {
            $currentClock = new WrapperClock($currentClock);
        }

        self::$currentClock = $currentClock;
    }

    /**
     * @internal Instance used to link new object to their factory creator.
     */
    public static function getCurrentClock(): ?WrapperClock
    {
        return self::$currentClock;
    }

    /**
     * Get a Carbon instance for the current date and time.
     */
    public function now(DateTimeZone|string|int|null $timezone = null): CarbonImmutable
    {
        return $this->__call('now', [$timezone]);
    }

    public function sleep(int|float $seconds): void
    {
        if ($this->hasTestNow()) {
            $this->setTestNow($this->getTestNow()->avoidMutation()->addSeconds($seconds));

            return;
        }

        (new NativeClock('UTC'))->sleep($seconds);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return [
    /*
     * ISO 639-2
     */
    'ab' => [
        'isoName' => 'Abkhazian',
        'nativeName' => 'аҧсуа бызшәа, аҧсшәа',
    ],
    'aa' => [
        'isoName' => 'Afar',
        'nativeName' => 'Afaraf',
    ],
    'af' => [
        'isoName' => 'Afrikaans',
        'nativeName' => 'Afrikaans',
    ],
    'ak' => [
        'isoName' => 'Akan',
        'nativeName' => 'Akan',
    ],
    'sq' => [
        'isoName' => 'Albanian',
        'nativeName' => 'Shqip',
    ],
    'am' => [
        'isoName' => 'Amharic',
        'nativeName' => 'አማርኛ',
    ],
    'ar' => [
        'isoName' => 'Arabic',
        'nativeName' => 'العربية',
    ],
    'an' => [
        'isoName' => 'Aragonese',
        'nativeName' => 'aragonés',
    ],
    'hy' => [
        'isoName' => 'Armenian',
        'nativeName' => 'Հայերեն',
    ],
    'as' => [
        'isoName' => 'Assamese',
        'nativeName' => 'অসমীয়া',
    ],
    'av' => [
        'isoName' => 'Avaric',
        'nativeName' => 'авар мацӀ, магӀарул мацӀ',
    ],
    'ae' => [
        'isoName' => 'Avestan',
        'nativeName' => 'avesta',
    ],
    'ay' => [
        'isoName' => 'Aymara',
        'nativeName' => 'aymar aru',
    ],
    'az' => [
        'isoName' => 'Azerbaijani',
        'nativeName' => 'azərbaycan dili',
    ],
    'bm' => [
        'isoName' => 'Bambara',
        'nativeName' => 'bamanankan',
    ],
    'ba' => [
        'isoName' => 'Bashkir',
        'nativeName' => 'башҡорт теле',
    ],
    'eu' => [
        'isoName' => 'Basque',
        'nativeName' => 'euskara, euskera',
    ],
    'be' => [
        'isoName' => 'Belarusian',
        'nativeName' => 'беларуская мова',
    ],
    'bn' => [
        'isoName' => 'Bengali',
        'nativeName' => 'বাংলা',
    ],
    'bh' => [
        'isoName' => 'Bihari languages',
        'nativeName' => 'भोजपुरी',
    ],
    'bi' => [
        'isoName' => 'Bislama',
        'nativeName' => 'Bislama',
    ],
    'bs' => [
        'isoName' => 'Bosnian',
        'nativeName' => 'bosanski jezik',
    ],
    'br' => [
        'isoName' => 'Breton',
        'nativeName' => 'brezhoneg',
    ],
    'bg' => [
        'isoName' => 'Bulgarian',
        'nativeName' => 'български език',
    ],
    'my' => [
        'isoName' => 'Burmese',
        'nativeName' => 'ဗမာစာ',
    ],
    'ca' => [
        'isoName' => 'Catalan, Valencian',
        'nativeName' => 'català, valencià',
    ],
    'ch' => [
        'isoName' => 'Chamorro',
        'nativeName' => 'Chamoru',
    ],
    'ce' => [
        'isoName' => 'Chechen',
        'nativeName' => 'нохчийн мотт',
    ],
    'ny' => [
        'isoName' => 'Chichewa, Chewa, Nyanja',
        'nativeName' => 'chiCheŵa, chinyanja',
    ],
    'zh' => [
        'isoName' => 'Chinese',
        'nativeName' => '中文 (Zhōngwén), 汉语, 漢語',
    ],
    'cv' => [
        'isoName' => 'Chuvash',
        'nativeName' => 'чӑваш чӗлхи',
    ],
    'kw' => [
        'isoName' => 'Cornish',
        'nativeName' => 'Kernewek',
    ],
    'co' => [
        'isoName' => 'Corsican',
        'nativeName' => 'corsu, lingua corsa',
    ],
    'cr' => [
        'isoName' => 'Cree',
        'nativeName' => 'ᓀᐦᐃᔭᐍᐏᐣ',
    ],
    'hr' => [
        'isoName' => 'Croatian',
        'nativeName' => 'hrvatski jezik',
    ],
    'cs' => [
        'isoName' => 'Czech',
        'nativeName' => 'čeština, český jazyk',
    ],
    'da' => [
        'isoName' => 'Danish',
        'nativeName' => 'dansk',
    ],
    'dv' => [
        'isoName' => 'Divehi, Dhivehi, Maldivian',
        'nativeName' => 'ދިވެހި',
    ],
    'nl' => [
        'isoName' => 'Dutch, Flemish',
        'nativeName' => 'Nederlands, Vlaams',
    ],
    'dz' => [
        'isoName' => 'Dzongkha',
        'nativeName' => 'རྫོང་ཁ',
    ],
    'en' => [
        'isoName' => 'English',
        'nativeName' => 'English',
    ],
    'eo' => [
        'isoName' => 'Esperanto',
        'nativeName' => 'Esperanto',
    ],
    'et' => [
        'isoName' => 'Estonian',
        'nativeName' => 'eesti, eesti keel',
    ],
    'ee' => [
        'isoName' => 'Ewe',
        'nativeName' => 'Eʋegbe',
    ],
    'fo' => [
        'isoName' => 'Faroese',
        'nativeName' => 'føroyskt',
    ],
    'fj' => [
        'isoName' => 'Fijian',
        'nativeName' => 'vosa Vakaviti',
    ],
    'fi' => [
        'isoName' => 'Finnish',
        'nativeName' => 'suomi, suomen kieli',
    ],
    'fr' => [
        'isoName' => 'French',
        'nativeName' => 'français',
    ],
    'ff' => [
        'isoName' => 'Fulah',
        'nativeName' => 'Fulfulde, Pulaar, Pular',
    ],
    'gl' => [
        'isoName' => 'Galician',
        'nativeName' => 'Galego',
    ],
    'ka' => [
        'isoName' => 'Georgian',
        'nativeName' => 'ქართული',
    ],
    'de' => [
        'isoName' => 'German',
        'nativeName' => 'Deutsch',
    ],
    'el' => [
        'isoName' => 'Greek (modern)',
        'nativeName' => 'ελληνικά',
    ],
    'gn' => [
        'isoName' => 'Guaraní',
        'nativeName' => 'Avañe\'ẽ',
    ],
    'gu' => [
        'isoName' => 'Gujarati',
        'nativeName' => 'ગુજરાતી',
    ],
    'ht' => [
        'isoName' => 'Haitian, Haitian Creole',
        'nativeName' => 'Kreyòl ayisyen',
    ],
    'ha' => [
        'isoName' => 'Hausa',
        'nativeName' => '(Hausa) هَوُسَ',
    ],
    'he' => [
        'isoName' => 'Hebrew (modern)',
        'nativeName' => 'עברית',
    ],
    'hz' => [
        'isoName' => 'Herero',
        'nativeName' => 'Otjiherero',
    ],
    'hi' => [
        'isoName' => 'Hindi',
        'nativeName' => 'हिन्दी, हिंदी',
    ],
    'ho' => [
        'isoName' => 'Hiri Motu',
        'nativeName' => 'Hiri Motu',
    ],
    'hu' => [
        'isoName' => 'Hungarian',
        'nativeName' => 'magyar',
    ],
    'ia' => [
        'isoName' => 'Interlingua',
        'nativeName' => 'Interlingua',
    ],
    'id' => [
        'isoName' => 'Indonesian',
        'nativeName' => 'Bahasa Indonesia',
    ],
    'ie' => [
        'isoName' => 'Interlingue',
        'nativeName' => 'Originally called Occidental; then Interlingue after WWII',
    ],
    'ga' => [
        'isoName' => 'Irish',
        'nativeName' => 'Gaeilge',
    ],
    'ig' => [
        'isoName' => 'Igbo',
        'nativeName' => 'Asụsụ Igbo',
    ],
    'ik' => [
        'isoName' => 'Inupiaq',
        'nativeName' => 'Iñupiaq, Iñupiatun',
    ],
    'io' => [
        'isoName' => 'Ido',
        'nativeName' => 'Ido',
    ],
    'is' => [
        'isoName' => 'Icelandic',
        'nativeName' => 'Íslenska',
    ],
    'it' => [
        'isoName' => 'Italian',
        'nativeName' => 'Italiano',
    ],
    'iu' => [
        'isoName' => 'Inuktitut',
        'nativeName' => 'ᐃᓄᒃᑎᑐᑦ',
    ],
    'ja' => [
        'isoName' => 'Japanese',
        'nativeName' => '日本語 (にほんご)',
    ],
    'jv' => [
        'isoName' => 'Javanese',
        'nativeName' => 'ꦧꦱꦗꦮ, Basa Jawa',
    ],
    'kl' => [
        'isoName' => 'Kalaallisut, Greenlandic',
        'nativeName' => 'kalaallisut, kalaallit oqaasii',
    ],
    'kn' => [
        'isoName' => 'Kannada',
        'nativeName' => 'ಕನ್ನಡ',
    ],
    'kr' => [
        'isoName' => 'Kanuri',
        'nativeName' => 'Kanuri',
    ],
    'ks' => [
        'isoName' => 'Kashmiri',
        'nativeName' => 'कश्मीरी, كشميري‎',
    ],
    'kk' => [
        'isoName' => 'Kazakh',
        'nativeName' => 'қазақ тілі',
    ],
    'km' => [
        'isoName' => 'Central Khmer',
        'nativeName' => 'ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ',
    ],
    'ki' => [
        'isoName' => 'Kikuyu, Gikuyu',
        'nativeName' => 'Gĩkũyũ',
    ],
    'rw' => [
        'isoName' => 'Kinyarwanda',
        'nativeName' => 'Ikinyarwanda',
    ],
    'ky' => [
        'isoName' => 'Kirghiz, Kyrgyz',
        'nativeName' => 'Кыргызча, Кыргыз тили',
    ],
    'kv' => [
        'isoName' => 'Komi',
        'nativeName' => 'коми кыв',
    ],
    'kg' => [
        'isoName' => 'Kongo',
        'nativeName' => 'Kikongo',
    ],
    'ko' => [
        'isoName' => 'Korean',
        'nativeName' => '한국어',
    ],
    'ku' => [
        'isoName' => 'Kurdish',
        'nativeName' => 'Kurdî, کوردی‎',
    ],
    'kj' => [
        'isoName' => 'Kuanyama, Kwanyama',
        'nativeName' => 'Kuanyama',
    ],
    'la' => [
        'isoName' => 'Latin',
        'nativeName' => 'latine, lingua latina',
    ],
    'lb' => [
        'isoName' => 'Luxembourgish, Letzeburgesch',
        'nativeName' => 'Lëtzebuergesch',
    ],
    'lg' => [
        'isoName' => 'Ganda',
        'nativeName' => 'Luganda',
    ],
    'li' => [
        'isoName' => 'Limburgan, Limburger, Limburgish',
        'nativeName' => 'Limburgs',
    ],
    'ln' => [
        'isoName' => 'Lingala',
        'nativeName' => 'Lingála',
    ],
    'lo' => [
        'isoName' => 'Lao',
        'nativeName' => 'ພາສາລາວ',
    ],
    'lt' => [
        'isoName' => 'Lithuanian',
        'nativeName' => 'lietuvių kalba',
    ],
    'lu' => [
        'isoName' => 'Luba-Katanga',
        'nativeName' => 'Kiluba',
    ],
    'lv' => [
        'isoName' => 'Latvian',
        'nativeName' => 'latviešu valoda',
    ],
    'gv' => [
        'isoName' => 'Manx',
        'nativeName' => 'Gaelg, Gailck',
    ],
    'mk' => [
        'isoName' => 'Macedonian',
        'nativeName' => 'македонски јазик',
    ],
    'mg' => [
        'isoName' => 'Malagasy',
        'nativeName' => 'fiteny malagasy',
    ],
    'ms' => [
        'isoName' => 'Malay',
        'nativeName' => 'Bahasa Melayu, بهاس ملايو‎',
    ],
    'ml' => [
        'isoName' => 'Malayalam',
        'nativeName' => 'മലയാളം',
    ],
    'mt' => [
        'isoName' => 'Maltese',
        'nativeName' => 'Malti',
    ],
    'mi' => [
        'isoName' => 'Maori',
        'nativeName' => 'te reo Māori',
    ],
    'mr' => [
        'isoName' => 'Marathi',
        'nativeName' => 'मराठी',
    ],
    'mh' => [
        'isoName' => 'Marshallese',
        'nativeName' => 'Kajin M̧ajeļ',
    ],
    'mn' => [
        'isoName' => 'Mongolian',
        'nativeName' => 'Монгол хэл',
    ],
    'na' => [
        'isoName' => 'Nauru',
        'nativeName' => 'Dorerin Naoero',
    ],
    'nv' => [
        'isoName' => 'Navajo, Navaho',
        'nativeName' => 'Diné bizaad',
    ],
    'nd' => [
        'isoName' => 'North Ndebele',
        'nativeName' => 'isiNdebele',
    ],
    'ne' => [
        'isoName' => 'Nepali',
        'nativeName' => 'नेपाली',
    ],
    'ng' => [
        'isoName' => 'Ndonga',
        'nativeName' => 'Owambo',
    ],
    'nb' => [
        'isoName' => 'Norwegian Bokmål',
        'nativeName' => 'Norsk Bokmål',
    ],
    'nn' => [
        'isoName' => 'Norwegian Nynorsk',
        'nativeName' => 'Norsk Nynorsk',
    ],
    'no' => [
        'isoName' => 'Norwegian',
        'nativeName' => 'Norsk',
    ],
    'ii' => [
        'isoName' => 'Sichuan Yi, Nuosu',
        'nativeName' => 'ꆈꌠ꒿ Nuosuhxop',
    ],
    'nr' => [
        'isoName' => 'South Ndebele',
        'nativeName' => 'isiNdebele',
    ],
    'oc' => [
        'isoName' => 'Occitan',
        'nativeName' => 'occitan, lenga d\'òc',
    ],
    'oj' => [
        'isoName' => 'Ojibwa',
        'nativeName' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
    ],
    'cu' => [
        'isoName' => 'Church Slavic, Church Slavonic, Old Church Slavonic, Old Slavonic, Old Bulgarian',
        'nativeName' => 'ѩзыкъ словѣньскъ',
    ],
    'om' => [
        'isoName' => 'Oromo',
        'nativeName' => 'Afaan Oromoo',
    ],
    'or' => [
        'isoName' => 'Oriya',
        'nativeName' => 'ଓଡ଼ିଆ',
    ],
    'os' => [
        'isoName' => 'Ossetian, Ossetic',
        'nativeName' => 'ирон æвзаг',
    ],
    'pa' => [
        'isoName' => 'Panjabi, Punjabi',
        'nativeName' => 'ਪੰਜਾਬੀ',
    ],
    'pi' => [
        'isoName' => 'Pali',
        'nativeName' => 'पाऴि',
    ],
    'fa' => [
        'isoName' => 'Persian',
        'nativeName' => 'فارسی',
    ],
    'pl' => [
        'isoName' => 'Polish',
        'nativeName' => 'język polski, polszczyzna',
    ],
    'ps' => [
        'isoName' => 'Pashto, Pushto',
        'nativeName' => 'پښتو',
    ],
    'pt' => [
        'isoName' => 'Portuguese',
        'nativeName' => 'Português',
    ],
    'qu' => [
        'isoName' => 'Quechua',
        'nativeName' => 'Runa Simi, Kichwa',
    ],
    'rm' => [
        'isoName' => 'Romansh',
        'nativeName' => 'Rumantsch Grischun',
    ],
    'rn' => [
        'isoName' => 'Rundi',
        'nativeName' => 'Ikirundi',
    ],
    'ro' => [
        'isoName' => 'Romanian, Moldavian, Moldovan',
        'nativeName' => 'Română',
    ],
    'ru' => [
        'isoName' => 'Russian',
        'nativeName' => 'русский',
    ],
    'sa' => [
        'isoName' => 'Sanskrit',
        'nativeName' => 'संस्कृतम्',
    ],
    'sc' => [
        'isoName' => 'Sardinian',
        'nativeName' => 'sardu',
    ],
    'sd' => [
        'isoName' => 'Sindhi',
        'nativeName' => 'सिन्धी, سنڌي، سندھی‎',
    ],
    'se' => [
        'isoName' => 'Northern Sami',
        'nativeName' => 'Davvisámegiella',
    ],
    'sm' => [
        'isoName' => 'Samoan',
        'nativeName' => 'gagana fa\'a Samoa',
    ],
    'sg' => [
        'isoName' => 'Sango',
        'nativeName' => 'yângâ tî sängö',
    ],
    'sr' => [
        'isoName' => 'Serbian',
        'nativeName' => 'српски језик',
    ],
    'gd' => [
        'isoName' => 'Gaelic, Scottish Gaelic',
        'nativeName' => 'Gàidhlig',
    ],
    'sn' => [
        'isoName' => 'Shona',
        'nativeName' => 'chiShona',
    ],
    'si' => [
        'isoName' => 'Sinhala, Sinhalese',
        'nativeName' => 'සිංහල',
    ],
    'sk' => [
        'isoName' => 'Slovak',
        'nativeName' => 'Slovenčina, Slovenský Jazyk',
    ],
    'sl' => [
        'isoName' => 'Slovenian',
        'nativeName' => 'Slovenski Jezik, Slovenščina',
    ],
    'so' => [
        'isoName' => 'Somali',
        'nativeName' => 'Soomaaliga, af Soomaali',
    ],
    'st' => [
        'isoName' => 'Southern Sotho',
        'nativeName' => 'Sesotho',
    ],
    'es' => [
        'isoName' => 'Spanish, Castilian',
        'nativeName' => 'Español',
    ],
    'su' => [
        'isoName' => 'Sundanese',
        'nativeName' => 'Basa Sunda',
    ],
    'sw' => [
        'isoName' => 'Swahili',
        'nativeName' => 'Kiswahili',
    ],
    'ss' => [
        'isoName' => 'Swati',
        'nativeName' => 'SiSwati',
    ],
    'sv' => [
        'isoName' => 'Swedish',
        'nativeName' => 'Svenska',
    ],
    'ta' => [
        'isoName' => 'Tamil',
        'nativeName' => 'தமிழ்',
    ],
    'te' => [
        'isoName' => 'Telugu',
        'nativeName' => 'తెలుగు',
    ],
    'tg' => [
        'isoName' => 'Tajik',
        'nativeName' => 'тоҷикӣ, toçikī, تاجیکی‎',
    ],
    'th' => [
        'isoName' => 'Thai',
        'nativeName' => 'ไทย',
    ],
    'ti' => [
        'isoName' => 'Tigrinya',
        'nativeName' => 'ትግርኛ',
    ],
    'bo' => [
        'isoName' => 'Tibetan',
        'nativeName' => 'བོད་ཡིག',
    ],
    'tk' => [
        'isoName' => 'Turkmen',
        'nativeName' => 'Türkmen, Түркмен',
    ],
    'tl' => [
        'isoName' => 'Tagalog',
        'nativeName' => 'Wikang Tagalog',
    ],
    'tn' => [
        'isoName' => 'Tswana',
        'nativeName' => 'Setswana',
    ],
    'to' => [
        'isoName' => 'Tongan (Tonga Islands)',
        'nativeName' => 'Faka Tonga',
    ],
    'tr' => [
        'isoName' => 'Turkish',
        'nativeName' => 'Türkçe',
    ],
    'ts' => [
        'isoName' => 'Tsonga',
        'nativeName' => 'Xitsonga',
    ],
    'tt' => [
        'isoName' => 'Tatar',
        'nativeName' => 'татар теле, tatar tele',
    ],
    'tw' => [
        'isoName' => 'Twi',
        'nativeName' => 'Twi',
    ],
    'ty' => [
        'isoName' => 'Tahitian',
        'nativeName' => 'Reo Tahiti',
    ],
    'ug' => [
        'isoName' => 'Uighur, Uyghur',
        'nativeName' => 'Uyƣurqə, ‫ئۇيغۇرچ',
    ],
    'uk' => [
        'isoName' => 'Ukrainian',
        'nativeName' => 'Українська',
    ],
    'ur' => [
        'isoName' => 'Urdu',
        'nativeName' => 'اردو',
    ],
    'uz' => [
        'isoName' => 'Uzbek',
        'nativeName' => 'Oʻzbek, Ўзбек, أۇزبېك‎',
    ],
    've' => [
        'isoName' => 'Venda',
        'nativeName' => 'Tshivenḓa',
    ],
    'vi' => [
        'isoName' => 'Vietnamese',
        'nativeName' => 'Tiếng Việt',
    ],
    'vo' => [
        'isoName' => 'Volapük',
        'nativeName' => 'Volapük',
    ],
    'wa' => [
        'isoName' => 'Walloon',
        'nativeName' => 'Walon',
    ],
    'cy' => [
        'isoName' => 'Welsh',
        'nativeName' => 'Cymraeg',
    ],
    'wo' => [
        'isoName' => 'Wolof',
        'nativeName' => 'Wollof',
    ],
    'fy' => [
        'isoName' => 'Western Frisian',
        'nativeName' => 'Frysk',
    ],
    'xh' => [
        'isoName' => 'Xhosa',
        'nativeName' => 'isiXhosa',
    ],
    'yi' => [
        'isoName' => 'Yiddish',
        'nativeName' => 'ייִדיש',
    ],
    'yo' => [
        'isoName' => 'Yoruba',
        'nativeName' => 'Yorùbá',
    ],
    'za' => [
        'isoName' => 'Zhuang, Chuang',
        'nativeName' => 'Saɯ cueŋƅ, Saw cuengh',
    ],
    'zu' => [
        'isoName' => 'Zulu',
        'nativeName' => 'isiZulu',
    ],
    /*
     * Add ISO 639-3 languages available in Carbon
     */
    'agq' => [
        'isoName' => 'Aghem',
        'nativeName' => 'Aghem',
    ],
    'agr' => [
        'isoName' => 'Aguaruna',
        'nativeName' => 'Aguaruna',
    ],
    'anp' => [
        'isoName' => 'Angika',
        'nativeName' => 'Angika',
    ],
    'asa' => [
        'isoName' => 'Asu',
        'nativeName' => 'Asu',
    ],
    'ast' => [
        'isoName' => 'Asturian',
        'nativeName' => 'Asturian',
    ],
    'ayc' => [
        'isoName' => 'Southern Aymara',
        'nativeName' => 'Southern Aymara',
    ],
    'bas' => [
        'isoName' => 'Basaa',
        'nativeName' => 'Basaa',
    ],
    'bem' => [
        'isoName' => 'Bemba',
        'nativeName' => 'Bemba',
    ],
    'bez' => [
        'isoName' => 'Bena',
        'nativeName' => 'Bena',
    ],
    'bhb' => [
        'isoName' => 'Bhili',
        'nativeName' => 'Bhili',
    ],
    'bho' => [
        'isoName' => 'Bhojpuri',
        'nativeName' => 'Bhojpuri',
    ],
    'brx' => [
        'isoName' => 'Bodo',
        'nativeName' => 'Bodo',
    ],
    'byn' => [
        'isoName' => 'Bilin',
        'nativeName' => 'Bilin',
    ],
    'ccp' => [
        'isoName' => 'Chakma',
        'nativeName' => 'Chakma',
    ],
    'cgg' => [
        'isoName' => 'Chiga',
        'nativeName' => 'Chiga',
    ],
    'chr' => [
        'isoName' => 'Cherokee',
        'nativeName' => 'Cherokee',
    ],
    'cmn' => [
        'isoName' => 'Chinese',
        'nativeName' => 'Chinese',
    ],
    'crh' => [
        'isoName' => 'Crimean Turkish',
        'nativeName' => 'Crimean Turkish',
    ],
    'csb' => [
        'isoName' => 'Kashubian',
        'nativeName' => 'Kashubian',
    ],
    'dav' => [
        'isoName' => 'Taita',
        'nativeName' => 'Taita',
    ],
    'dje' => [
        'isoName' => 'Zarma',
        'nativeName' => 'Zarma',
    ],
    'doi' => [
        'isoName' => 'Dogri (macrolanguage)',
        'nativeName' => 'Dogri (macrolanguage)',
    ],
    'dsb' => [
        'isoName' => 'Lower Sorbian',
        'nativeName' => 'Lower Sorbian',
    ],
    'dua' => [
        'isoName' => 'Duala',
        'nativeName' => 'Duala',
    ],
    'dyo' => [
        'isoName' => 'Jola-Fonyi',
        'nativeName' => 'Jola-Fonyi',
    ],
    'ebu' => [
        'isoName' => 'Embu',
        'nativeName' => 'Embu',
    ],
    'ewo' => [
        'isoName' => 'Ewondo',
        'nativeName' => 'Ewondo',
    ],
    'fil' => [
        'isoName' => 'Filipino',
        'nativeName' => 'Filipino',
    ],
    'fur' => [
        'isoName' => 'Friulian',
        'nativeName' => 'Friulian',
    ],
    'gez' => [
        'isoName' => 'Geez',
        'nativeName' => 'Geez',
    ],
    'gom' => [
        'isoName' => 'Konkani, Goan',
        'nativeName' => 'ಕೊಂಕಣಿ',
    ],
    'gsw' => [
        'isoName' => 'Swiss German',
        'nativeName' => 'Swiss German',
    ],
    'guz' => [
        'isoName' => 'Gusii',
        'nativeName' => 'Gusii',
    ],
    'hak' => [
        'isoName' => 'Hakka Chinese',
        'nativeName' => 'Hakka Chinese',
    ],
    'haw' => [
        'isoName' => 'Hawaiian',
        'nativeName' => 'Hawaiian',
    ],
    'hif' => [
        'isoName' => 'Fiji Hindi',
        'nativeName' => 'Fiji Hindi',
    ],
    'hne' => [
        'isoName' => 'Chhattisgarhi',
        'nativeName' => 'Chhattisgarhi',
    ],
    'hsb' => [
        'isoName' => 'Upper Sorbian',
        'nativeName' => 'Upper Sorbian',
    ],
    'jgo' => [
        'isoName' => 'Ngomba',
        'nativeName' => 'Ngomba',
    ],
    'jmc' => [
        'isoName' => 'Machame',
        'nativeName' => 'Machame',
    ],
    'kab' => [
        'isoName' => 'Kabyle',
        'nativeName' => 'Kabyle',
    ],
    'kam' => [
        'isoName' => 'Kamba',
        'nativeName' => 'Kamba',
    ],
    'kde' => [
        'isoName' => 'Makonde',
        'nativeName' => 'Makonde',
    ],
    'kea' => [
        'isoName' => 'Kabuverdianu',
        'nativeName' => 'Kabuverdianu',
    ],
    'khq' => [
        'isoName' => 'Koyra Chiini',
        'nativeName' => 'Koyra Chiini',
    ],
    'kkj' => [
        'isoName' => 'Kako',
        'nativeName' => 'Kako',
    ],
    'kln' => [
        'isoName' => 'Kalenjin',
        'nativeName' => 'Kalenjin',
    ],
    'kok' => [
        'isoName' => 'Konkani',
        'nativeName' => 'Konkani',
    ],
    'ksb' => [
        'isoName' => 'Shambala',
        'nativeName' => 'Shambala',
    ],
    'ksf' => [
        'isoName' => 'Bafia',
        'nativeName' => 'Bafia',
    ],
    'ksh' => [
        'isoName' => 'Colognian',
        'nativeName' => 'Colognian',
    ],
    'lag' => [
        'isoName' => 'Langi',
        'nativeName' => 'Langi',
    ],
    'lij' => [
        'isoName' => 'Ligurian',
        'nativeName' => 'Ligurian',
    ],
    'lkt' => [
        'isoName' => 'Lakota',
        'nativeName' => 'Lakota',
    ],
    'lrc' => [
        'isoName' => 'Northern Luri',
        'nativeName' => 'Northern Luri',
    ],
    'luo' => [
        'isoName' => 'Luo',
        'nativeName' => 'Luo',
    ],
    'luy' => [
        'isoName' => 'Luyia',
        'nativeName' => 'Luyia',
    ],
    'lzh' => [
        'isoName' => 'Literary Chinese',
        'nativeName' => 'Literary Chinese',
    ],
    'mag' => [
        'isoName' => 'Magahi',
        'nativeName' => 'Magahi',
    ],
    'mai' => [
        'isoName' => 'Maithili',
        'nativeName' => 'Maithili',
    ],
    'mas' => [
        'isoName' => 'Masai',
        'nativeName' => 'Masai',
    ],
    'mer' => [
        'isoName' => 'Meru',
        'nativeName' => 'Meru',
    ],
    'mfe' => [
        'isoName' => 'Morisyen',
        'nativeName' => 'Morisyen',
    ],
    'mgh' => [
        'isoName' => 'Makhuwa-Meetto',
        'nativeName' => 'Makhuwa-Meetto',
    ],
    'mgo' => [
        'isoName' => 'Metaʼ',
        'nativeName' => 'Metaʼ',
    ],
    'mhr' => [
        'isoName' => 'Eastern Mari',
        'nativeName' => 'Eastern Mari',
    ],
    'miq' => [
        'isoName' => 'Mískito',
        'nativeName' => 'Mískito',
    ],
    'mjw' => [
        'isoName' => 'Karbi',
        'nativeName' => 'Karbi',
    ],
    'mni' => [
        'isoName' => 'Manipuri',
        'nativeName' => 'Manipuri',
    ],
    'mua' => [
        'isoName' => 'Mundang',
        'nativeName' => 'Mundang',
    ],
    'mzn' => [
        'isoName' => 'Mazanderani',
        'nativeName' => 'Mazanderani',
    ],
    'nan' => [
        'isoName' => 'Min Nan Chinese',
        'nativeName' => 'Min Nan Chinese',
    ],
    'naq' => [
        'isoName' => 'Nama',
        'nativeName' => 'Nama',
    ],
    'nds' => [
        'isoName' => 'Low German',
        'nativeName' => 'Low German',
    ],
    'nhn' => [
        'isoName' => 'Central Nahuatl',
        'nativeName' => 'Central Nahuatl',
    ],
    'niu' => [
        'isoName' => 'Niuean',
        'nativeName' => 'Niuean',
    ],
    'nmg' => [
        'isoName' => 'Kwasio',
        'nativeName' => 'Kwasio',
    ],
    'nnh' => [
        'isoName' => 'Ngiemboon',
        'nativeName' => 'Ngiemboon',
    ],
    'nso' => [
        'isoName' => 'Northern Sotho',
        'nativeName' => 'Northern Sotho',
    ],
    'nus' => [
        'isoName' => 'Nuer',
        'nativeName' => 'Nuer',
    ],
    'nyn' => [
        'isoName' => 'Nyankole',
        'nativeName' => 'Nyankole',
    ],
    'pap' => [
        'isoName' => 'Papiamento',
        'nativeName' => 'Papiamento',
    ],
    'prg' => [
        'isoName' => 'Prussian',
        'nativeName' => 'Prussian',
    ],
    'quz' => [
        'isoName' => 'Cusco Quechua',
        'nativeName' => 'Cusco Quechua',
    ],
    'raj' => [
        'isoName' => 'Rajasthani',
        'nativeName' => 'Rajasthani',
    ],
    'rof' => [
        'isoName' => 'Rombo',
        'nativeName' => 'Rombo',
    ],
    'rwk' => [
        'isoName' => 'Rwa',
        'nativeName' => 'Rwa',
    ],
    'sah' => [
        'isoName' => 'Sakha',
        'nativeName' => 'Sakha',
    ],
    'saq' => [
        'isoName' => 'Samburu',
        'nativeName' => 'Samburu',
    ],
    'sat' => [
        'isoName' => 'Santali',
        'nativeName' => 'Santali',
    ],
    'sbp' => [
        'isoName' => 'Sangu',
        'nativeName' => 'Sangu',
    ],
    'scr' => [
        'isoName' => 'Serbo Croatian',
        'nativeName' => 'Serbo Croatian',
    ],
    'seh' => [
        'isoName' => 'Sena',
        'nativeName' => 'Sena',
    ],
    'ses' => [
        'isoName' => 'Koyraboro Senni',
        'nativeName' => 'Koyraboro Senni',
    ],
    'sgs' => [
        'isoName' => 'Samogitian',
        'nativeName' => 'Samogitian',
    ],
    'shi' => [
        'isoName' => 'Tachelhit',
        'nativeName' => 'Tachelhit',
    ],
    'shn' => [
        'isoName' => 'Shan',
        'nativeName' => 'Shan',
    ],
    'shs' => [
        'isoName' => 'Shuswap',
        'nativeName' => 'Shuswap',
    ],
    'sid' => [
        'isoName' => 'Sidamo',
        'nativeName' => 'Sidamo',
    ],
    'smn' => [
        'isoName' => 'Inari Sami',
        'nativeName' => 'Inari Sami',
    ],
    'szl' => [
        'isoName' => 'Silesian',
        'nativeName' => 'Silesian',
    ],
    'tcy' => [
        'isoName' => 'Tulu',
        'nativeName' => 'Tulu',
    ],
    'teo' => [
        'isoName' => 'Teso',
        'nativeName' => 'Teso',
    ],
    'tet' => [
        'isoName' => 'Tetum',
        'nativeName' => 'Tetum',
    ],
    'the' => [
        'isoName' => 'Chitwania Tharu',
        'nativeName' => 'Chitwania Tharu',
    ],
    'tig' => [
        'isoName' => 'Tigre',
        'nativeName' => 'Tigre',
    ],
    'tlh' => [
        'isoName' => 'Klingon',
        'nativeName' => 'tlhIngan Hol',
    ],
    'tpi' => [
        'isoName' => 'Tok Pisin',
        'nativeName' => 'Tok Pisin',
    ],
    'twq' => [
        'isoName' => 'Tasawaq',
        'nativeName' => 'Tasawaq',
    ],
    'tzl' => [
        'isoName' => 'Talossan',
        'nativeName' => 'Talossan',
    ],
    'tzm' => [
        'isoName' => 'Tamazight, Central Atlas',
        'nativeName' => 'ⵜⵎⴰⵣⵉⵖⵜ',
    ],
    'unm' => [
        'isoName' => 'Unami',
        'nativeName' => 'Unami',
    ],
    'vai' => [
        'isoName' => 'Vai',
        'nativeName' => 'Vai',
    ],
    'vun' => [
        'isoName' => 'Vunjo',
        'nativeName' => 'Vunjo',
    ],
    'wae' => [
        'isoName' => 'Walser',
        'nativeName' => 'Walser',
    ],
    'wal' => [
        'isoName' => 'Wolaytta',
        'nativeName' => 'Wolaytta',
    ],
    'xog' => [
        'isoName' => 'Soga',
        'nativeName' => 'Soga',
    ],
    'yav' => [
        'isoName' => 'Yangben',
        'nativeName' => 'Yangben',
    ],
    'yue' => [
        'isoName' => 'Cantonese',
        'nativeName' => 'Cantonese',
    ],
    'yuw' => [
        'isoName' => 'Yau (Morobe Province)',
        'nativeName' => 'Yau (Morobe Province)',
    ],
    'zgh' => [
        'isoName' => 'Standard Moroccan Tamazight',
        'nativeName' => 'Standard Moroccan Tamazight',
    ],
];
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * ISO 3166-2 short names.
 *
 * ⚠ Provided with No Warranty
 *
 * This list has no official value, and it's using short name, i.e. the first column of
 * https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
 *
 * Without the extra parenthesis unless a particular ambiguity in the list.
 *
 * For instance:
 *  - Falkland Islands and Malvinas both to FK, but we keep only the first for brevity and
 *    because there is no ambiguity in the list to justify longer name.
 *  - For Sint Maarten/Saint Martin not to have any confusion between FM and SX codes that
 *    are on the same island and so to be clear it's not referring to the whole island,
 *    south (dutch-speaking) and north (french-speaking) parentheses are kept for disambiguation.
 *  - For Virgin Islands, that can refer to either VG or VI, parentheses are also kept for
 *    disambiguation.
 *
 * We won't take into consideration any change request in this list unless there is an update
 * in ISO 3166-2 itself that we need to align to.
 *
 * It's a purely geographical helper, state sovereignty is out of scope, for political
 * complains you should address them directly to https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
 *
 * Anyone needing official state names (such as the second column of the wikipedia page above)
 * should seek for another tool, this list is not meant to provide long names.
 */
return [
    'AD' => 'Andorra',
    'AE' => 'United Arab Emirates',
    'AF' => 'Afghanistan',
    'AG' => 'Antigua and Barbuda',
    'AI' => 'Anguilla',
    'AL' => 'Albania',
    'AM' => 'Armenia',
    'AO' => 'Angola',
    'AQ' => 'Antarctica',
    'AR' => 'Argentina',
    'AS' => 'American Samoa',
    'AT' => 'Austria',
    'AU' => 'Australia',
    'AW' => 'Aruba',
    'AX' => 'Åland Islands',
    'AZ' => 'Azerbaijan',
    'BA' => 'Bosnia and Herzegovina',
    'BB' => 'Barbados',
    'BD' => 'Bangladesh',
    'BE' => 'Belgium',
    'BF' => 'Burkina Faso',
    'BG' => 'Bulgaria',
    'BH' => 'Bahrain',
    'BI' => 'Burundi',
    'BJ' => 'Benin',
    'BL' => 'Saint Barthélemy',
    'BM' => 'Bermuda',
    'BN' => 'Brunei Darussalam',
    'BO' => 'Bolivia',
    'BQ' => 'Bonaire, Sint Eustatius and Saba',
    'BR' => 'Brazil',
    'BS' => 'Bahamas',
    'BT' => 'Bhutan',
    'BV' => 'Bouvet Island',
    'BW' => 'Botswana',
    'BY' => 'Belarus',
    'BZ' => 'Belize',
    'CA' => 'Canada',
    'CC' => 'Cocos (Keeling) Islands',
    'CD' => 'Congo, Democratic Republic of the',
    'CF' => 'Central African Republic',
    'CG' => 'Congo',
    'CH' => 'Switzerland',
    'CI' => 'Côte d\'Ivoire',
    'CK' => 'Cook Islands',
    'CL' => 'Chile',
    'CM' => 'Cameroon',
    'CN' => 'China',
    'CO' => 'Colombia',
    'CR' => 'Costa Rica',
    'CU' => 'Cuba',
    'CV' => 'Cabo Verde',
    'CW' => 'Curaçao',
    'CX' => 'Christmas Island',
    'CY' => 'Cyprus',
    'CZ' => 'Czechia',
    'DE' => 'Germany',
    'DJ' => 'Djibouti',
    'DK' => 'Denmark',
    'DM' => 'Dominica',
    'DO' => 'Dominican Republic',
    'DZ' => 'Algeria',
    'EC' => 'Ecuador',
    'EE' => 'Estonia',
    'EG' => 'Egypt',
    'EH' => 'Western Sahara',
    'ER' => 'Eritrea',
    'ES' => 'Spain',
    'ET' => 'Ethiopia',
    'FI' => 'Finland',
    'FJ' => 'Fiji',
    'FK' => 'Falkland Islands',
    'FM' => 'Micronesia',
    'FO' => 'Faroe Islands',
    'FR' => 'France',
    'GA' => 'Gabon',
    'GB' => 'United Kingdom of Great Britain and Northern Ireland',
    'GD' => 'Grenada',
    'GE' => 'Georgia',
    'GF' => 'French Guiana',
    'GG' => 'Guernsey',
    'GH' => 'Ghana',
    'GI' => 'Gibraltar',
    'GL' => 'Greenland',
    'GM' => 'Gambia',
    'GN' => 'Guinea',
    'GP' => 'Guadeloupe',
    'GQ' => 'Equatorial Guinea',
    'GR' => 'Greece',
    'GS' => 'South Georgia and the South Sandwich Islands',
    'GT' => 'Guatemala',
    'GU' => 'Guam',
    'GW' => 'Guinea-Bissau',
    'GY' => 'Guyana',
    'HK' => 'Hong Kong',
    'HM' => 'Heard Island and McDonald Islands',
    'HN' => 'Honduras',
    'HR' => 'Croatia',
    'HT' => 'Haiti',
    'HU' => 'Hungary',
    'ID' => 'Indonesia',
    'IE' => 'Ireland',
    'IL' => 'Israel',
    'IM' => 'Isle of Man',
    'IN' => 'India',
    'IO' => 'British Indian Ocean Territory',
    'IQ' => 'Iraq',
    'IR' => 'Iran',
    'IS' => 'Iceland',
    'IT' => 'Italy',
    'JE' => 'Jersey',
    'JM' => 'Jamaica',
    'JO' => 'Jordan',
    'JP' => 'Japan',
    'KE' => 'Kenya',
    'KG' => 'Kyrgyzstan',
    'KH' => 'Cambodia',
    'KI' => 'Kiribati',
    'KM' => 'Comoros',
    'KN' => 'Saint Kitts and Nevis',
    'KP' => 'Korea (Democratic People\'s Republic of)',
    'KR' => 'Korea, Republic of',
    'KW' => 'Kuwait',
    'KY' => 'Cayman Islands',
    'KZ' => 'Kazakhstan',
    'LA' => 'Lao People\'s Democratic Republic',
    'LB' => 'Lebanon',
    'LC' => 'Saint Lucia',
    'LI' => 'Liechtenstein',
    'LK' => 'Sri Lanka',
    'LR' => 'Liberia',
    'LS' => 'Lesotho',
    'LT' => 'Lithuania',
    'LU' => 'Luxembourg',
    'LV' => 'Latvia',
    'LY' => 'Libya',
    'MA' => 'Morocco',
    'MC' => 'Monaco',
    'MD' => 'Moldova',
    'ME' => 'Montenegro',
    'MF' => 'Saint Martin (French part)',
    'MG' => 'Madagascar',
    'MH' => 'Marshall Islands',
    'MK' => 'North Macedonia',
    'ML' => 'Mali',
    'MM' => 'Myanmar',
    'MN' => 'Mongolia',
    'MO' => 'Macao',
    'MP' => 'Northern Mariana Islands',
    'MQ' => 'Martinique',
    'MR' => 'Mauritania',
    'MS' => 'Montserrat',
    'MT' => 'Malta',
    'MU' => 'Mauritius',
    'MV' => 'Maldives',
    'MW' => 'Malawi',
    'MX' => 'Mexico',
    'MY' => 'Malaysia',
    'MZ' => 'Mozambique',
    'NA' => 'Namibia',
    'NC' => 'New Caledonia',
    'NE' => 'Niger',
    'NF' => 'Norfolk Island',
    'NG' => 'Nigeria',
    'NI' => 'Nicaragua',
    'NL' => 'Netherlands',
    'NO' => 'Norway',
    'NP' => 'Nepal',
    'NR' => 'Nauru',
    'NU' => 'Niue',
    'NZ' => 'New Zealand',
    'OM' => 'Oman',
    'PA' => 'Panama',
    'PE' => 'Peru',
    'PF' => 'French Polynesia',
    'PG' => 'Papua New Guinea',
    'PH' => 'Philippines',
    'PK' => 'Pakistan',
    'PL' => 'Poland',
    'PM' => 'Saint Pierre and Miquelon',
    'PN' => 'Pitcairn',
    'PR' => 'Puerto Rico',
    'PS' => 'Palestine',
    'PT' => 'Portugal',
    'PW' => 'Palau',
    'PY' => 'Paraguay',
    'QA' => 'Qatar',
    'RE' => 'Réunion',
    'RO' => 'Romania',
    'RS' => 'Serbia',
    'RU' => 'Russian Federation',
    'RW' => 'Rwanda',
    'SA' => 'Saudi Arabia',
    'SB' => 'Solomon Islands',
    'SC' => 'Seychelles',
    'SD' => 'Sudan',
    'SE' => 'Sweden',
    'SG' => 'Singapore',
    'SH' => 'Saint Helena, Ascension and Tristan da Cunha',
    'SI' => 'Slovenia',
    'SJ' => 'Svalbard and Jan Mayen',
    'SK' => 'Slovakia',
    'SL' => 'Sierra Leone',
    'SM' => 'San Marino',
    'SN' => 'Senegal',
    'SO' => 'Somalia',
    'SR' => 'Suriname',
    'SS' => 'South Sudan',
    'ST' => 'Sao Tome and Principe',
    'SV' => 'El Salvador',
    'SX' => 'Sint Maarten (Dutch part)',
    'SY' => 'Syrian Arab Republic',
    'SZ' => 'Eswatini',
    'TC' => 'Turks and Caicos Islands',
    'TD' => 'Chad',
    'TF' => 'French Southern Territories',
    'TG' => 'Togo',
    'TH' => 'Thailand',
    'TJ' => 'Tajikistan',
    'TK' => 'Tokelau',
    'TL' => 'Timor-Leste',
    'TM' => 'Turkmenistan',
    'TN' => 'Tunisia',
    'TO' => 'Tonga',
    'TR' => 'Turkey',
    'TT' => 'Trinidad and Tobago',
    'TV' => 'Tuvalu',
    'TW' => 'Taiwan',
    'TZ' => 'Tanzania',
    'UA' => 'Ukraine',
    'UG' => 'Uganda',
    'UM' => 'United States Minor Outlying Islands',
    'US' => 'United States of America',
    'UY' => 'Uruguay',
    'UZ' => 'Uzbekistan',
    'VA' => 'Holy See',
    'VC' => 'Saint Vincent and the Grenadines',
    'VE' => 'Venezuela',
    'VG' => 'Virgin Islands (British)',
    'VI' => 'Virgin Islands (U.S.)',
    'VN' => 'Viet Nam',
    'VU' => 'Vanuatu',
    'WF' => 'Wallis and Futuna',
    'WS' => 'Samoa',
    'YE' => 'Yemen',
    'YT' => 'Mayotte',
    'ZA' => 'South Africa',
    'ZM' => 'Zambia',
    'ZW' => 'Zimbabwe',
];
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Constants;

interface UnitValue
{
    /**
     * The day constants.
     */
    public const SUNDAY = 0;
    public const MONDAY = 1;
    public const TUESDAY = 2;
    public const WEDNESDAY = 3;
    public const THURSDAY = 4;
    public const FRIDAY = 5;
    public const SATURDAY = 6;

    /**
     * The month constants.
     * These aren't used by Carbon itself but exist for
     * convenience's sake alone.
     */
    public const JANUARY = 1;
    public const FEBRUARY = 2;
    public const MARCH = 3;
    public const APRIL = 4;
    public const MAY = 5;
    public const JUNE = 6;
    public const JULY = 7;
    public const AUGUST = 8;
    public const SEPTEMBER = 9;
    public const OCTOBER = 10;
    public const NOVEMBER = 11;
    public const DECEMBER = 12;

    /**
     * Number of X in Y.
     */
    public const YEARS_PER_MILLENNIUM = 1_000;
    public const YEARS_PER_CENTURY = 100;
    public const YEARS_PER_DECADE = 10;
    public const MONTHS_PER_YEAR = 12;
    public const MONTHS_PER_QUARTER = 3;
    public const QUARTERS_PER_YEAR = 4;
    public const WEEKS_PER_YEAR = 52;
    public const WEEKS_PER_MONTH = 4;
    public const DAYS_PER_YEAR = 365;
    public const DAYS_PER_WEEK = 7;
    public const HOURS_PER_DAY = 24;
    public const MINUTES_PER_HOUR = 60;
    public const SECONDS_PER_MINUTE = 60;
    public const MILLISECONDS_PER_SECOND = 1_000;
    public const MICROSECONDS_PER_MILLISECOND = 1_000;
    public const MICROSECONDS_PER_SECOND = 1_000_000;
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Constants;

interface DiffOptions
{
    /**
     * Diff wording options(expressed in octal).
     */
    public const NO_ZERO_DIFF = 01;
    public const JUST_NOW = 02;
    public const ONE_DAY_WORDS = 04;
    public const TWO_DAY_WORDS = 010;
    public const SEQUENTIAL_PARTS_ONLY = 020;
    public const ROUND = 040;
    public const FLOOR = 0100;
    public const CEIL = 0200;

    /**
     * Diff syntax options.
     */
    public const DIFF_ABSOLUTE = 1; // backward compatibility with true
    public const DIFF_RELATIVE_AUTO = 0; // backward compatibility with false
    public const DIFF_RELATIVE_TO_NOW = 2;
    public const DIFF_RELATIVE_TO_OTHER = 3;
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Constants;

interface Format
{
    /**
     * RFC7231 DateTime format.
     *
     * @var string
     */
    public const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T';

    /**
     * Default format to use for __toString method when type juggling occurs.
     *
     * @var string
     */
    public const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s';

    /**
     * Format for converting mocked time, includes microseconds.
     *
     * @var string
     */
    public const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u';

    /**
     * Pattern detection for ->isoFormat and ::createFromIsoFormat.
     *
     * @var string
     */
    public const ISO_FORMAT_REGEXP = '(O[YMDHhms]|[Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY?|g{1,5}|G{1,5}|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?)';
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Constants;

interface TranslationOptions
{
    /**
     * Translate string options.
     */
    public const TRANSLATE_MONTHS = 1;
    public const TRANSLATE_DAYS = 2;
    public const TRANSLATE_UNITS = 4;
    public const TRANSLATE_MERIDIEM = 8;
    public const TRANSLATE_DIFF = 0x10;
    public const TRANSLATE_ALL = self::TRANSLATE_MONTHS | self::TRANSLATE_DAYS | self::TRANSLATE_UNITS | self::TRANSLATE_MERIDIEM | self::TRANSLATE_DIFF;

    /**
     * Special settings to get the start of week from current locale culture.
     */
    public const WEEK_DAY_AUTO = 'auto';

    /**
     * Default locale (language and region).
     *
     * @var string
     */
    public const DEFAULT_LOCALE = 'en';
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Exceptions\InvalidFormatException;

enum WeekDay: int
{
    // Using constants is only safe starting from PHP 8.2
    case Sunday = 0; // CarbonInterface::SUNDAY
    case Monday = 1; // CarbonInterface::MONDAY
    case Tuesday = 2; // CarbonInterface::TUESDAY
    case Wednesday = 3; // CarbonInterface::WEDNESDAY
    case Thursday = 4; // CarbonInterface::THURSDAY
    case Friday = 5; // CarbonInterface::FRIDAY
    case Saturday = 6; // CarbonInterface::SATURDAY

    public static function int(self|int|null $value): ?int
    {
        return $value instanceof self ? $value->value : $value;
    }

    public static function fromNumber(int $number): self
    {
        $day = $number % CarbonInterface::DAYS_PER_WEEK;

        return self::from($day + ($day < 0 ? CarbonInterface::DAYS_PER_WEEK : 0));
    }

    public static function fromName(string $name, ?string $locale = null): self
    {
        try {
            return self::from(CarbonImmutable::parseFromLocale($name, $locale)->dayOfWeek);
        } catch (InvalidFormatException $exception) {
            // Possibly current language expect a dot after short name, but it's missing
            if ($locale !== null && !mb_strlen($name) < 4 && !str_ends_with($name, '.')) {
                try {
                    return self::from(CarbonImmutable::parseFromLocale($name.'.', $locale)->dayOfWeek);
                } catch (InvalidFormatException) {
                    // Throw previous error
                }
            }

            throw $exception;
        }
    }

    public function next(?CarbonImmutable $now = null): CarbonImmutable
    {
        return $now?->modify($this->name) ?? new CarbonImmutable($this->name);
    }

    public function locale(string $locale, ?CarbonImmutable $now = null): CarbonImmutable
    {
        return $this->next($now)->locale($locale);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Exceptions\InvalidFormatException;

enum Month: int
{
    // Using constants is only safe starting from PHP 8.2
    case January = 1; // CarbonInterface::JANUARY
    case February = 2; // CarbonInterface::FEBRUARY
    case March = 3; // CarbonInterface::MARCH
    case April = 4; // CarbonInterface::APRIL
    case May = 5; // CarbonInterface::MAY
    case June = 6; // CarbonInterface::JUNE
    case July = 7; // CarbonInterface::JULY
    case August = 8; // CarbonInterface::AUGUST
    case September = 9; // CarbonInterface::SEPTEMBER
    case October = 10; // CarbonInterface::OCTOBER
    case November = 11; // CarbonInterface::NOVEMBER
    case December = 12; // CarbonInterface::DECEMBER

    public static function int(self|int|null $value): ?int
    {
        return $value instanceof self ? $value->value : $value;
    }

    public static function fromNumber(int $number): self
    {
        $month = $number % CarbonInterface::MONTHS_PER_YEAR;

        return self::from($month + ($month < 1 ? CarbonInterface::MONTHS_PER_YEAR : 0));
    }

    public static function fromName(string $name, ?string $locale = null): self
    {
        try {
            return self::from(CarbonImmutable::parseFromLocale("$name 1", $locale)->month);
        } catch (InvalidFormatException $exception) {
            // Possibly current language expect a dot after short name, but it's missing
            if ($locale !== null && !mb_strlen($name) < 4 && !str_ends_with($name, '.')) {
                try {
                    return self::from(CarbonImmutable::parseFromLocale("$name. 1", $locale)->month);
                } catch (InvalidFormatException $e) {
                    // Throw previous error
                }
            }

            throw $exception;
        }
    }

    public function ofTheYear(CarbonImmutable|int|null $now = null): CarbonImmutable
    {
        if (\is_int($now)) {
            return CarbonImmutable::create($now, $this->value);
        }

        $modifier = $this->name.' 1st';

        return $now?->modify($modifier) ?? new CarbonImmutable($modifier);
    }

    public function locale(string $locale, ?CarbonImmutable $now = null): CarbonImmutable
    {
        return $this->ofTheYear($now)->locale($locale);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

enum Unit: string
{
    case Microsecond = 'microsecond';
    case Millisecond = 'millisecond';
    case Second = 'second';
    case Minute = 'minute';
    case Hour = 'hour';
    case Day = 'day';
    case Week = 'week';
    case Month = 'month';
    case Quarter = 'quarter';
    case Year = 'year';
    case Decade = 'decade';
    case Century = 'century';
    case Millennium = 'millennium';

    public static function toName(self|string $unit): string
    {
        return $unit instanceof self ? $unit->value : $unit;
    }

    /** @internal */
    public static function toNameIfUnit(mixed $unit): mixed
    {
        return $unit instanceof self ? $unit->value : $unit;
    }

    public static function fromName(string $name, ?string $locale = null): self
    {
        if ($locale !== null) {
            $messages = Translator::get($locale)->getMessages($locale) ?? [];

            if ($messages !== []) {
                $lowerName = mb_strtolower($name);

                foreach (self::cases() as $unit) {
                    foreach (['', '_from_now', '_ago', '_after', '_before'] as $suffix) {
                        $message = $messages[$unit->value.$suffix] ?? null;

                        if (\is_string($message)) {
                            $words = explode('|', mb_strtolower(preg_replace(
                                '/[{\[\]].+?[}\[\]]/',
                                '',
                                str_replace(':count', '', $message),
                            )));

                            foreach ($words as $word) {
                                if (trim($word) === $lowerName) {
                                    return $unit;
                                }
                            }
                        }
                    }
                }
            }
        }

        return self::from(CarbonImmutable::singularUnit($name));
    }

    public function singular(?string $locale = null): string
    {
        if ($locale !== null) {
            return trim(Translator::get($locale)->trans($this->value, [
                '%count%' => 1,
                ':count' => 1,
            ]), "1 \n\r\t\v\0");
        }

        return $this->value;
    }

    public function plural(?string $locale = null): string
    {
        if ($locale !== null) {
            return trim(Translator::get($locale)->trans($this->value, [
                '%count%' => 9,
                ':count' => 9,
            ]), "9 \n\r\t\v\0");
        }

        return CarbonImmutable::pluralUnit($this->value);
    }

    public function interval(int|float $value = 1): CarbonInterval
    {
        return CarbonInterval::fromString("$value $this->name");
    }

    public function locale(string $locale): CarbonInterval
    {
        return $this->interval()->locale($locale);
    }

    public function toPeriod(...$params): CarbonPeriod
    {
        return $this->interval()->toPeriod(...$params);
    }

    public function stepBy(mixed $interval, Unit|string|null $unit = null): CarbonPeriod
    {
        return $this->interval()->stepBy($interval, $unit);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use DateTimeInterface;

interface CarbonConverterInterface
{
    public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface;
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

trait ObjectInitialisation
{
    /**
     * True when parent::__construct has been called.
     *
     * @var string
     */
    protected $constructedObjectId;
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use BackedEnum;
use BadMethodCallException;
use Carbon\CarbonConverterInterface;
use Carbon\CarbonInterface;
use Carbon\Exceptions\BadComparisonUnitException;
use Carbon\FactoryImmutable;
use Carbon\Month;
use Carbon\Unit;
use Carbon\WeekDay;
use Closure;
use DateInterval;
use DateTimeInterface;
use InvalidArgumentException;

/**
 * Trait Comparison.
 *
 * Comparison utils and testers. All the following methods return booleans.
 * nowWithSameTz
 *
 * Depends on the following methods:
 *
 * @method static        resolveCarbon($date)
 * @method static        copy()
 * @method static        nowWithSameTz()
 * @method static static yesterday($timezone = null)
 * @method static static tomorrow($timezone = null)
 */
trait Comparison
{
    protected bool $endOfTime = false;

    protected bool $startOfTime = false;

    /**
     * Determines if the instance is equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->eq(Carbon::parse('2018-07-25 12:45:16')); // true
     * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see equalTo()
     */
    public function eq(DateTimeInterface|string $date): bool
    {
        return $this->equalTo($date);
    }

    /**
     * Determines if the instance is equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->equalTo(Carbon::parse('2018-07-25 12:45:16')); // true
     * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:17'); // false
     * ```
     */
    public function equalTo(DateTimeInterface|string $date): bool
    {
        return $this == $this->resolveCarbon($date);
    }

    /**
     * Determines if the instance is not equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->ne(Carbon::parse('2018-07-25 12:45:16')); // false
     * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see notEqualTo()
     */
    public function ne(DateTimeInterface|string $date): bool
    {
        return $this->notEqualTo($date);
    }

    /**
     * Determines if the instance is not equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->notEqualTo(Carbon::parse('2018-07-25 12:45:16')); // false
     * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:17'); // true
     * ```
     */
    public function notEqualTo(DateTimeInterface|string $date): bool
    {
        return !$this->equalTo($date);
    }

    /**
     * Determines if the instance is greater (after) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see greaterThan()
     */
    public function gt(DateTimeInterface|string $date): bool
    {
        return $this->greaterThan($date);
    }

    /**
     * Determines if the instance is greater (after) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false
     * ```
     */
    public function greaterThan(DateTimeInterface|string $date): bool
    {
        return $this > $this->resolveCarbon($date);
    }

    /**
     * Determines if the instance is greater (after) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see greaterThan()
     */
    public function isAfter(DateTimeInterface|string $date): bool
    {
        return $this->greaterThan($date);
    }

    /**
     * Determines if the instance is greater (after) than or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see greaterThanOrEqualTo()
     */
    public function gte(DateTimeInterface|string $date): bool
    {
        return $this->greaterThanOrEqualTo($date);
    }

    /**
     * Determines if the instance is greater (after) than or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:17'); // false
     * ```
     */
    public function greaterThanOrEqualTo(DateTimeInterface|string $date): bool
    {
        return $this >= $this->resolveCarbon($date);
    }

    /**
     * Determines if the instance is less (before) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see lessThan()
     */
    public function lt(DateTimeInterface|string $date): bool
    {
        return $this->lessThan($date);
    }

    /**
     * Determines if the instance is less (before) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:17'); // true
     * ```
     */
    public function lessThan(DateTimeInterface|string $date): bool
    {
        return $this < $this->resolveCarbon($date);
    }

    /**
     * Determines if the instance is less (before) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see lessThan()
     */
    public function isBefore(DateTimeInterface|string $date): bool
    {
        return $this->lessThan($date);
    }

    /**
     * Determines if the instance is less (before) or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see lessThanOrEqualTo()
     */
    public function lte(DateTimeInterface|string $date): bool
    {
        return $this->lessThanOrEqualTo($date);
    }

    /**
     * Determines if the instance is less (before) or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:17'); // true
     * ```
     */
    public function lessThanOrEqualTo(DateTimeInterface|string $date): bool
    {
        return $this <= $this->resolveCarbon($date);
    }

    /**
     * Determines if the instance is between two others.
     *
     * The third argument allow you to specify if bounds are included or not (true by default)
     * but for when you including/excluding bounds may produce different results in your application,
     * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->between('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01', false); // false
     * ```
     *
     * @param bool $equal Indicates if an equal to comparison should be done
     */
    public function between(DateTimeInterface|string $date1, DateTimeInterface|string $date2, bool $equal = true): bool
    {
        $date1 = $this->resolveCarbon($date1);
        $date2 = $this->resolveCarbon($date2);

        if ($date1->greaterThan($date2)) {
            [$date1, $date2] = [$date2, $date1];
        }

        if ($equal) {
            return $this >= $date1 && $this <= $date2;
        }

        return $this > $date1 && $this < $date2;
    }

    /**
     * Determines if the instance is between two others, bounds included.
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->betweenIncluded('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-25', '2018-08-01'); // true
     * ```
     */
    public function betweenIncluded(DateTimeInterface|string $date1, DateTimeInterface|string $date2): bool
    {
        return $this->between($date1, $date2, true);
    }

    /**
     * Determines if the instance is between two others, bounds excluded.
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->betweenExcluded('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-25', '2018-08-01'); // false
     * ```
     */
    public function betweenExcluded(DateTimeInterface|string $date1, DateTimeInterface|string $date2): bool
    {
        return $this->between($date1, $date2, false);
    }

    /**
     * Determines if the instance is between two others
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->isBetween('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->isBetween('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01', false); // false
     * ```
     *
     * @param bool $equal Indicates if an equal to comparison should be done
     */
    public function isBetween(DateTimeInterface|string $date1, DateTimeInterface|string $date2, bool $equal = true): bool
    {
        return $this->between($date1, $date2, $equal);
    }

    /**
     * Determines if the instance is a weekday.
     *
     * @example
     * ```
     * Carbon::parse('2019-07-14')->isWeekday(); // false
     * Carbon::parse('2019-07-15')->isWeekday(); // true
     * ```
     */
    public function isWeekday(): bool
    {
        return !$this->isWeekend();
    }

    /**
     * Determines if the instance is a weekend day.
     *
     * @example
     * ```
     * Carbon::parse('2019-07-14')->isWeekend(); // true
     * Carbon::parse('2019-07-15')->isWeekend(); // false
     * ```
     */
    public function isWeekend(): bool
    {
        return \in_array(
            $this->dayOfWeek,
            $this->transmitFactory(static fn () => static::getWeekendDays()),
            true,
        );
    }

    /**
     * Determines if the instance is yesterday.
     *
     * @example
     * ```
     * Carbon::yesterday()->isYesterday(); // true
     * Carbon::tomorrow()->isYesterday(); // false
     * ```
     */
    public function isYesterday(): bool
    {
        return $this->toDateString() === $this->transmitFactory(
            fn () => static::yesterday($this->getTimezone())->toDateString(),
        );
    }

    /**
     * Determines if the instance is today.
     *
     * @example
     * ```
     * Carbon::today()->isToday(); // true
     * Carbon::tomorrow()->isToday(); // false
     * ```
     */
    public function isToday(): bool
    {
        return $this->toDateString() === $this->nowWithSameTz()->toDateString();
    }

    /**
     * Determines if the instance is tomorrow.
     *
     * @example
     * ```
     * Carbon::tomorrow()->isTomorrow(); // true
     * Carbon::yesterday()->isTomorrow(); // false
     * ```
     */
    public function isTomorrow(): bool
    {
        return $this->toDateString() === $this->transmitFactory(
            fn () => static::tomorrow($this->getTimezone())->toDateString(),
        );
    }

    /**
     * Determines if the instance is in the future, ie. greater (after) than now.
     *
     * @example
     * ```
     * Carbon::now()->addHours(5)->isFuture(); // true
     * Carbon::now()->subHours(5)->isFuture(); // false
     * ```
     */
    public function isFuture(): bool
    {
        return $this->greaterThan($this->nowWithSameTz());
    }

    /**
     * Determines if the instance is in the past, ie. less (before) than now.
     *
     * @example
     * ```
     * Carbon::now()->subHours(5)->isPast(); // true
     * Carbon::now()->addHours(5)->isPast(); // false
     * ```
     */
    public function isPast(): bool
    {
        return $this->lessThan($this->nowWithSameTz());
    }

    /**
     * Determines if the instance is now or in the future, ie. greater (after) than or equal to now.
     *
     * @example
     * ```
     * Carbon::now()->isNowOrFuture(); // true
     * Carbon::now()->addHours(5)->isNowOrFuture(); // true
     * Carbon::now()->subHours(5)->isNowOrFuture(); // false
     * ```
     */
    public function isNowOrFuture(): bool
    {
        return $this->greaterThanOrEqualTo($this->nowWithSameTz());
    }

    /**
     * Determines if the instance is now or in the past, ie. less (before) than or equal to now.
     *
     * @example
     * ```
     * Carbon::now()->isNowOrPast(); // true
     * Carbon::now()->subHours(5)->isNowOrPast(); // true
     * Carbon::now()->addHours(5)->isNowOrPast(); // false
     * ```
     */
    public function isNowOrPast(): bool
    {
        return $this->lessThanOrEqualTo($this->nowWithSameTz());
    }

    /**
     * Determines if the instance is a leap year.
     *
     * @example
     * ```
     * Carbon::parse('2020-01-01')->isLeapYear(); // true
     * Carbon::parse('2019-01-01')->isLeapYear(); // false
     * ```
     */
    public function isLeapYear(): bool
    {
        return $this->rawFormat('L') === '1';
    }

    /**
     * Determines if the instance is a long year (using calendar year).
     *
     * ⚠️ This method completely ignores month and day to use the numeric year number,
     * it's not correct if the exact date matters. For instance as `2019-12-30` is already
     * in the first week of the 2020 year, if you want to know from this date if ISO week
     * year 2020 is a long year, use `isLongIsoYear` instead.
     *
     * @example
     * ```
     * Carbon::create(2015)->isLongYear(); // true
     * Carbon::create(2016)->isLongYear(); // false
     * ```
     *
     * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
     */
    public function isLongYear(): bool
    {
        return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === static::WEEKS_PER_YEAR + 1;
    }

    /**
     * Determines if the instance is a long year (using ISO 8601 year).
     *
     * @example
     * ```
     * Carbon::parse('2015-01-01')->isLongIsoYear(); // true
     * Carbon::parse('2016-01-01')->isLongIsoYear(); // true
     * Carbon::parse('2016-01-03')->isLongIsoYear(); // false
     * Carbon::parse('2019-12-29')->isLongIsoYear(); // false
     * Carbon::parse('2019-12-30')->isLongIsoYear(); // true
     * ```
     *
     * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
     */
    public function isLongIsoYear(): bool
    {
        return static::create($this->isoWeekYear, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
    }

    /**
     * Compares the formatted values of the two dates.
     *
     * @example
     * ```
     * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-12-13')); // true
     * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-06-14')); // false
     * ```
     *
     * @param string                   $format date formats to compare.
     * @param DateTimeInterface|string $date   instance to compare with or null to use current day.
     */
    public function isSameAs(string $format, DateTimeInterface|string $date): bool
    {
        return $this->rawFormat($format) === $this->resolveCarbon($date)->rawFormat($format);
    }

    /**
     * Determines if the instance is in the current unit given.
     *
     * @example
     * ```
     * Carbon::parse('2019-01-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // true
     * Carbon::parse('2018-12-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // false
     * ```
     *
     * @param string                   $unit singular unit string
     * @param DateTimeInterface|string $date instance to compare with or null to use current day.
     *
     * @throws BadComparisonUnitException
     *
     * @return bool
     */
    public function isSameUnit(string $unit, DateTimeInterface|string $date): bool
    {
        if ($unit === /* @call isSameUnit */ 'quarter') {
            $other = $this->resolveCarbon($date);

            return $other->year === $this->year && $other->quarter === $this->quarter;
        }

        $units = [
            // @call isSameUnit
            'year' => 'Y',
            // @call isSameUnit
            'month' => 'Y-n',
            // @call isSameUnit
            'week' => 'o-W',
            // @call isSameUnit
            'day' => 'Y-m-d',
            // @call isSameUnit
            'hour' => 'Y-m-d H',
            // @call isSameUnit
            'minute' => 'Y-m-d H:i',
            // @call isSameUnit
            'second' => 'Y-m-d H:i:s',
            // @call isSameUnit
            'milli' => 'Y-m-d H:i:s.v',
            // @call isSameUnit
            'millisecond' => 'Y-m-d H:i:s.v',
            // @call isSameUnit
            'micro' => 'Y-m-d H:i:s.u',
            // @call isSameUnit
            'microsecond' => 'Y-m-d H:i:s.u',
        ];

        if (isset($units[$unit])) {
            return $this->isSameAs($units[$unit], $date);
        }

        if (isset($this->$unit)) {
            return $this->resolveCarbon($date)->$unit === $this->$unit;
        }

        if ($this->isLocalStrictModeEnabled()) {
            throw new BadComparisonUnitException($unit);
        }

        return false;
    }

    /**
     * Determines if the instance is in the current unit given.
     *
     * @example
     * ```
     * Carbon::now()->isCurrentUnit('hour'); // true
     * Carbon::now()->subHours(2)->isCurrentUnit('hour'); // false
     * ```
     *
     * @param string $unit The unit to test.
     *
     * @throws BadMethodCallException
     */
    public function isCurrentUnit(string $unit): bool
    {
        return $this->{'isSame'.ucfirst($unit)}('now');
    }

    /**
     * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
     *
     * @example
     * ```
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-03-01')); // true
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-04-01')); // false
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01')); // false
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01'), false); // true
     * ```
     *
     * @param DateTimeInterface|string $date       The instance to compare with or null to use current day.
     * @param bool                     $ofSameYear Check if it is the same month in the same year.
     *
     * @return bool
     */
    public function isSameQuarter(DateTimeInterface|string $date, bool $ofSameYear = true): bool
    {
        $date = $this->resolveCarbon($date);

        return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date));
    }

    /**
     * Checks if the passed in date is in the same month as the instance´s month.
     *
     * @example
     * ```
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-01-01')); // true
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-02-01')); // false
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01')); // false
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01'), false); // true
     * ```
     *
     * @param DateTimeInterface|string $date       The instance to compare with or null to use the current date.
     * @param bool                     $ofSameYear Check if it is the same month in the same year.
     *
     * @return bool
     */
    public function isSameMonth(DateTimeInterface|string $date, bool $ofSameYear = true): bool
    {
        return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date);
    }

    /**
     * Checks if this day is a specific day of the week.
     *
     * @example
     * ```
     * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::WEDNESDAY); // true
     * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::FRIDAY); // false
     * Carbon::parse('2019-07-17')->isDayOfWeek('Wednesday'); // true
     * Carbon::parse('2019-07-17')->isDayOfWeek('Friday'); // false
     * ```
     *
     * @param int|string $dayOfWeek
     *
     * @return bool
     */
    public function isDayOfWeek($dayOfWeek): bool
    {
        if (\is_string($dayOfWeek) && \defined($constant = static::class.'::'.strtoupper($dayOfWeek))) {
            $dayOfWeek = \constant($constant);
        }

        return $this->dayOfWeek === $dayOfWeek;
    }

    /**
     * Check if its the birthday. Compares the date/month values of the two dates.
     *
     * @example
     * ```
     * Carbon::now()->subYears(5)->isBirthday(); // true
     * Carbon::now()->subYears(5)->subDay()->isBirthday(); // false
     * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-05')); // true
     * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-06')); // false
     * ```
     *
     * @param DateTimeInterface|string|null $date The instance to compare with or null to use current day.
     *
     * @return bool
     */
    public function isBirthday(DateTimeInterface|string|null $date = null): bool
    {
        return $this->isSameAs('md', $date ?? 'now');
    }

    /**
     * Check if today is the last day of the Month
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28')->isLastOfMonth(); // true
     * Carbon::parse('2019-03-28')->isLastOfMonth(); // false
     * Carbon::parse('2019-03-30')->isLastOfMonth(); // false
     * Carbon::parse('2019-03-31')->isLastOfMonth(); // true
     * Carbon::parse('2019-04-30')->isLastOfMonth(); // true
     * ```
     */
    public function isLastOfMonth(): bool
    {
        return $this->day === $this->daysInMonth;
    }

    /**
     * Check if the instance is start of a given unit (tolerating a given interval).
     *
     * @example
     * ```
     * // Check if a date-time is the first 15 minutes of the hour it's in
     * Carbon::parse('2019-02-28 20:13:00')->isStartOfUnit(Unit::Hour, '15 minutes'); // true
     * ```
     */
    public function isStartOfUnit(
        Unit $unit,
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
        mixed ...$params,
    ): bool {
        $interval ??= match ($unit) {
            Unit::Day, Unit::Hour, Unit::Minute, Unit::Second, Unit::Millisecond, Unit::Microsecond => Unit::Microsecond,
            default => Unit::Day,
        };

        $startOfUnit = $this->avoidMutation()->startOf($unit, ...$params);
        $startOfUnitDateTime = $startOfUnit->rawFormat('Y-m-d H:i:s.u');
        $maximumDateTime = $startOfUnit
            ->add($interval instanceof Unit ? '1  '.$interval->value : $interval)
            ->rawFormat('Y-m-d H:i:s.u');

        if ($maximumDateTime < $startOfUnitDateTime) {
            return false;
        }

        return $this->rawFormat('Y-m-d H:i:s.u') < $maximumDateTime;
    }

    /**
     * Check if the instance is end of a given unit (tolerating a given interval).
     *
     * @example
     * ```
     * // Check if a date-time is the last 15 minutes of the hour it's in
     * Carbon::parse('2019-02-28 20:13:00')->isEndOfUnit(Unit::Hour, '15 minutes'); // false
     * ```
     */
    public function isEndOfUnit(
        Unit $unit,
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
        mixed ...$params,
    ): bool {
        $interval ??= match ($unit) {
            Unit::Day, Unit::Hour, Unit::Minute, Unit::Second, Unit::Millisecond, Unit::Microsecond => Unit::Microsecond,
            default => Unit::Day,
        };

        $endOfUnit = $this->avoidMutation()->endOf($unit, ...$params);
        $endOfUnitDateTime = $endOfUnit->rawFormat('Y-m-d H:i:s.u');
        $minimumDateTime = $endOfUnit
            ->sub($interval instanceof Unit ? '1  '.$interval->value : $interval)
            ->rawFormat('Y-m-d H:i:s.u');

        if ($minimumDateTime > $endOfUnitDateTime) {
            return false;
        }

        return $this->rawFormat('Y-m-d H:i:s.u') > $minimumDateTime;
    }

    /**
     * Determines if the instance is start of millisecond (first microsecond by default but interval can be customized).
     */
    public function isStartOfMillisecond(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Millisecond, $interval);
    }

    /**
     * Determines if the instance is end of millisecond (last microsecond by default but interval can be customized).
     */
    public function isEndOfMillisecond(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Millisecond, $interval);
    }

    /**
     * Determines if the instance is start of second (first microsecond by default but interval can be customized).
     */
    public function isStartOfSecond(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Second, $interval);
    }

    /**
     * Determines if the instance is end of second (last microsecond by default but interval can be customized).
     */
    public function isEndOfSecond(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Second, $interval);
    }

    /**
     * Determines if the instance is start of minute (first microsecond by default but interval can be customized).
     */
    public function isStartOfMinute(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Minute, $interval);
    }

    /**
     * Determines if the instance is end of minute (last microsecond by default but interval can be customized).
     */
    public function isEndOfMinute(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Minute, $interval);
    }

    /**
     * Determines if the instance is start of hour (first microsecond by default but interval can be customized).
     */
    public function isStartOfHour(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Hour, $interval);
    }

    /**
     * Determines if the instance is end of hour (last microsecond by default but interval can be customized).
     */
    public function isEndOfHour(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Hour, $interval);
    }

    /**
     * Check if the instance is start of day / midnight.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 00:00:00')->isStartOfDay(); // true
     * Carbon::parse('2019-02-28 00:00:00.999999')->isStartOfDay(); // true
     * Carbon::parse('2019-02-28 00:00:01')->isStartOfDay(); // false
     * Carbon::parse('2019-02-28 00:00:00.000000')->isStartOfDay(true); // true
     * Carbon::parse('2019-02-28 00:00:00.000012')->isStartOfDay(true); // false
     * ```
     *
     * @param bool                                                           $checkMicroseconds check time at microseconds precision
     * @param Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval          if an interval is specified it will be used as precision
     *                                                                                          for instance with "15 minutes", it checks if current date-time
     *                                                                                          is in the last 15 minutes of the day, with Unit::Hour, it
     *                                                                                          checks if it's in the last hour of the day.
     */
    public function isStartOfDay(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|bool $checkMicroseconds = false,
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        if ($checkMicroseconds === true) {
            @trigger_error(
                "Since 3.8.0, it's deprecated to use \$checkMicroseconds.\n".
                "It will be removed in 4.0.0.\n".
                "Instead, you should use either isStartOfDay(interval: Unit::Microsecond) or isStartOfDay(interval: Unit::Second)\n".
                'And you can now use any custom interval as precision, such as isStartOfDay(interval: "15 minutes")',
                \E_USER_DEPRECATED,
            );
        }

        if ($interval === null && !\is_bool($checkMicroseconds)) {
            $interval = $checkMicroseconds;
        }

        if ($interval !== null) {
            if ($interval instanceof Unit) {
                $interval = '1  '.$interval->value;
            }

            $date = $this->rawFormat('Y-m-d');
            $time = $this->rawFormat('H:i:s.u');
            $maximum = $this->avoidMutation()->startOfDay()->add($interval);
            $maximumDate = $maximum->rawFormat('Y-m-d');

            if ($date === $maximumDate) {
                return $time < $maximum->rawFormat('H:i:s.u');
            }

            return $maximumDate > $date;
        }

        /* @var CarbonInterface $this */
        return $checkMicroseconds
            ? $this->rawFormat('H:i:s.u') === '00:00:00.000000'
            : $this->rawFormat('H:i:s') === '00:00:00';
    }

    /**
     * Check if the instance is end of day.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(); // true
     * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(); // true
     * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(); // true
     * Carbon::parse('2019-02-28 23:59:58.999999')->isEndOfDay(); // false
     * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(true); // true
     * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(true); // false
     * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(true); // false
     * ```
     *
     * @param bool                                                           $checkMicroseconds check time at microseconds precision
     * @param Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval          if an interval is specified it will be used as precision
     *                                                                                          for instance with "15 minutes", it checks if current date-time
     *                                                                                          is in the last 15 minutes of the day, with Unit::Hour, it
     *                                                                                          checks if it's in the last hour of the day.
     */
    public function isEndOfDay(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|bool $checkMicroseconds = false,
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        if ($checkMicroseconds === true) {
            @trigger_error(
                "Since 3.8.0, it's deprecated to use \$checkMicroseconds.\n".
                "It will be removed in 4.0.0.\n".
                "Instead, you should use either isEndOfDay(interval: Unit::Microsecond) or isEndOfDay(interval: Unit::Second)\n".
                'And you can now use any custom interval as precision, such as isEndOfDay(interval: "15 minutes")',
                \E_USER_DEPRECATED,
            );
        }

        if ($interval === null && !\is_bool($checkMicroseconds)) {
            $interval = $checkMicroseconds;
        }

        if ($interval !== null) {
            $date = $this->rawFormat('Y-m-d');
            $time = $this->rawFormat('H:i:s.u');
            $minimum = $this->avoidMutation()
                ->endOfDay()
                ->sub($interval instanceof Unit ? '1  '.$interval->value : $interval);
            $minimumDate = $minimum->rawFormat('Y-m-d');

            if ($date === $minimumDate) {
                return $time > $minimum->rawFormat('H:i:s.u');
            }

            return $minimumDate < $date;
        }

        /* @var CarbonInterface $this */
        return $checkMicroseconds
            ? $this->rawFormat('H:i:s.u') === '23:59:59.999999'
            : $this->rawFormat('H:i:s') === '23:59:59';
    }

    /**
     * Determines if the instance is start of week (first day by default but interval can be customized).
     *
     * @example
     * ```
     * Carbon::parse('2024-08-31')->startOfWeek()->isStartOfWeek(); // true
     * Carbon::parse('2024-08-31')->isStartOfWeek(); // false
     * ```
     */
    public function isStartOfWeek(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
        WeekDay|int|null $weekStartsAt = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Week, $interval, $weekStartsAt);
    }

    /**
     * Determines if the instance is end of week (last day by default but interval can be customized).
     *
     * @example
     * ```
     * Carbon::parse('2024-08-31')->endOfWeek()->isEndOfWeek(); // true
     * Carbon::parse('2024-08-31')->isEndOfWeek(); // false
     * ```
     */
    public function isEndOfWeek(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
        WeekDay|int|null $weekEndsAt = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Week, $interval, $weekEndsAt);
    }

    /**
     * Determines if the instance is start of month (first day by default but interval can be customized).
     */
    public function isStartOfMonth(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Month, $interval);
    }

    /**
     * Determines if the instance is end of month (last day by default but interval can be customized).
     */
    public function isEndOfMonth(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Month, $interval);
    }

    /**
     * Determines if the instance is start of quarter (first day by default but interval can be customized).
     */
    public function isStartOfQuarter(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Quarter, $interval);
    }

    /**
     * Determines if the instance is end of quarter (last day by default but interval can be customized).
     */
    public function isEndOfQuarter(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Quarter, $interval);
    }

    /**
     * Determines if the instance is start of year (first day by default but interval can be customized).
     */
    public function isStartOfYear(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Year, $interval);
    }

    /**
     * Determines if the instance is end of year (last day by default but interval can be customized).
     */
    public function isEndOfYear(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Year, $interval);
    }

    /**
     * Determines if the instance is start of decade (first day by default but interval can be customized).
     */
    public function isStartOfDecade(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Decade, $interval);
    }

    /**
     * Determines if the instance is end of decade (last day by default but interval can be customized).
     */
    public function isEndOfDecade(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Decade, $interval);
    }

    /**
     * Determines if the instance is start of century (first day by default but interval can be customized).
     */
    public function isStartOfCentury(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Century, $interval);
    }

    /**
     * Determines if the instance is end of century (last day by default but interval can be customized).
     */
    public function isEndOfCentury(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Century, $interval);
    }

    /**
     * Determines if the instance is start of millennium (first day by default but interval can be customized).
     */
    public function isStartOfMillennium(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isStartOfUnit(Unit::Millennium, $interval);
    }

    /**
     * Determines if the instance is end of millennium (last day by default but interval can be customized).
     */
    public function isEndOfMillennium(
        Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null,
    ): bool {
        return $this->isEndOfUnit(Unit::Millennium, $interval);
    }

    /**
     * Check if the instance is start of day / midnight.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 00:00:00')->isMidnight(); // true
     * Carbon::parse('2019-02-28 00:00:00.999999')->isMidnight(); // true
     * Carbon::parse('2019-02-28 00:00:01')->isMidnight(); // false
     * ```
     */
    public function isMidnight(): bool
    {
        return $this->isStartOfDay();
    }

    /**
     * Check if the instance is midday.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 11:59:59.999999')->isMidday(); // false
     * Carbon::parse('2019-02-28 12:00:00')->isMidday(); // true
     * Carbon::parse('2019-02-28 12:00:00.999999')->isMidday(); // true
     * Carbon::parse('2019-02-28 12:00:01')->isMidday(); // false
     * ```
     */
    public function isMidday(): bool
    {
        /* @var CarbonInterface $this */
        return $this->rawFormat('G:i:s') === static::$midDayAt.':00:00';
    }

    /**
     * Checks if the (date)time string is in a given format.
     *
     * @example
     * ```
     * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
     * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
     * ```
     */
    public static function hasFormat(string $date, string $format): bool
    {
        return FactoryImmutable::getInstance()->hasFormat($date, $format);
    }

    /**
     * Checks if the (date)time string is in a given format.
     *
     * @example
     * ```
     * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true
     * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false
     * ```
     *
     * @param string $date
     * @param string $format
     *
     * @return bool
     */
    public static function hasFormatWithModifiers(?string $date, string $format): bool
    {
        return FactoryImmutable::getInstance()->hasFormatWithModifiers($date, $format);
    }

    /**
     * Checks if the (date)time string is in a given format and valid to create a
     * new instance.
     *
     * @example
     * ```
     * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true
     * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false
     * ```
     */
    public static function canBeCreatedFromFormat(?string $date, string $format): bool
    {
        if ($date === null) {
            return false;
        }

        try {
            // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string
            // doesn't match the format in any way.
            if (!static::rawCreateFromFormat($format, $date)) {
                return false;
            }
        } catch (InvalidArgumentException) {
            return false;
        }

        return static::hasFormatWithModifiers($date, $format);
    }

    /**
     * Returns true if the current date matches the given string.
     *
     * @example
     * ```
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2018')); // false
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('06-02')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06-02')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('Sunday')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('June')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:45')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:00')); // false
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12h')); // true
     * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3pm')); // true
     * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3am')); // false
     * ```
     *
     * @param string $tester day name, month name, hour, date, etc. as string
     */
    public function is(WeekDay|Month|string $tester): bool
    {
        if ($tester instanceof BackedEnum) {
            $tester = $tester->name;
        }

        $tester = trim($tester);

        if (preg_match('/^\d+$/', $tester)) {
            return $this->year === (int) $tester;
        }

        if (preg_match('/^(?:Jan|January|Feb|February|Mar|March|Apr|April|May|Jun|June|Jul|July|Aug|August|Sep|September|Oct|October|Nov|November|Dec|December)$/i', $tester)) {
            return $this->isSameMonth(
                $this->transmitFactory(static fn () => static::parse("$tester 1st")),
                false,
            );
        }

        if (preg_match('/^\d{3,}-\d{1,2}$/', $tester)) {
            return $this->isSameMonth(
                $this->transmitFactory(static fn () => static::parse($tester)),
            );
        }

        if (preg_match('/^(\d{1,2})-(\d{1,2})$/', $tester, $match)) {
            return $this->month === (int) $match[1] && $this->day === (int) $match[2];
        }

        $modifier = preg_replace('/(\d)h$/i', '$1:00', $tester);

        /* @var CarbonInterface $max */
        $median = $this->transmitFactory(static fn () => static::parse('5555-06-15 12:30:30.555555'))
            ->modify($modifier);
        $current = $this->avoidMutation();
        /* @var CarbonInterface $other */
        $other = $this->avoidMutation()->modify($modifier);

        if ($current->eq($other)) {
            return true;
        }

        if (preg_match('/\d:\d{1,2}:\d{1,2}$/', $tester)) {
            return $current->startOfSecond()->eq($other);
        }

        if (preg_match('/\d:\d{1,2}$/', $tester)) {
            return $current->startOfMinute()->eq($other);
        }

        if (preg_match('/\d(?:h|am|pm)$/', $tester)) {
            return $current->startOfHour()->eq($other);
        }

        if (preg_match(
            '/^(?:january|february|march|april|may|june|july|august|september|october|november|december)(?:\s+\d+)?$/i',
            $tester,
        )) {
            return $current->startOfMonth()->eq($other->startOfMonth());
        }

        $units = [
            'month' => [1, 'year'],
            'day' => [1, 'month'],
            'hour' => [0, 'day'],
            'minute' => [0, 'hour'],
            'second' => [0, 'minute'],
            'microsecond' => [0, 'second'],
        ];

        foreach ($units as $unit => [$minimum, $startUnit]) {
            if ($minimum === $median->$unit) {
                $current = $current->startOf($startUnit);

                break;
            }
        }

        return $current->eq($other);
    }

    /**
     * Returns true if the date was created using CarbonImmutable::startOfTime()
     *
     * @return bool
     */
    public function isStartOfTime(): bool
    {
        return $this->startOfTime ?? false;
    }

    /**
     * Returns true if the date was created using CarbonImmutable::endOfTime()
     *
     * @return bool
     */
    public function isEndOfTime(): bool
    {
        return $this->endOfTime ?? false;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\FactoryImmutable;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Static config for localization.
 */
trait StaticLocalization
{
    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     */
    public static function setHumanDiffOptions(int $humanDiffOptions): void
    {
        FactoryImmutable::getDefaultInstance()->setHumanDiffOptions($humanDiffOptions);
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     */
    public static function enableHumanDiffOption(int $humanDiffOption): void
    {
        FactoryImmutable::getDefaultInstance()->enableHumanDiffOption($humanDiffOption);
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     */
    public static function disableHumanDiffOption(int $humanDiffOption): void
    {
        FactoryImmutable::getDefaultInstance()->disableHumanDiffOption($humanDiffOption);
    }

    /**
     * Return default humanDiff() options (merged flags as integer).
     */
    public static function getHumanDiffOptions(): int
    {
        return FactoryImmutable::getInstance()->getHumanDiffOptions();
    }

    /**
     * Set the default translator instance to use.
     *
     * @param TranslatorInterface $translator
     *
     * @return void
     */
    public static function setTranslator(TranslatorInterface $translator): void
    {
        FactoryImmutable::getDefaultInstance()->setTranslator($translator);
    }

    /**
     * Initialize the default translator instance if necessary.
     */
    public static function getTranslator(): TranslatorInterface
    {
        return FactoryImmutable::getInstance()->getTranslator();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Carbon;
use Carbon\CarbonImmutable;

/**
 * Trait Mutability.
 *
 * Utils to know if the current object is mutable or immutable and convert it.
 */
trait Mutability
{
    use Cast;

    /**
     * Returns true if the current class/instance is mutable.
     */
    public static function isMutable(): bool
    {
        return false;
    }

    /**
     * Returns true if the current class/instance is immutable.
     */
    public static function isImmutable(): bool
    {
        return !static::isMutable();
    }

    /**
     * Return a mutable copy of the instance.
     */
    public function toMutable(): Carbon
    {
        return $this->cast(Carbon::class);
    }

    /**
     * Return an immutable copy of the instance.
     */
    public function toImmutable(): CarbonImmutable
    {
        // Immutable objects are fine as is (uncloned)
        if ($this::class === CarbonImmutable::class) {
            return $this;
        }

        return $this->cast(CarbonImmutable::class);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Exceptions\InvalidCastException;
use DateTimeInterface;

/**
 * Trait Cast.
 *
 * Utils to cast into an other class.
 */
trait Cast
{
    /**
     * Cast the current instance into the given class.
     *
     * @template T
     *
     * @param class-string<T> $className The $className::instance() method will be called to cast the current object.
     *
     * @return T
     */
    public function cast(string $className): mixed
    {
        if (!method_exists($className, 'instance')) {
            if (is_a($className, DateTimeInterface::class, true)) {
                return $className::createFromFormat('U.u', $this->rawFormat('U.u'))
                    ->setTimezone($this->getTimezone());
            }

            throw new InvalidCastException("$className has not the instance() method needed to cast the date.");
        }

        return $className::instance($this);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Exceptions\InvalidFormatException;
use Carbon\FactoryImmutable;
use DateTimeZone;
use ReturnTypeWillChange;
use Throwable;

/**
 * Trait Serialization.
 *
 * Serialization and JSON stuff.
 *
 * Depends on the following properties:
 *
 * @property int $year
 * @property int $month
 * @property int $daysInMonth
 * @property int $quarter
 *
 * Depends on the following methods:
 *
 * @method string|static locale(string $locale = null, string ...$fallbackLocales)
 * @method string        toJSON()
 */
trait Serialization
{
    use ObjectInitialisation;

    /**
     * List of key to use for dump/serialization.
     *
     * @var string[]
     */
    protected array $dumpProperties = ['date', 'timezone_type', 'timezone'];

    /**
     * Locale to dump comes here before serialization.
     *
     * @var string|null
     */
    protected $dumpLocale;

    /**
     * Embed date properties to dump in a dedicated variables so it won't overlap native
     * DateTime ones.
     *
     * @var array|null
     */
    protected $dumpDateProperties;

    /**
     * Return a serialized string of the instance.
     */
    public function serialize(): string
    {
        return serialize($this);
    }

    /**
     * Create an instance from a serialized string.
     *
     * If $value is not from a trusted source, consider using the allowed_classes option to limit
     * the types of objects that can be built, for instance:
     *
     * @example
     * ```php
     * $object = Carbon::fromSerialized($value, ['allowed_classes' => [Carbon::class, CarbonImmutable::class]]);
     * ```
     *
     * @param \Stringable|string $value
     * @param array              $options example: ['allowed_classes' => [CarbonImmutable::class]]
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function fromSerialized($value, array $options = []): static
    {
        $instance = @unserialize((string) $value, $options);

        if (!$instance instanceof static) {
            throw new InvalidFormatException("Invalid serialized value: $value");
        }

        return $instance;
    }

    /**
     * The __set_state handler.
     *
     * @param string|array $dump
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public static function __set_state($dump): static
    {
        if (\is_string($dump)) {
            return static::parse($dump);
        }

        /** @var \DateTimeInterface $date */
        $date = get_parent_class(static::class) && method_exists(parent::class, '__set_state')
            ? parent::__set_state((array) $dump)
            : (object) $dump;

        return static::instance($date);
    }

    /**
     * Returns the values to dump on serialize() called on.
     *
     * @return array
     */
    public function __serialize(): array
    {
        // @codeCoverageIgnoreStart
        if (isset($this->timezone_type, $this->timezone, $this->date)) {
            return [
                'date' => $this->date,
                'timezone_type' => $this->timezone_type,
                'timezone' => $this->dumpTimezone($this->timezone),
            ];
        }
        // @codeCoverageIgnoreEnd

        $timezone = $this->getTimezone();
        $export = [
            'date' => $this->format('Y-m-d H:i:s.u'),
            'timezone_type' => $timezone->getType(),
            'timezone' => $timezone->getName(),
        ];

        // @codeCoverageIgnoreStart
        if (\extension_loaded('msgpack') && isset($this->constructedObjectId)) {
            $timezone = $this->timezone ?? null;
            $export['dumpDateProperties'] = [
                'date' => $this->format('Y-m-d H:i:s.u'),
                'timezone' => $this->dumpTimezone($timezone),
            ];
        }
        // @codeCoverageIgnoreEnd

        if ($this->localTranslator ?? null) {
            $export['dumpLocale'] = $this->locale ?? null;
        }

        return $export;
    }

    /**
     * Set locale if specified on unserialize() called.
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        try {
            $this->__construct($data['date'] ?? null, $data['timezone'] ?? null);
        } catch (Throwable $exception) {
            if (!isset($data['dumpDateProperties']['date'], $data['dumpDateProperties']['timezone'])) {
                throw $exception;
            }

            try {
                // FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later.
                ['date' => $date, 'timezone' => $timezone] = $data['dumpDateProperties'];
                $this->__construct($date, $timezone);
            } catch (Throwable) {
                throw $exception;
            }
        }
        // @codeCoverageIgnoreEnd

        if (isset($data['dumpLocale'])) {
            $this->locale($data['dumpLocale']);
        }
    }

    /**
     * Prepare the object for JSON serialization.
     */
    public function jsonSerialize(): mixed
    {
        $serializer = $this->localSerializer
            ?? $this->getFactory()->getSettings()['toJsonFormat']
            ?? null;

        if ($serializer) {
            return \is_string($serializer)
                ? $this->rawFormat($serializer)
                : $serializer($this);
        }

        return $this->toJSON();
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather transform Carbon object before the serialization.
     *
     * JSON serialize all Carbon instances using the given callback.
     */
    public static function serializeUsing(string|callable|null $format): void
    {
        FactoryImmutable::getDefaultInstance()->serializeUsing($format);
    }

    /**
     * Cleanup properties attached to the public scope of DateTime when a dump of the date is requested.
     * foreach ($date as $_) {}
     * serializer($date)
     * var_export($date)
     * get_object_vars($date)
     */
    public function cleanupDumpProperties(): self
    {
        // @codeCoverageIgnoreStart
        if (PHP_VERSION < 8.2) {
            foreach ($this->dumpProperties as $property) {
                if (isset($this->$property)) {
                    unset($this->$property);
                }
            }
        }
        // @codeCoverageIgnoreEnd

        return $this;
    }

    /** @codeCoverageIgnore */
    private function dumpTimezone(mixed $timezone): mixed
    {
        return $timezone instanceof DateTimeZone ? $timezone->getName() : $timezone;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterval;
use Carbon\Exceptions\InvalidIntervalException;
use DateInterval;

/**
 * Trait to call rounding methods to interval or the interval of a period.
 */
trait IntervalRounding
{
    protected function callRoundMethod(string $method, array $parameters): ?static
    {
        $action = substr($method, 0, 4);

        if ($action !== 'ceil') {
            $action = substr($method, 0, 5);
        }

        if (\in_array($action, ['round', 'floor', 'ceil'])) {
            return $this->{$action.'Unit'}(substr($method, \strlen($action)), ...$parameters);
        }

        return null;
    }

    protected function roundWith(DateInterval|string|float|int $precision, callable|string $function): ?static
    {
        $unit = 'second';

        if ($precision instanceof DateInterval) {
            $precision = CarbonInterval::instance($precision)->forHumans(['locale' => 'en']);
        }

        if (\is_string($precision) && preg_match('/^\s*(?<precision>\d+)?\s*(?<unit>\w+)(?<other>\W.*)?$/', $precision, $match)) {
            if (trim($match['other'] ?? '') !== '') {
                throw new InvalidIntervalException('Rounding is only possible with single unit intervals.');
            }

            $precision = (int) ($match['precision'] ?: 1);
            $unit = $match['unit'];
        }

        return $this->roundUnit($unit, $precision, $function);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use Carbon\CarbonTimeZone;
use Carbon\Factory;
use Carbon\FactoryImmutable;
use Closure;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;

trait Test
{
    ///////////////////////////////////////////////////////////////////
    ///////////////////////// TESTING AIDS ////////////////////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Set a Carbon instance (real or mock) to be returned when a "now"
     * instance is created.  The provided instance will be returned
     * specifically under the following conditions:
     *   - A call to the static now() method, ex. Carbon::now()
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
     *   - When a string containing the desired time is passed to Carbon::parse().
     *
     * Note the timezone parameter was left out of the examples above and
     * has no affect as the mock value will be returned regardless of its value.
     *
     * Only the moment is mocked with setTestNow(), the timezone will still be the one passed
     * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()).
     *
     * To clear the test instance call this method using the default
     * parameter of null.
     *
     * /!\ Use this method for unit tests only.
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
     */
    public static function setTestNow(mixed $testNow = null): void
    {
        FactoryImmutable::getDefaultInstance()->setTestNow($testNow);
    }

    /**
     * Set a Carbon instance (real or mock) to be returned when a "now"
     * instance is created.  The provided instance will be returned
     * specifically under the following conditions:
     *   - A call to the static now() method, ex. Carbon::now()
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
     *   - When a string containing the desired time is passed to Carbon::parse().
     *
     * It will also align default timezone (e.g. call date_default_timezone_set()) with
     * the second argument or if null, with the timezone of the given date object.
     *
     * To clear the test instance call this method using the default
     * parameter of null.
     *
     * /!\ Use this method for unit tests only.
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
     */
    public static function setTestNowAndTimezone($testNow = null, $timezone = null): void
    {
        FactoryImmutable::getDefaultInstance()->setTestNowAndTimezone($testNow, $timezone);
    }

    /**
     * Temporarily sets a static date to be used within the callback.
     * Using setTestNow to set the date, executing the callback, then
     * clearing the test instance.
     *
     * /!\ Use this method for unit tests only.
     *
     * @template T
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow  real or mock Carbon instance
     * @param Closure(): T                                       $callback
     *
     * @return T
     */
    public static function withTestNow(mixed $testNow, callable $callback): mixed
    {
        return FactoryImmutable::getDefaultInstance()->withTestNow($testNow, $callback);
    }

    /**
     * Get the Carbon instance (real or mock) to be returned when a "now"
     * instance is created.
     *
     * @return Closure|CarbonInterface|null the current instance used for testing
     */
    public static function getTestNow(): Closure|CarbonInterface|null
    {
        return FactoryImmutable::getInstance()->getTestNow();
    }

    /**
     * Determine if there is a valid test instance set. A valid test instance
     * is anything that is not null.
     *
     * @return bool true if there is a test instance, otherwise false
     */
    public static function hasTestNow(): bool
    {
        return FactoryImmutable::getInstance()->hasTestNow();
    }

    /**
     * Get the mocked date passed in setTestNow() and if it's a Closure, execute it.
     */
    protected static function getMockedTestNow(DateTimeZone|string|int|null $timezone): ?CarbonInterface
    {
        $testNow = FactoryImmutable::getInstance()->handleTestNowClosure(static::getTestNow(), $timezone);

        if ($testNow === null) {
            return null;
        }

        $testNow = $testNow->avoidMutation();

        return $timezone ? $testNow->setTimezone($timezone) : $testNow;
    }

    private function mockConstructorParameters(&$time, ?CarbonTimeZone $timezone): void
    {
        $clock = $this->clock?->unwrap();
        $now = $clock instanceof Factory
            ? $clock->getTestNow()
            : $this->nowFromClock($timezone);
        $testInstance = $now ?? self::getMockedTestNowClone($timezone);

        if (!$testInstance) {
            return;
        }

        if ($testInstance instanceof DateTimeInterface) {
            $testInstance = $testInstance->setTimezone($timezone ?? date_default_timezone_get());
        }

        if (static::hasRelativeKeywords($time)) {
            $testInstance = $testInstance->modify($time);
        }

        $factory = $this->getClock()?->unwrap();

        if (!($factory instanceof Factory)) {
            $factory = FactoryImmutable::getInstance();
        }

        $testInstance = $factory->handleTestNowClosure($testInstance, $timezone);

        $time = $testInstance instanceof self
            ? $testInstance->rawFormat(static::MOCK_DATETIME_FORMAT)
            : $testInstance->format(static::MOCK_DATETIME_FORMAT);
    }

    private static function getMockedTestNowClone($timezone): CarbonInterface|self|null
    {
        $mock = static::getMockedTestNow($timezone);

        return $mock ? clone $mock : null;
    }

    private function nowFromClock(?CarbonTimeZone $timezone): ?DateTimeImmutable
    {
        $now = $this->clock?->now();

        return $now && $timezone ? $now->setTimezone($timezone) : null;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use DateTimeZone;

/**
 * Trait Timestamp.
 */
trait Timestamp
{
    /**
     * Create a Carbon instance from a timestamp and set the timezone (UTC by default).
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    #[\ReturnTypeWillChange]
    public static function createFromTimestamp(
        float|int|string $timestamp,
        DateTimeZone|string|int|null $timezone = null,
    ): static {
        $date = static::createFromTimestampUTC($timestamp);

        return $timezone === null ? $date : $date->setTimezone($timezone);
    }

    /**
     * Create a Carbon instance from a timestamp keeping the timezone to UTC.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public static function createFromTimestampUTC(float|int|string $timestamp): static
    {
        [$integer, $decimal] = self::getIntegerAndDecimalParts($timestamp);
        $delta = floor($decimal / static::MICROSECONDS_PER_SECOND);
        $integer += $delta;
        $decimal -= $delta * static::MICROSECONDS_PER_SECOND;
        $decimal = str_pad((string) $decimal, 6, '0', STR_PAD_LEFT);

        return static::rawCreateFromFormat('U u', "$integer $decimal");
    }

    /**
     * Create a Carbon instance from a timestamp in milliseconds.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     *
     * @param float|int|string $timestamp
     *
     * @return static
     */
    public static function createFromTimestampMsUTC($timestamp): static
    {
        [$milliseconds, $microseconds] = self::getIntegerAndDecimalParts($timestamp, 3);
        $sign = $milliseconds < 0 || ($milliseconds === 0.0 && $microseconds < 0) ? -1 : 1;
        $milliseconds = abs($milliseconds);
        $microseconds = $sign * abs($microseconds) + static::MICROSECONDS_PER_MILLISECOND * ($milliseconds % static::MILLISECONDS_PER_SECOND);
        $seconds = $sign * floor($milliseconds / static::MILLISECONDS_PER_SECOND);
        $delta = floor($microseconds / static::MICROSECONDS_PER_SECOND);
        $seconds = (int) ($seconds + $delta);
        $microseconds -= $delta * static::MICROSECONDS_PER_SECOND;
        $microseconds = str_pad((string) (int) $microseconds, 6, '0', STR_PAD_LEFT);

        return static::rawCreateFromFormat('U u', "$seconds $microseconds");
    }

    /**
     * Create a Carbon instance from a timestamp in milliseconds.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public static function createFromTimestampMs(
        float|int|string $timestamp,
        DateTimeZone|string|int|null $timezone = null,
    ): static {
        $date = static::createFromTimestampMsUTC($timestamp);

        return $timezone === null ? $date : $date->setTimezone($timezone);
    }

    /**
     * Set the instance's timestamp.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public function timestamp(float|int|string $timestamp): static
    {
        return $this->setTimestamp($timestamp);
    }

    /**
     * Returns a timestamp rounded with the given precision (6 by default).
     *
     * @example getPreciseTimestamp()   1532087464437474 (microsecond maximum precision)
     * @example getPreciseTimestamp(6)  1532087464437474
     * @example getPreciseTimestamp(5)  153208746443747  (1/100000 second precision)
     * @example getPreciseTimestamp(4)  15320874644375   (1/10000 second precision)
     * @example getPreciseTimestamp(3)  1532087464437    (millisecond precision)
     * @example getPreciseTimestamp(2)  153208746444     (1/100 second precision)
     * @example getPreciseTimestamp(1)  15320874644      (1/10 second precision)
     * @example getPreciseTimestamp(0)  1532087464       (second precision)
     * @example getPreciseTimestamp(-1) 153208746        (10 second precision)
     * @example getPreciseTimestamp(-2) 15320875         (100 second precision)
     *
     * @param int $precision
     *
     * @return float
     */
    public function getPreciseTimestamp($precision = 6): float
    {
        return round(((float) $this->rawFormat('Uu')) / pow(10, 6 - $precision));
    }

    /**
     * Returns the milliseconds timestamps used amongst other by Date javascript objects.
     *
     * @return float
     */
    public function valueOf(): float
    {
        return $this->getPreciseTimestamp(3);
    }

    /**
     * Returns the timestamp with millisecond precision.
     *
     * @return int
     */
    public function getTimestampMs(): int
    {
        return (int) $this->getPreciseTimestamp(3);
    }

    /**
     * @alias getTimestamp
     *
     * Returns the UNIX timestamp for the current date.
     *
     * @return int
     */
    public function unix(): int
    {
        return $this->getTimestamp();
    }

    /**
     * Return an array with integer part digits and decimals digits split from one or more positive numbers
     * (such as timestamps) as string with the given number of decimals (6 by default).
     *
     * By splitting integer and decimal, this method obtain a better precision than
     * number_format when the input is a string.
     *
     * @param float|int|string $numbers  one or more numbers
     * @param int              $decimals number of decimals precision (6 by default)
     *
     * @return array 0-index is integer part, 1-index is decimal part digits
     */
    private static function getIntegerAndDecimalParts($numbers, $decimals = 6): array
    {
        if (\is_int($numbers) || \is_float($numbers)) {
            $numbers = number_format($numbers, $decimals, '.', '');
        }

        $sign = str_starts_with($numbers, '-') ? -1 : 1;
        $integer = 0;
        $decimal = 0;

        foreach (preg_split('`[^\d.]+`', $numbers) as $chunk) {
            [$integerPart, $decimalPart] = explode('.', "$chunk.");

            $integer += (int) $integerPart;
            $decimal += (float) ("0.$decimalPart");
        }

        $overflow = floor($decimal);
        $integer += $overflow;
        $decimal -= $overflow;

        return [$sign * $integer, $decimal === 0.0 ? 0.0 : $sign * round($decimal * pow(10, $decimals))];
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\FactoryImmutable;
use Closure;

/**
 * Trait ToStringFormat.
 *
 * Handle global format customization for string cast of the object.
 */
trait ToStringFormat
{
    /**
     * Reset the format used to the default when type juggling a Carbon instance to a string
     *
     * @return void
     */
    public static function resetToStringFormat(): void
    {
        FactoryImmutable::getDefaultInstance()->resetToStringFormat();
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather let Carbon object being cast to string with DEFAULT_TO_STRING_FORMAT, and
     *             use other method or custom format passed to format() method if you need to dump another string
     *             format.
     *
     * Set the default format used when type juggling a Carbon instance to a string.
     *
     * @param string|Closure|null $format
     *
     * @return void
     */
    public static function setToStringFormat(string|Closure|null $format): void
    {
        FactoryImmutable::getDefaultInstance()->setToStringFormat($format);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Closure;
use Generator;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionNamedType;
use Throwable;

/**
 * Trait Mixin.
 *
 * Allows mixing in entire classes with multiple macros.
 */
trait Mixin
{
    /**
     * Stack of macro instance contexts.
     */
    protected static array $macroContextStack = [];

    /**
     * Mix another object into the class.
     *
     * @example
     * ```
     * Carbon::mixin(new class {
     *   public function addMoon() {
     *     return function () {
     *       return $this->addDays(30);
     *     };
     *   }
     *   public function subMoon() {
     *     return function () {
     *       return $this->subDays(30);
     *     };
     *   }
     * });
     * $fullMoon = Carbon::create('2018-12-22');
     * $nextFullMoon = $fullMoon->addMoon();
     * $blackMoon = Carbon::create('2019-01-06');
     * $previousBlackMoon = $blackMoon->subMoon();
     * echo "$nextFullMoon\n";
     * echo "$previousBlackMoon\n";
     * ```
     *
     * @throws ReflectionException
     */
    public static function mixin(object|string $mixin): void
    {
        \is_string($mixin) && trait_exists($mixin)
            ? self::loadMixinTrait($mixin)
            : self::loadMixinClass($mixin);
    }

    /**
     * @throws ReflectionException
     */
    private static function loadMixinClass(object|string $mixin): void
    {
        $methods = (new ReflectionClass($mixin))->getMethods(
            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED,
        );

        foreach ($methods as $method) {
            if (self::cannotBeAMixinMethod($method)) {
                continue;
            }

            $macro = $method->invoke($mixin);

            if (\is_callable($macro)) {
                static::macro($method->name, $macro);
            }
        }
    }

    private static function cannotBeAMixinMethod(ReflectionMethod $method): bool
    {
        if ($method->isConstructor() || $method->isDestructor()) {
            return true;
        }

        $returnType = $method->getReturnType();

        if ($returnType instanceof ReflectionNamedType) {
            $returnedTypeName = $returnType->getName();

            if ($returnType->isBuiltin()) {
                return !\in_array($returnedTypeName, [
                    'callable',
                    'object', // could have __invoke
                    'array', // could be [MyClass::class, 'myMethod']
                    'mixed', // could be one of the above
                    // The other builtin types cannot be callable, so we can skip invoking them
                ], true);
            }

            // If it returns a non-invokable object, it cannot be a mixin method
            if (class_exists($returnedTypeName)) {
                return !is_a($returnedTypeName, Closure::class, true) && !\is_callable([$returnedTypeName, '__invoke']);
            }
        }

        return false;
    }

    private static function loadMixinTrait(string $trait): void
    {
        $context = eval(self::getAnonymousClassCodeForTrait($trait));
        $className = \get_class($context);
        $baseClass = static::class;

        foreach (self::getMixableMethods($context) as $name) {
            $closureBase = Closure::fromCallable([$context, $name]);

            static::macro($name, function (...$parameters) use ($closureBase, $className, $baseClass) {
                $downContext = isset($this) ? ($this) : new $baseClass();
                $context = isset($this) ? $this->cast($className) : new $className();

                try {
                    // @ is required to handle error if not converted into exceptions
                    $closure = @$closureBase->bindTo($context);
                } catch (Throwable) { // @codeCoverageIgnore
                    $closure = $closureBase; // @codeCoverageIgnore
                }

                // in case of errors not converted into exceptions
                $closure = $closure ?: $closureBase;

                $result = $closure(...$parameters);

                if (!($result instanceof $className)) {
                    return $result;
                }

                if ($downContext instanceof CarbonInterface && $result instanceof CarbonInterface) {
                    if ($context !== $result) {
                        $downContext = $downContext->copy();
                    }

                    return $downContext
                        ->setTimezone($result->getTimezone())
                        ->modify($result->format('Y-m-d H:i:s.u'))
                        ->settings($result->getSettings());
                }

                if ($downContext instanceof CarbonInterval && $result instanceof CarbonInterval) {
                    if ($context !== $result) {
                        $downContext = $downContext->copy();
                    }

                    $downContext->copyProperties($result);
                    self::copyStep($downContext, $result);
                    self::copyNegativeUnits($downContext, $result);

                    return $downContext->settings($result->getSettings());
                }

                if ($downContext instanceof CarbonPeriod && $result instanceof CarbonPeriod) {
                    if ($context !== $result) {
                        $downContext = $downContext->copy();
                    }

                    return $downContext
                        ->setDates($result->getStartDate(), $result->getEndDate())
                        ->setRecurrences($result->getRecurrences())
                        ->setOptions($result->getOptions())
                        ->settings($result->getSettings());
                }

                return $result;
            });
        }
    }

    private static function getAnonymousClassCodeForTrait(string $trait): string
    {
        return 'return new class() extends '.static::class.' {use '.$trait.';};';
    }

    private static function getMixableMethods(self $context): Generator
    {
        foreach (get_class_methods($context) as $name) {
            if (method_exists(static::class, $name)) {
                continue;
            }

            yield $name;
        }
    }

    /**
     * Stack a Carbon context from inside calls of self::this() and execute a given action.
     */
    protected static function bindMacroContext(?self $context, callable $callable): mixed
    {
        static::$macroContextStack[] = $context;

        try {
            return $callable();
        } finally {
            array_pop(static::$macroContextStack);
        }
    }

    /**
     * Return the current context from inside a macro callee or a null if static.
     */
    protected static function context(): ?static
    {
        return end(static::$macroContextStack) ?: null;
    }

    /**
     * Return the current context from inside a macro callee or a new one if static.
     */
    protected static function this(): static
    {
        return end(static::$macroContextStack) ?: new static();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use Carbon\Exceptions\UnknownUnitException;
use Carbon\WeekDay;
use DateInterval;

/**
 * Trait Rounding.
 *
 * Round, ceil, floor units.
 *
 * Depends on the following methods:
 *
 * @method static copy()
 * @method static startOfWeek(int $weekStartsAt = null)
 */
trait Rounding
{
    use IntervalRounding;

    /**
     * Round the current instance at the given unit with given precision if specified and the given function.
     */
    public function roundUnit(
        string $unit,
        DateInterval|string|float|int $precision = 1,
        callable|string $function = 'round',
    ): static {
        $metaUnits = [
            // @call roundUnit
            'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'],
            // @call roundUnit
            'century' => [static::YEARS_PER_CENTURY, 'year'],
            // @call roundUnit
            'decade' => [static::YEARS_PER_DECADE, 'year'],
            // @call roundUnit
            'quarter' => [static::MONTHS_PER_QUARTER, 'month'],
            // @call roundUnit
            'millisecond' => [1000, 'microsecond'],
        ];
        $normalizedUnit = static::singularUnit($unit);
        $ranges = array_merge(static::getRangesByUnit($this->daysInMonth), [
            // @call roundUnit
            'microsecond' => [0, 999999],
        ]);
        $factor = 1;

        if ($normalizedUnit === 'week') {
            $normalizedUnit = 'day';
            $precision *= static::DAYS_PER_WEEK;
        }

        if (isset($metaUnits[$normalizedUnit])) {
            [$factor, $normalizedUnit] = $metaUnits[$normalizedUnit];
        }

        $precision *= $factor;

        if (!isset($ranges[$normalizedUnit])) {
            throw new UnknownUnitException($unit);
        }

        $found = false;
        $fraction = 0;
        $arguments = null;
        $initialValue = null;
        $factor = $this->year < 0 ? -1 : 1;
        $changes = [];
        $minimumInc = null;

        foreach ($ranges as $unit => [$minimum, $maximum]) {
            if ($normalizedUnit === $unit) {
                $arguments = [$this->$unit, $minimum];
                $initialValue = $this->$unit;
                $fraction = $precision - floor($precision);
                $found = true;

                continue;
            }

            if ($found) {
                $delta = $maximum + 1 - $minimum;
                $factor /= $delta;
                $fraction *= $delta;
                $inc = ($this->$unit - $minimum) * $factor;

                if ($inc !== 0.0) {
                    $minimumInc = $minimumInc ?? ($arguments[0] / pow(2, 52));

                    // If value is still the same when adding a non-zero increment/decrement,
                    // it means precision got lost in the addition
                    if (abs($inc) < $minimumInc) {
                        $inc = $minimumInc * ($inc < 0 ? -1 : 1);
                    }

                    // If greater than $precision, assume precision loss caused an overflow
                    if ($function !== 'floor' || abs($arguments[0] + $inc - $initialValue) >= $precision) {
                        $arguments[0] += $inc;
                    }
                }

                $changes[$unit] = round(
                    $minimum + ($fraction ? $fraction * $function(($this->$unit - $minimum) / $fraction) : 0),
                );

                // Cannot use modulo as it lose double precision
                while ($changes[$unit] >= $delta) {
                    $changes[$unit] -= $delta;
                }

                $fraction -= floor($fraction);
            }
        }

        [$value, $minimum] = $arguments;
        $normalizedValue = floor($function(($value - $minimum) / $precision) * $precision + $minimum);

        /** @var CarbonInterface $result */
        $result = $this;

        foreach ($changes as $unit => $value) {
            $result = $result->$unit($value);
        }

        return $result->$normalizedUnit($normalizedValue);
    }

    /**
     * Truncate the current instance at the given unit with given precision if specified.
     */
    public function floorUnit(string $unit, DateInterval|string|float|int $precision = 1): static
    {
        return $this->roundUnit($unit, $precision, 'floor');
    }

    /**
     * Ceil the current instance at the given unit with given precision if specified.
     */
    public function ceilUnit(string $unit, DateInterval|string|float|int $precision = 1): static
    {
        return $this->roundUnit($unit, $precision, 'ceil');
    }

    /**
     * Round the current instance second with given precision if specified.
     */
    public function round(DateInterval|string|float|int $precision = 1, callable|string $function = 'round'): static
    {
        return $this->roundWith($precision, $function);
    }

    /**
     * Round the current instance second with given precision if specified.
     */
    public function floor(DateInterval|string|float|int $precision = 1): static
    {
        return $this->round($precision, 'floor');
    }

    /**
     * Ceil the current instance second with given precision if specified.
     */
    public function ceil(DateInterval|string|float|int $precision = 1): static
    {
        return $this->round($precision, 'ceil');
    }

    /**
     * Round the current instance week.
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     */
    public function roundWeek(WeekDay|int|null $weekStartsAt = null): static
    {
        return $this->closest(
            $this->avoidMutation()->floorWeek($weekStartsAt),
            $this->avoidMutation()->ceilWeek($weekStartsAt),
        );
    }

    /**
     * Truncate the current instance week.
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     */
    public function floorWeek(WeekDay|int|null $weekStartsAt = null): static
    {
        return $this->startOfWeek($weekStartsAt);
    }

    /**
     * Ceil the current instance week.
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     */
    public function ceilWeek(WeekDay|int|null $weekStartsAt = null): static
    {
        if ($this->isMutable()) {
            $startOfWeek = $this->avoidMutation()->startOfWeek($weekStartsAt);

            return $startOfWeek != $this ?
                $this->startOfWeek($weekStartsAt)->addWeek() :
                $this;
        }

        $startOfWeek = $this->startOfWeek($weekStartsAt);

        return $startOfWeek != $this ?
            $startOfWeek->addWeek() :
            $this->avoidMutation();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterval;

/**
 * Trait Week.
 *
 * week and ISO week number, year and count in year.
 *
 * Depends on the following properties:
 *
 * @property int $daysInYear
 * @property int $dayOfWeek
 * @property int $dayOfYear
 * @property int $year
 *
 * Depends on the following methods:
 *
 * @method static addWeeks(int $weeks = 1)
 * @method static copy()
 * @method static dayOfYear(int $dayOfYear)
 * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
 * @method static next(int|string $modifier = null)
 * @method static startOfWeek(int $day = null)
 * @method static subWeeks(int $weeks = 1)
 * @method static year(int $year = null)
 */
trait Week
{
    /**
     * Set/get the week number of year using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $year      if null, act as a getter, if not null, set the year and return current instance.
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int|static
     */
    public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
    {
        return $this->weekYear(
            $year,
            $dayOfWeek ?? static::MONDAY,
            $dayOfYear ?? static::THURSDAY,
        );
    }

    /**
     * Set/get the week number of year using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $year      if null, act as a getter, if not null, set the year and return current instance.
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int|static
     */
    public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null)
    {
        $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? static::SUNDAY;
        $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;

        if ($year !== null) {
            $year = (int) round($year);

            if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) {
                return $this->avoidMutation();
            }

            $week = $this->week(null, $dayOfWeek, $dayOfYear);
            $day = $this->dayOfWeek;
            $date = $this->year($year);

            $date = match ($date->weekYear(null, $dayOfWeek, $dayOfYear) - $year) {
                CarbonInterval::POSITIVE => $date->subWeeks(static::WEEKS_PER_YEAR / 2),
                CarbonInterval::NEGATIVE => $date->addWeeks(static::WEEKS_PER_YEAR / 2),
                default => $date,
            };

            $date = $date
                ->addWeeks($week - $date->week(null, $dayOfWeek, $dayOfYear))
                ->startOfWeek($dayOfWeek);

            if ($date->dayOfWeek === $day) {
                return $date;
            }

            return $date->next($day);
        }

        $year = $this->year;
        $day = $this->dayOfYear;
        $date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);

        if ($date->year === $year && $day < $date->dayOfYear) {
            return $year - 1;
        }

        $date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);

        if ($date->year === $year && $day >= $date->dayOfYear) {
            return $year + 1;
        }

        return $year;
    }

    /**
     * Get the number of weeks of the current week-year using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int
     */
    public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null)
    {
        return $this->weeksInYear(
            $dayOfWeek ?? static::MONDAY,
            $dayOfYear ?? static::THURSDAY,
        );
    }

    /**
     * Get the number of weeks of the current week-year using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int
     */
    public function weeksInYear($dayOfWeek = null, $dayOfYear = null)
    {
        $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? static::SUNDAY;
        $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
        $year = $this->year;
        $start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        $startDay = $start->dayOfYear;
        if ($start->year !== $year) {
            $startDay -= $start->daysInYear;
        }
        $end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        $endDay = $end->dayOfYear;
        if ($end->year !== $year) {
            $endDay += $this->daysInYear;
        }

        return (int) round(($endDay - $startDay) / static::DAYS_PER_WEEK);
    }

    /**
     * Get/set the week number using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $week
     * @param int|null $dayOfWeek
     * @param int|null $dayOfYear
     *
     * @return int|static
     */
    public function week($week = null, $dayOfWeek = null, $dayOfYear = null)
    {
        $date = $this;
        $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
        $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;

        if ($week !== null) {
            return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear));
        }

        $start = $date->avoidMutation()->shiftTimezone('UTC')->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        $end = $date->avoidMutation()->shiftTimezone('UTC')->startOfWeek($dayOfWeek);

        if ($start > $end) {
            $start = $start->subWeeks(static::WEEKS_PER_YEAR / 2)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
        }

        $week = (int) ($start->diffInDays($end) / static::DAYS_PER_WEEK + 1);

        return $week > $end->weeksInYear($dayOfWeek, $dayOfYear) ? 1 : $week;
    }

    /**
     * Get/set the week number using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $week
     * @param int|null $dayOfWeek
     * @param int|null $dayOfYear
     *
     * @return int|static
     */
    public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null)
    {
        return $this->week(
            $week,
            $dayOfWeek ?? static::MONDAY,
            $dayOfYear ?? static::THURSDAY,
        );
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Carbon\Exceptions\UnknownUnitException;
use Carbon\Unit;
use Closure;
use DateInterval;
use DateTimeInterface;

/**
 * Trait Difference.
 *
 * Depends on the following methods:
 *
 * @method bool lessThan($date)
 * @method static copy()
 * @method static resolveCarbon($date = null)
 */
trait Difference
{
    /**
     * Get the difference as a DateInterval instance.
     * Return relative interval (negative if $absolute flag is not set to true and the given date is before
     * current one).
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return DateInterval
     */
    public function diffAsDateInterval($date = null, bool $absolute = false): DateInterval
    {
        $other = $this->resolveCarbon($date);

        // Work-around for https://bugs.php.net/bug.php?id=81458
        // It was initially introduced for https://bugs.php.net/bug.php?id=80998
        // The very specific case of 80998 was fixed in PHP 8.1beta3, but it introduced 81458
        // So we still need to keep this for now
        if ($other->tz !== $this->tz) {
            $other = $other->avoidMutation()->setTimezone($this->tz);
        }

        return parent::diff($other, $absolute);
    }

    /**
     * Get the difference as a CarbonInterval instance.
     * Return relative interval (negative if $absolute flag is not set to true and the given date is before
     * current one).
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return CarbonInterval
     */
    public function diffAsCarbonInterval($date = null, bool $absolute = false, array $skip = []): CarbonInterval
    {
        return CarbonInterval::diff($this, $this->resolveCarbon($date), $absolute, $skip)
            ->setLocalTranslator($this->getLocalTranslator());
    }

    /**
     * @alias diffAsCarbonInterval
     *
     * Get the difference as a DateInterval instance.
     * Return relative interval (negative if $absolute flag is not set to true and the given date is before
     * current one).
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return CarbonInterval
     */
    public function diff($date = null, bool $absolute = false, array $skip = []): CarbonInterval
    {
        return $this->diffAsCarbonInterval($date, $absolute, $skip);
    }

    /**
     * @param Unit|string                                            $unit     microsecond, millisecond, second, minute,
     *                                                                         hour, day, week, month, quarter, year,
     *                                                                         century, millennium
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = false, bool $utc = false): float
    {
        $unit = static::pluralUnit($unit instanceof Unit ? $unit->value : rtrim($unit, 'z'));
        $method = 'diffIn'.$unit;

        if (!method_exists($this, $method)) {
            throw new UnknownUnitException($unit);
        }

        return $this->$method($date, $absolute, $utc);
    }

    /**
     * Get the difference in years
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInYears($date = null, bool $absolute = false, bool $utc = false): float
    {
        $start = $this;
        $end = $this->resolveCarbon($date);

        if ($utc) {
            $start = $start->avoidMutation()->utc();
            $end = $end->avoidMutation()->utc();
        }

        $ascending = ($start <= $end);
        $sign = $absolute || $ascending ? 1 : -1;

        if (!$ascending) {
            [$start, $end] = [$end, $start];
        }

        $yearsDiff = (int) $start->diff($end, $absolute)->format('%r%y');
        /** @var Carbon|CarbonImmutable $floorEnd */
        $floorEnd = $start->avoidMutation()->addYears($yearsDiff);

        if ($floorEnd >= $end) {
            return $sign * $yearsDiff;
        }

        /** @var Carbon|CarbonImmutable $ceilEnd */
        $ceilEnd = $start->avoidMutation()->addYears($yearsDiff + 1);

        $daysToFloor = $floorEnd->diffInDays($end);
        $daysToCeil = $end->diffInDays($ceilEnd);

        return $sign * ($yearsDiff + $daysToFloor / ($daysToCeil + $daysToFloor));
    }

    /**
     * Get the difference in quarters.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInQuarters($date = null, bool $absolute = false, bool $utc = false): float
    {
        return $this->diffInMonths($date, $absolute, $utc) / static::MONTHS_PER_QUARTER;
    }

    /**
     * Get the difference in months.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInMonths($date = null, bool $absolute = false, bool $utc = false): float
    {
        $start = $this;
        $end = $this->resolveCarbon($date);

        // Compare using UTC
        if ($utc || ($end->timezoneName !== $start->timezoneName)) {
            $start = $start->avoidMutation()->utc();
            $end = $end->avoidMutation()->utc();
        }

        [$yearStart, $monthStart, $dayStart] = explode('-', $start->format('Y-m-dHisu'));
        [$yearEnd, $monthEnd, $dayEnd] = explode('-', $end->format('Y-m-dHisu'));

        $monthsDiff = (((int) $yearEnd) - ((int) $yearStart)) * static::MONTHS_PER_YEAR +
            ((int) $monthEnd) - ((int) $monthStart);

        if ($monthsDiff > 0) {
            $monthsDiff -= ($dayStart > $dayEnd ? 1 : 0);
        } elseif ($monthsDiff < 0) {
            $monthsDiff += ($dayStart < $dayEnd ? 1 : 0);
        }

        $ascending = ($start <= $end);
        $sign = $absolute || $ascending ? 1 : -1;
        $monthsDiff = abs($monthsDiff);

        if (!$ascending) {
            [$start, $end] = [$end, $start];
        }

        /** @var Carbon|CarbonImmutable $floorEnd */
        $floorEnd = $start->avoidMutation()->addMonths($monthsDiff);

        if ($floorEnd >= $end) {
            return $sign * $monthsDiff;
        }

        /** @var Carbon|CarbonImmutable $ceilEnd */
        $ceilEnd = $start->avoidMutation()->addMonths($monthsDiff + 1);

        $daysToFloor = $floorEnd->diffInDays($end);
        $daysToCeil = $end->diffInDays($ceilEnd);

        return $sign * ($monthsDiff + $daysToFloor / ($daysToCeil + $daysToFloor));
    }

    /**
     * Get the difference in weeks.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInWeeks($date = null, bool $absolute = false, bool $utc = false): float
    {
        return $this->diffInDays($date, $absolute, $utc) / static::DAYS_PER_WEEK;
    }

    /**
     * Get the difference in days.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInDays($date = null, bool $absolute = false, bool $utc = false): float
    {
        $date = $this->resolveCarbon($date);
        $current = $this;

        // Compare using UTC
        if ($utc || ($date->timezoneName !== $current->timezoneName)) {
            $date = $date->avoidMutation()->utc();
            $current = $current->avoidMutation()->utc();
        }

        $negative = ($date < $current);
        [$start, $end] = $negative ? [$date, $current] : [$current, $date];
        $interval = $start->diffAsDateInterval($end);
        $daysA = $this->getIntervalDayDiff($interval);
        $floorEnd = $start->avoidMutation()->addDays($daysA);
        $daysB = $daysA + ($floorEnd <= $end ? 1 : -1);
        $ceilEnd = $start->avoidMutation()->addDays($daysB);
        $microsecondsBetween = $floorEnd->diffInMicroseconds($ceilEnd);
        $microsecondsToEnd = $floorEnd->diffInMicroseconds($end);

        return ($negative && !$absolute ? -1 : 1)
            * ($daysA * ($microsecondsBetween - $microsecondsToEnd) + $daysB * $microsecondsToEnd)
            / $microsecondsBetween;
    }

    /**
     * Get the difference in days using a filter closure.
     *
     * @param Closure                                                $callback
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInDaysFiltered(Closure $callback, $date = null, bool $absolute = false): int
    {
        return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute);
    }

    /**
     * Get the difference in hours using a filter closure.
     *
     * @param Closure                                                $callback
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInHoursFiltered(Closure $callback, $date = null, bool $absolute = false): int
    {
        return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute);
    }

    /**
     * Get the difference by the given interval using a filter closure.
     *
     * @param CarbonInterval                                         $ci       An interval to traverse by
     * @param Closure                                                $callback
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, bool $absolute = false): int
    {
        $start = $this;
        $end = $this->resolveCarbon($date);
        $inverse = false;

        if ($end < $start) {
            $start = $end;
            $end = $this;
            $inverse = true;
        }

        $options = CarbonPeriod::EXCLUDE_END_DATE | ($this->isMutable() ? 0 : CarbonPeriod::IMMUTABLE);
        $diff = $ci->toPeriod($start, $end, $options)->filter($callback)->count();

        return $inverse && !$absolute ? -$diff : $diff;
    }

    /**
     * Get the difference in weekdays.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInWeekdays($date = null, bool $absolute = false): int
    {
        return $this->diffInDaysFiltered(
            static fn (CarbonInterface $date) => $date->isWeekday(),
            $this->resolveCarbon($date)->avoidMutation()->modify($this->format('H:i:s.u')),
            $absolute,
        );
    }

    /**
     * Get the difference in weekend days using a filter.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInWeekendDays($date = null, bool $absolute = false): int
    {
        return $this->diffInDaysFiltered(
            static fn (CarbonInterface $date) => $date->isWeekend(),
            $this->resolveCarbon($date)->avoidMutation()->modify($this->format('H:i:s.u')),
            $absolute,
        );
    }

    /**
     * Get the difference in hours.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInHours($date = null, bool $absolute = false): float
    {
        return $this->diffInMinutes($date, $absolute) / static::MINUTES_PER_HOUR;
    }

    /**
     * Get the difference in minutes.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInMinutes($date = null, bool $absolute = false): float
    {
        return $this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE;
    }

    /**
     * Get the difference in seconds.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInSeconds($date = null, bool $absolute = false): float
    {
        return $this->diffInMilliseconds($date, $absolute) / static::MILLISECONDS_PER_SECOND;
    }

    /**
     * Get the difference in microseconds.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInMicroseconds($date = null, bool $absolute = false): float
    {
        /** @var CarbonInterface $date */
        $date = $this->resolveCarbon($date);
        $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND +
            $date->micro - $this->micro;

        return $absolute ? abs($value) : $value;
    }

    /**
     * Get the difference in milliseconds.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInMilliseconds($date = null, bool $absolute = false): float
    {
        return $this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND;
    }

    /**
     * The number of seconds since midnight.
     *
     * @return float
     */
    public function secondsSinceMidnight(): float
    {
        return $this->diffInSeconds($this->copy()->startOfDay(), true);
    }

    /**
     * The number of seconds until 23:59:59.
     *
     * @return float
     */
    public function secondsUntilEndOfDay(): float
    {
        return $this->diffInSeconds($this->copy()->endOfDay(), true);
    }

    /**
     * Get the difference in a human readable format in the current locale from current instance to an other
     * instance given (or now if null given).
     *
     * @example
     * ```
     * echo Carbon::tomorrow()->diffForHumans() . "\n";
     * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
     * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
     * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
     * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
     * ```
     *
     * @param Carbon|DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                            if null passed, now will be used as comparison reference;
     *                                                            if any other type, it will be converted to date and used as reference.
     * @param int|array                                  $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                            ⦿ 'syntax' entry (see below)
     *                                                            ⦿ 'short' entry (see below)
     *                                                            ⦿ 'parts' entry (see below)
     *                                                            ⦿ 'options' entry (see below)
     *                                                            ⦿ 'skip' entry, list of units to skip (array of strings or a single string,
     *                                                            ` it can be the unit name (singular or plural) or its shortcut
     *                                                            ` (y, m, w, d, h, min, s, ms, µs).
     *                                                            ⦿ 'aUnit' entry, prefer "an hour" over "1 hour" if true
     *                                                            ⦿ 'altNumbers' entry, use alternative numbers if available
     *                                                            ` (from the current language if true is passed, from the given language(s)
     *                                                            ` if array or string is passed)
     *                                                            ⦿ 'join' entry determines how to join multiple parts of the string
     *                                                            `  - if $join is a string, it's used as a joiner glue
     *                                                            `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                            `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                            `    will be used instead of the glue for the last item
     *                                                            `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                            `  - if $join is missing, a space will be used as glue
     *                                                            ⦿ 'other' entry (see above)
     *                                                            ⦿ 'minimumUnit' entry determines the smallest unit of time to display can be long or
     *                                                            `  short form of the units, e.g. 'hour' or 'h' (default value: s)
     *                                                            ⦿ 'locale' language in which the diff should be output (has no effect if 'translator' key is set)
     *                                                            ⦿ 'translator' a custom translator to use to translator the output.
     *                                                            if int passed, it adds modifiers:
     *                                                            Possible values:
     *                                                            - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                            - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                            - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                            Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                       $short   displays short format of time units
     * @param int                                        $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                        $options human diff options
     */
    public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null): string
    {
        /* @var CarbonInterface $this */
        if (\is_array($other)) {
            $other['syntax'] = \array_key_exists('syntax', $other) ? $other['syntax'] : $syntax;
            $syntax = $other;
            $other = $syntax['other'] ?? null;
        }

        $intSyntax = &$syntax;

        if (\is_array($syntax)) {
            $syntax['syntax'] = $syntax['syntax'] ?? null;
            $intSyntax = &$syntax['syntax'];
        }

        $intSyntax = (int) ($intSyntax ?? static::DIFF_RELATIVE_AUTO);
        $intSyntax = $intSyntax === static::DIFF_RELATIVE_AUTO && $other === null ? static::DIFF_RELATIVE_TO_NOW : $intSyntax;

        $parts = min(7, max(1, (int) $parts));
        $skip = \is_array($syntax) ? ($syntax['skip'] ?? []) : [];
        $options ??= $this->localHumanDiffOptions ?? $this->transmitFactory(
            static fn () => static::getHumanDiffOptions(),
        );

        return $this->diff($other, skip: (array) $skip)->forHumans($syntax, (bool) $short, $parts, $options);
    }

    /**
     * @alias diffForHumans
     *
     * Get the difference in a human readable format in the current locale from current instance to an other
     * instance given (or now if null given).
     *
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                             if null passed, now will be used as comparison reference;
     *                                                             if any other type, it will be converted to date and used as reference.
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                             - 'syntax' entry (see below)
     *                                                             - 'short' entry (see below)
     *                                                             - 'parts' entry (see below)
     *                                                             - 'options' entry (see below)
     *                                                             - 'join' entry determines how to join multiple parts of the string
     *                                                             `  - if $join is a string, it's used as a joiner glue
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                             `    will be used instead of the glue for the last item
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                             `  - if $join is missing, a space will be used as glue
     *                                                             - 'other' entry (see above)
     *                                                             if int passed, it add modifiers:
     *                                                             Possible values:
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                        $short   displays short format of time units
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                         $options human diff options
     *
     * @return string
     */
    public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
    {
        return $this->diffForHumans($other, $syntax, $short, $parts, $options);
    }

    /**
     * @alias diffForHumans
     *
     * Get the difference in a human readable format in the current locale from current instance to an other
     * instance given (or now if null given).
     */
    public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
    {
        return $this->diffForHumans($other, $syntax, $short, $parts, $options);
    }

    /**
     * Get the difference in a human readable format in the current locale from an other
     * instance given (or now if null given) to current instance.
     *
     * When comparing a value in the past to default now:
     * 1 hour from now
     * 5 months from now
     *
     * When comparing a value in the future to default now:
     * 1 hour ago
     * 5 months ago
     *
     * When comparing a value in the past to another value:
     * 1 hour after
     * 5 months after
     *
     * When comparing a value in the future to another value:
     * 1 hour before
     * 5 months before
     *
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                             if null passed, now will be used as comparison reference;
     *                                                             if any other type, it will be converted to date and used as reference.
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                             - 'syntax' entry (see below)
     *                                                             - 'short' entry (see below)
     *                                                             - 'parts' entry (see below)
     *                                                             - 'options' entry (see below)
     *                                                             - 'join' entry determines how to join multiple parts of the string
     *                                                             `  - if $join is a string, it's used as a joiner glue
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                             `    will be used instead of the glue for the last item
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                             `  - if $join is missing, a space will be used as glue
     *                                                             - 'other' entry (see above)
     *                                                             if int passed, it add modifiers:
     *                                                             Possible values:
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                        $short   displays short format of time units
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                         $options human diff options
     *
     * @return string
     */
    public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
    {
        if (!$syntax && !$other) {
            $syntax = CarbonInterface::DIFF_RELATIVE_TO_NOW;
        }

        return $this->resolveCarbon($other)->diffForHumans($this, $syntax, $short, $parts, $options);
    }

    /**
     * @alias to
     *
     * Get the difference in a human readable format in the current locale from an other
     * instance given (or now if null given) to current instance.
     *
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                             if null passed, now will be used as comparison reference;
     *                                                             if any other type, it will be converted to date and used as reference.
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                             - 'syntax' entry (see below)
     *                                                             - 'short' entry (see below)
     *                                                             - 'parts' entry (see below)
     *                                                             - 'options' entry (see below)
     *                                                             - 'join' entry determines how to join multiple parts of the string
     *                                                             `  - if $join is a string, it's used as a joiner glue
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                             `    will be used instead of the glue for the last item
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                             `  - if $join is missing, a space will be used as glue
     *                                                             - 'other' entry (see above)
     *                                                             if int passed, it add modifiers:
     *                                                             Possible values:
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                        $short   displays short format of time units
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                         $options human diff options
     *
     * @return string
     */
    public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null)
    {
        return $this->to($other, $syntax, $short, $parts, $options);
    }

    /**
     * Get the difference in a human readable format in the current locale from current
     * instance to now.
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                           - 'syntax' entry (see below)
     *                           - 'short' entry (see below)
     *                           - 'parts' entry (see below)
     *                           - 'options' entry (see below)
     *                           - 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           if int passed, it add modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int       $options human diff options
     *
     * @return string
     */
    public function fromNow($syntax = null, $short = false, $parts = 1, $options = null)
    {
        $other = null;

        if ($syntax instanceof DateTimeInterface) {
            [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null);
        }

        return $this->from($other, $syntax, $short, $parts, $options);
    }

    /**
     * Get the difference in a human readable format in the current locale from an other
     * instance given to now
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                           - 'syntax' entry (see below)
     *                           - 'short' entry (see below)
     *                           - 'parts' entry (see below)
     *                           - 'options' entry (see below)
     *                           - 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           if int passed, it add modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: 1: single part)
     * @param int       $options human diff options
     *
     * @return string
     */
    public function toNow($syntax = null, $short = false, $parts = 1, $options = null)
    {
        return $this->to(null, $syntax, $short, $parts, $options);
    }

    /**
     * Get the difference in a human readable format in the current locale from an other
     * instance given to now
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                           - 'syntax' entry (see below)
     *                           - 'short' entry (see below)
     *                           - 'parts' entry (see below)
     *                           - 'options' entry (see below)
     *                           - 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           if int passed, it add modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: 1: single part)
     * @param int       $options human diff options
     *
     * @return string
     */
    public function ago($syntax = null, $short = false, $parts = 1, $options = null)
    {
        $other = null;

        if ($syntax instanceof DateTimeInterface) {
            [$other, $syntax, $short, $parts, $options] = array_pad(\func_get_args(), 5, null);
        }

        return $this->from($other, $syntax, $short, $parts, $options);
    }

    /**
     * Get the difference in a human-readable format in the current locale from current instance to another
     * instance given (or now if null given).
     *
     * @return string
     */
    public function timespan($other = null, $timezone = null): string
    {
        if (\is_string($other)) {
            $other = $this->transmitFactory(static fn () => static::parse($other, $timezone));
        }

        return $this->diffForHumans($other, [
            'join' => ', ',
            'syntax' => CarbonInterface::DIFF_ABSOLUTE,
            'parts' => INF,
        ]);
    }

    /**
     * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days,
     * or a calendar date (e.g. "10/29/2017") otherwise.
     *
     * Language, date and time formats will change according to the current locale.
     *
     * @param Carbon|\DateTimeInterface|string|null $referenceTime
     * @param array                                 $formats
     *
     * @return string
     */
    public function calendar($referenceTime = null, array $formats = [])
    {
        /** @var CarbonInterface $current */
        $current = $this->avoidMutation()->startOfDay();
        /** @var CarbonInterface $other */
        $other = $this->resolveCarbon($referenceTime)->avoidMutation()->setTimezone($this->getTimezone())->startOfDay();
        $diff = $other->diffInDays($current, false);
        $format = $diff <= -static::DAYS_PER_WEEK ? 'sameElse' : (
            $diff < -1 ? 'lastWeek' : (
                $diff < 0 ? 'lastDay' : (
                    $diff < 1 ? 'sameDay' : (
                        $diff < 2 ? 'nextDay' : (
                            $diff < static::DAYS_PER_WEEK ? 'nextWeek' : 'sameElse'
                        )
                    )
                )
            )
        );
        $format = array_merge($this->getCalendarFormats(), $formats)[$format];
        if ($format instanceof Closure) {
            $format = $format($current, $other) ?? '';
        }

        return $this->isoFormat((string) $format);
    }

    private function getIntervalDayDiff(DateInterval $interval): int
    {
        return (int) $interval->format('%r%a');
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use BadMethodCallException;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use Carbon\CarbonPeriod;
use Carbon\CarbonTimeZone;
use Carbon\Exceptions\BadComparisonUnitException;
use Carbon\Exceptions\ImmutableException;
use Carbon\Exceptions\InvalidTimeZoneException;
use Carbon\Exceptions\UnitException;
use Carbon\Exceptions\UnknownGetterException;
use Carbon\Exceptions\UnknownMethodException;
use Carbon\Exceptions\UnknownSetterException;
use Carbon\Exceptions\UnknownUnitException;
use Carbon\FactoryImmutable;
use Carbon\Month;
use Carbon\Translator;
use Carbon\Unit;
use Carbon\WeekDay;
use Closure;
use DateInterval;
use DatePeriod;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Generator;
use InvalidArgumentException;
use ReflectionException;
use Symfony\Component\Clock\NativeClock;
use Throwable;

/**
 * A simple API extension for DateTime.
 *
 * <autodoc generated by `composer phpdoc`>
 *
 * @property      string           $localeDayOfWeek                                                                   the day of week in current locale
 * @property      string           $shortLocaleDayOfWeek                                                              the abbreviated day of week in current locale
 * @property      string           $localeMonth                                                                       the month in current locale
 * @property      string           $shortLocaleMonth                                                                  the abbreviated month in current locale
 * @property      int              $year
 * @property      int              $yearIso
 * @property      int              $month
 * @property      int              $day
 * @property      int              $hour
 * @property      int              $minute
 * @property      int              $second
 * @property      int              $micro
 * @property      int              $microsecond
 * @property      int              $dayOfWeekIso                                                                      1 (for Monday) through 7 (for Sunday)
 * @property      int|float|string $timestamp                                                                         seconds since the Unix Epoch
 * @property      string           $englishDayOfWeek                                                                  the day of week in English
 * @property      string           $shortEnglishDayOfWeek                                                             the abbreviated day of week in English
 * @property      string           $englishMonth                                                                      the month in English
 * @property      string           $shortEnglishMonth                                                                 the abbreviated month in English
 * @property      int              $milliseconds
 * @property      int              $millisecond
 * @property      int              $milli
 * @property      int              $week                                                                              1 through 53
 * @property      int              $isoWeek                                                                           1 through 53
 * @property      int              $weekYear                                                                          year according to week format
 * @property      int              $isoWeekYear                                                                       year according to ISO week format
 * @property      int              $age                                                                               does a diffInYears() with default parameters
 * @property      int              $offset                                                                            the timezone offset in seconds from UTC
 * @property      int              $offsetMinutes                                                                     the timezone offset in minutes from UTC
 * @property      int              $offsetHours                                                                       the timezone offset in hours from UTC
 * @property      CarbonTimeZone   $timezone                                                                          the current timezone
 * @property      CarbonTimeZone   $tz                                                                                alias of $timezone
 * @property      int              $centuryOfMillennium                                                               The value of the century starting from the beginning of the current millennium
 * @property      int              $dayOfCentury                                                                      The value of the day starting from the beginning of the current century
 * @property      int              $dayOfDecade                                                                       The value of the day starting from the beginning of the current decade
 * @property      int              $dayOfMillennium                                                                   The value of the day starting from the beginning of the current millennium
 * @property      int              $dayOfMonth                                                                        The value of the day starting from the beginning of the current month
 * @property      int              $dayOfQuarter                                                                      The value of the day starting from the beginning of the current quarter
 * @property      int              $dayOfWeek                                                                         0 (for Sunday) through 6 (for Saturday)
 * @property      int              $dayOfYear                                                                         1 through 366
 * @property      int              $decadeOfCentury                                                                   The value of the decade starting from the beginning of the current century
 * @property      int              $decadeOfMillennium                                                                The value of the decade starting from the beginning of the current millennium
 * @property      int              $hourOfCentury                                                                     The value of the hour starting from the beginning of the current century
 * @property      int              $hourOfDay                                                                         The value of the hour starting from the beginning of the current day
 * @property      int              $hourOfDecade                                                                      The value of the hour starting from the beginning of the current decade
 * @property      int              $hourOfMillennium                                                                  The value of the hour starting from the beginning of the current millennium
 * @property      int              $hourOfMonth                                                                       The value of the hour starting from the beginning of the current month
 * @property      int              $hourOfQuarter                                                                     The value of the hour starting from the beginning of the current quarter
 * @property      int              $hourOfWeek                                                                        The value of the hour starting from the beginning of the current week
 * @property      int              $hourOfYear                                                                        The value of the hour starting from the beginning of the current year
 * @property      int              $microsecondOfCentury                                                              The value of the microsecond starting from the beginning of the current century
 * @property      int              $microsecondOfDay                                                                  The value of the microsecond starting from the beginning of the current day
 * @property      int              $microsecondOfDecade                                                               The value of the microsecond starting from the beginning of the current decade
 * @property      int              $microsecondOfHour                                                                 The value of the microsecond starting from the beginning of the current hour
 * @property      int              $microsecondOfMillennium                                                           The value of the microsecond starting from the beginning of the current millennium
 * @property      int              $microsecondOfMillisecond                                                          The value of the microsecond starting from the beginning of the current millisecond
 * @property      int              $microsecondOfMinute                                                               The value of the microsecond starting from the beginning of the current minute
 * @property      int              $microsecondOfMonth                                                                The value of the microsecond starting from the beginning of the current month
 * @property      int              $microsecondOfQuarter                                                              The value of the microsecond starting from the beginning of the current quarter
 * @property      int              $microsecondOfSecond                                                               The value of the microsecond starting from the beginning of the current second
 * @property      int              $microsecondOfWeek                                                                 The value of the microsecond starting from the beginning of the current week
 * @property      int              $microsecondOfYear                                                                 The value of the microsecond starting from the beginning of the current year
 * @property      int              $millisecondOfCentury                                                              The value of the millisecond starting from the beginning of the current century
 * @property      int              $millisecondOfDay                                                                  The value of the millisecond starting from the beginning of the current day
 * @property      int              $millisecondOfDecade                                                               The value of the millisecond starting from the beginning of the current decade
 * @property      int              $millisecondOfHour                                                                 The value of the millisecond starting from the beginning of the current hour
 * @property      int              $millisecondOfMillennium                                                           The value of the millisecond starting from the beginning of the current millennium
 * @property      int              $millisecondOfMinute                                                               The value of the millisecond starting from the beginning of the current minute
 * @property      int              $millisecondOfMonth                                                                The value of the millisecond starting from the beginning of the current month
 * @property      int              $millisecondOfQuarter                                                              The value of the millisecond starting from the beginning of the current quarter
 * @property      int              $millisecondOfSecond                                                               The value of the millisecond starting from the beginning of the current second
 * @property      int              $millisecondOfWeek                                                                 The value of the millisecond starting from the beginning of the current week
 * @property      int              $millisecondOfYear                                                                 The value of the millisecond starting from the beginning of the current year
 * @property      int              $minuteOfCentury                                                                   The value of the minute starting from the beginning of the current century
 * @property      int              $minuteOfDay                                                                       The value of the minute starting from the beginning of the current day
 * @property      int              $minuteOfDecade                                                                    The value of the minute starting from the beginning of the current decade
 * @property      int              $minuteOfHour                                                                      The value of the minute starting from the beginning of the current hour
 * @property      int              $minuteOfMillennium                                                                The value of the minute starting from the beginning of the current millennium
 * @property      int              $minuteOfMonth                                                                     The value of the minute starting from the beginning of the current month
 * @property      int              $minuteOfQuarter                                                                   The value of the minute starting from the beginning of the current quarter
 * @property      int              $minuteOfWeek                                                                      The value of the minute starting from the beginning of the current week
 * @property      int              $minuteOfYear                                                                      The value of the minute starting from the beginning of the current year
 * @property      int              $monthOfCentury                                                                    The value of the month starting from the beginning of the current century
 * @property      int              $monthOfDecade                                                                     The value of the month starting from the beginning of the current decade
 * @property      int              $monthOfMillennium                                                                 The value of the month starting from the beginning of the current millennium
 * @property      int              $monthOfQuarter                                                                    The value of the month starting from the beginning of the current quarter
 * @property      int              $monthOfYear                                                                       The value of the month starting from the beginning of the current year
 * @property      int              $quarterOfCentury                                                                  The value of the quarter starting from the beginning of the current century
 * @property      int              $quarterOfDecade                                                                   The value of the quarter starting from the beginning of the current decade
 * @property      int              $quarterOfMillennium                                                               The value of the quarter starting from the beginning of the current millennium
 * @property      int              $quarterOfYear                                                                     The value of the quarter starting from the beginning of the current year
 * @property      int              $secondOfCentury                                                                   The value of the second starting from the beginning of the current century
 * @property      int              $secondOfDay                                                                       The value of the second starting from the beginning of the current day
 * @property      int              $secondOfDecade                                                                    The value of the second starting from the beginning of the current decade
 * @property      int              $secondOfHour                                                                      The value of the second starting from the beginning of the current hour
 * @property      int              $secondOfMillennium                                                                The value of the second starting from the beginning of the current millennium
 * @property      int              $secondOfMinute                                                                    The value of the second starting from the beginning of the current minute
 * @property      int              $secondOfMonth                                                                     The value of the second starting from the beginning of the current month
 * @property      int              $secondOfQuarter                                                                   The value of the second starting from the beginning of the current quarter
 * @property      int              $secondOfWeek                                                                      The value of the second starting from the beginning of the current week
 * @property      int              $secondOfYear                                                                      The value of the second starting from the beginning of the current year
 * @property      int              $weekOfCentury                                                                     The value of the week starting from the beginning of the current century
 * @property      int              $weekOfDecade                                                                      The value of the week starting from the beginning of the current decade
 * @property      int              $weekOfMillennium                                                                  The value of the week starting from the beginning of the current millennium
 * @property      int              $weekOfMonth                                                                       1 through 5
 * @property      int              $weekOfQuarter                                                                     The value of the week starting from the beginning of the current quarter
 * @property      int              $weekOfYear                                                                        ISO-8601 week number of year, weeks starting on Monday
 * @property      int              $yearOfCentury                                                                     The value of the year starting from the beginning of the current century
 * @property      int              $yearOfDecade                                                                      The value of the year starting from the beginning of the current decade
 * @property      int              $yearOfMillennium                                                                  The value of the year starting from the beginning of the current millennium
 * @property-read string           $latinMeridiem                                                                     "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
 * @property-read string           $latinUpperMeridiem                                                                "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
 * @property-read string           $timezoneAbbreviatedName                                                           the current timezone abbreviated name
 * @property-read string           $tzAbbrName                                                                        alias of $timezoneAbbreviatedName
 * @property-read string           $dayName                                                                           long name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortDayName                                                                      short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $minDayName                                                                        very short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $monthName                                                                         long name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortMonthName                                                                    short name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $meridiem                                                                          lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read string           $upperMeridiem                                                                     uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read int              $noZeroHour                                                                        current hour from 1 to 24
 * @property-read int              $isoWeeksInYear                                                                    51 through 53
 * @property-read int              $weekNumberInMonth                                                                 1 through 5
 * @property-read int              $firstWeekDay                                                                      0 through 6
 * @property-read int              $lastWeekDay                                                                       0 through 6
 * @property-read int              $quarter                                                                           the quarter of this instance, 1 - 4
 * @property-read int              $decade                                                                            the decade of this instance
 * @property-read int              $century                                                                           the century of this instance
 * @property-read int              $millennium                                                                        the millennium of this instance
 * @property-read bool             $dst                                                                               daylight savings time indicator, true if DST, false otherwise
 * @property-read bool             $local                                                                             checks if the timezone is local, true if local, false otherwise
 * @property-read bool             $utc                                                                               checks if the timezone is UTC, true if UTC, false otherwise
 * @property-read string           $timezoneName                                                                      the current timezone name
 * @property-read string           $tzName                                                                            alias of $timezoneName
 * @property-read string           $locale                                                                            locale of the current instance
 * @property-read int              $centuriesInMillennium                                                             The number of centuries contained in the current millennium
 * @property-read int              $daysInCentury                                                                     The number of days contained in the current century
 * @property-read int              $daysInDecade                                                                      The number of days contained in the current decade
 * @property-read int              $daysInMillennium                                                                  The number of days contained in the current millennium
 * @property-read int              $daysInMonth                                                                       number of days in the given month
 * @property-read int              $daysInQuarter                                                                     The number of days contained in the current quarter
 * @property-read int              $daysInWeek                                                                        The number of days contained in the current week
 * @property-read int              $daysInYear                                                                        365 or 366
 * @property-read int              $decadesInCentury                                                                  The number of decades contained in the current century
 * @property-read int              $decadesInMillennium                                                               The number of decades contained in the current millennium
 * @property-read int              $hoursInCentury                                                                    The number of hours contained in the current century
 * @property-read int              $hoursInDay                                                                        The number of hours contained in the current day
 * @property-read int              $hoursInDecade                                                                     The number of hours contained in the current decade
 * @property-read int              $hoursInMillennium                                                                 The number of hours contained in the current millennium
 * @property-read int              $hoursInMonth                                                                      The number of hours contained in the current month
 * @property-read int              $hoursInQuarter                                                                    The number of hours contained in the current quarter
 * @property-read int              $hoursInWeek                                                                       The number of hours contained in the current week
 * @property-read int              $hoursInYear                                                                       The number of hours contained in the current year
 * @property-read int              $microsecondsInCentury                                                             The number of microseconds contained in the current century
 * @property-read int              $microsecondsInDay                                                                 The number of microseconds contained in the current day
 * @property-read int              $microsecondsInDecade                                                              The number of microseconds contained in the current decade
 * @property-read int              $microsecondsInHour                                                                The number of microseconds contained in the current hour
 * @property-read int              $microsecondsInMillennium                                                          The number of microseconds contained in the current millennium
 * @property-read int              $microsecondsInMillisecond                                                         The number of microseconds contained in the current millisecond
 * @property-read int              $microsecondsInMinute                                                              The number of microseconds contained in the current minute
 * @property-read int              $microsecondsInMonth                                                               The number of microseconds contained in the current month
 * @property-read int              $microsecondsInQuarter                                                             The number of microseconds contained in the current quarter
 * @property-read int              $microsecondsInSecond                                                              The number of microseconds contained in the current second
 * @property-read int              $microsecondsInWeek                                                                The number of microseconds contained in the current week
 * @property-read int              $microsecondsInYear                                                                The number of microseconds contained in the current year
 * @property-read int              $millisecondsInCentury                                                             The number of milliseconds contained in the current century
 * @property-read int              $millisecondsInDay                                                                 The number of milliseconds contained in the current day
 * @property-read int              $millisecondsInDecade                                                              The number of milliseconds contained in the current decade
 * @property-read int              $millisecondsInHour                                                                The number of milliseconds contained in the current hour
 * @property-read int              $millisecondsInMillennium                                                          The number of milliseconds contained in the current millennium
 * @property-read int              $millisecondsInMinute                                                              The number of milliseconds contained in the current minute
 * @property-read int              $millisecondsInMonth                                                               The number of milliseconds contained in the current month
 * @property-read int              $millisecondsInQuarter                                                             The number of milliseconds contained in the current quarter
 * @property-read int              $millisecondsInSecond                                                              The number of milliseconds contained in the current second
 * @property-read int              $millisecondsInWeek                                                                The number of milliseconds contained in the current week
 * @property-read int              $millisecondsInYear                                                                The number of milliseconds contained in the current year
 * @property-read int              $minutesInCentury                                                                  The number of minutes contained in the current century
 * @property-read int              $minutesInDay                                                                      The number of minutes contained in the current day
 * @property-read int              $minutesInDecade                                                                   The number of minutes contained in the current decade
 * @property-read int              $minutesInHour                                                                     The number of minutes contained in the current hour
 * @property-read int              $minutesInMillennium                                                               The number of minutes contained in the current millennium
 * @property-read int              $minutesInMonth                                                                    The number of minutes contained in the current month
 * @property-read int              $minutesInQuarter                                                                  The number of minutes contained in the current quarter
 * @property-read int              $minutesInWeek                                                                     The number of minutes contained in the current week
 * @property-read int              $minutesInYear                                                                     The number of minutes contained in the current year
 * @property-read int              $monthsInCentury                                                                   The number of months contained in the current century
 * @property-read int              $monthsInDecade                                                                    The number of months contained in the current decade
 * @property-read int              $monthsInMillennium                                                                The number of months contained in the current millennium
 * @property-read int              $monthsInQuarter                                                                   The number of months contained in the current quarter
 * @property-read int              $monthsInYear                                                                      The number of months contained in the current year
 * @property-read int              $quartersInCentury                                                                 The number of quarters contained in the current century
 * @property-read int              $quartersInDecade                                                                  The number of quarters contained in the current decade
 * @property-read int              $quartersInMillennium                                                              The number of quarters contained in the current millennium
 * @property-read int              $quartersInYear                                                                    The number of quarters contained in the current year
 * @property-read int              $secondsInCentury                                                                  The number of seconds contained in the current century
 * @property-read int              $secondsInDay                                                                      The number of seconds contained in the current day
 * @property-read int              $secondsInDecade                                                                   The number of seconds contained in the current decade
 * @property-read int              $secondsInHour                                                                     The number of seconds contained in the current hour
 * @property-read int              $secondsInMillennium                                                               The number of seconds contained in the current millennium
 * @property-read int              $secondsInMinute                                                                   The number of seconds contained in the current minute
 * @property-read int              $secondsInMonth                                                                    The number of seconds contained in the current month
 * @property-read int              $secondsInQuarter                                                                  The number of seconds contained in the current quarter
 * @property-read int              $secondsInWeek                                                                     The number of seconds contained in the current week
 * @property-read int              $secondsInYear                                                                     The number of seconds contained in the current year
 * @property-read int              $weeksInCentury                                                                    The number of weeks contained in the current century
 * @property-read int              $weeksInDecade                                                                     The number of weeks contained in the current decade
 * @property-read int              $weeksInMillennium                                                                 The number of weeks contained in the current millennium
 * @property-read int              $weeksInMonth                                                                      The number of weeks contained in the current month
 * @property-read int              $weeksInQuarter                                                                    The number of weeks contained in the current quarter
 * @property-read int              $weeksInYear                                                                       51 through 53
 * @property-read int              $yearsInCentury                                                                    The number of years contained in the current century
 * @property-read int              $yearsInDecade                                                                     The number of years contained in the current decade
 * @property-read int              $yearsInMillennium                                                                 The number of years contained in the current millennium
 *
 * @method        bool             isUtc()                                                                            Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
 * @method        bool             isLocal()                                                                          Check if the current instance has non-UTC timezone.
 * @method        bool             isValid()                                                                          Check if the current instance is a valid date.
 * @method        bool             isDST()                                                                            Check if the current instance is in a daylight saving time.
 * @method        bool             isSunday()                                                                         Checks if the instance day is sunday.
 * @method        bool             isMonday()                                                                         Checks if the instance day is monday.
 * @method        bool             isTuesday()                                                                        Checks if the instance day is tuesday.
 * @method        bool             isWednesday()                                                                      Checks if the instance day is wednesday.
 * @method        bool             isThursday()                                                                       Checks if the instance day is thursday.
 * @method        bool             isFriday()                                                                         Checks if the instance day is friday.
 * @method        bool             isSaturday()                                                                       Checks if the instance day is saturday.
 * @method        bool             isSameYear(DateTimeInterface|string $date)                                         Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentYear()                                                                    Checks if the instance is in the same year as the current moment.
 * @method        bool             isNextYear()                                                                       Checks if the instance is in the same year as the current moment next year.
 * @method        bool             isLastYear()                                                                       Checks if the instance is in the same year as the current moment last year.
 * @method        bool             isCurrentMonth()                                                                   Checks if the instance is in the same month as the current moment.
 * @method        bool             isNextMonth()                                                                      Checks if the instance is in the same month as the current moment next month.
 * @method        bool             isLastMonth()                                                                      Checks if the instance is in the same month as the current moment last month.
 * @method        bool             isSameWeek(DateTimeInterface|string $date)                                         Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentWeek()                                                                    Checks if the instance is in the same week as the current moment.
 * @method        bool             isNextWeek()                                                                       Checks if the instance is in the same week as the current moment next week.
 * @method        bool             isLastWeek()                                                                       Checks if the instance is in the same week as the current moment last week.
 * @method        bool             isSameDay(DateTimeInterface|string $date)                                          Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDay()                                                                     Checks if the instance is in the same day as the current moment.
 * @method        bool             isNextDay()                                                                        Checks if the instance is in the same day as the current moment next day.
 * @method        bool             isLastDay()                                                                        Checks if the instance is in the same day as the current moment last day.
 * @method        bool             isSameHour(DateTimeInterface|string $date)                                         Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentHour()                                                                    Checks if the instance is in the same hour as the current moment.
 * @method        bool             isNextHour()                                                                       Checks if the instance is in the same hour as the current moment next hour.
 * @method        bool             isLastHour()                                                                       Checks if the instance is in the same hour as the current moment last hour.
 * @method        bool             isSameMinute(DateTimeInterface|string $date)                                       Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMinute()                                                                  Checks if the instance is in the same minute as the current moment.
 * @method        bool             isNextMinute()                                                                     Checks if the instance is in the same minute as the current moment next minute.
 * @method        bool             isLastMinute()                                                                     Checks if the instance is in the same minute as the current moment last minute.
 * @method        bool             isSameSecond(DateTimeInterface|string $date)                                       Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentSecond()                                                                  Checks if the instance is in the same second as the current moment.
 * @method        bool             isNextSecond()                                                                     Checks if the instance is in the same second as the current moment next second.
 * @method        bool             isLastSecond()                                                                     Checks if the instance is in the same second as the current moment last second.
 * @method        bool             isSameMilli(DateTimeInterface|string $date)                                        Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMilli()                                                                   Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMilli()                                                                      Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMilli()                                                                      Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMillisecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillisecond()                                                             Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMicro(DateTimeInterface|string $date)                                        Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicro()                                                                   Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicro()                                                                      Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicro()                                                                      Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameMicrosecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicrosecond()                                                             Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameDecade(DateTimeInterface|string $date)                                       Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDecade()                                                                  Checks if the instance is in the same decade as the current moment.
 * @method        bool             isNextDecade()                                                                     Checks if the instance is in the same decade as the current moment next decade.
 * @method        bool             isLastDecade()                                                                     Checks if the instance is in the same decade as the current moment last decade.
 * @method        bool             isSameCentury(DateTimeInterface|string $date)                                      Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentCentury()                                                                 Checks if the instance is in the same century as the current moment.
 * @method        bool             isNextCentury()                                                                    Checks if the instance is in the same century as the current moment next century.
 * @method        bool             isLastCentury()                                                                    Checks if the instance is in the same century as the current moment last century.
 * @method        bool             isSameMillennium(DateTimeInterface|string $date)                                   Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillennium()                                                              Checks if the instance is in the same millennium as the current moment.
 * @method        bool             isNextMillennium()                                                                 Checks if the instance is in the same millennium as the current moment next millennium.
 * @method        bool             isLastMillennium()                                                                 Checks if the instance is in the same millennium as the current moment last millennium.
 * @method        bool             isCurrentQuarter()                                                                 Checks if the instance is in the same quarter as the current moment.
 * @method        bool             isNextQuarter()                                                                    Checks if the instance is in the same quarter as the current moment next quarter.
 * @method        bool             isLastQuarter()                                                                    Checks if the instance is in the same quarter as the current moment last quarter.
 * @method        CarbonInterface  years(int $value)                                                                  Set current instance year to the given value.
 * @method        CarbonInterface  year(int $value)                                                                   Set current instance year to the given value.
 * @method        CarbonInterface  setYears(int $value)                                                               Set current instance year to the given value.
 * @method        CarbonInterface  setYear(int $value)                                                                Set current instance year to the given value.
 * @method        CarbonInterface  months(Month|int $value)                                                           Set current instance month to the given value.
 * @method        CarbonInterface  month(Month|int $value)                                                            Set current instance month to the given value.
 * @method        CarbonInterface  setMonths(Month|int $value)                                                        Set current instance month to the given value.
 * @method        CarbonInterface  setMonth(Month|int $value)                                                         Set current instance month to the given value.
 * @method        CarbonInterface  days(int $value)                                                                   Set current instance day to the given value.
 * @method        CarbonInterface  day(int $value)                                                                    Set current instance day to the given value.
 * @method        CarbonInterface  setDays(int $value)                                                                Set current instance day to the given value.
 * @method        CarbonInterface  setDay(int $value)                                                                 Set current instance day to the given value.
 * @method        CarbonInterface  hours(int $value)                                                                  Set current instance hour to the given value.
 * @method        CarbonInterface  hour(int $value)                                                                   Set current instance hour to the given value.
 * @method        CarbonInterface  setHours(int $value)                                                               Set current instance hour to the given value.
 * @method        CarbonInterface  setHour(int $value)                                                                Set current instance hour to the given value.
 * @method        CarbonInterface  minutes(int $value)                                                                Set current instance minute to the given value.
 * @method        CarbonInterface  minute(int $value)                                                                 Set current instance minute to the given value.
 * @method        CarbonInterface  setMinutes(int $value)                                                             Set current instance minute to the given value.
 * @method        CarbonInterface  setMinute(int $value)                                                              Set current instance minute to the given value.
 * @method        CarbonInterface  seconds(int $value)                                                                Set current instance second to the given value.
 * @method        CarbonInterface  second(int $value)                                                                 Set current instance second to the given value.
 * @method        CarbonInterface  setSeconds(int $value)                                                             Set current instance second to the given value.
 * @method        CarbonInterface  setSecond(int $value)                                                              Set current instance second to the given value.
 * @method        CarbonInterface  millis(int $value)                                                                 Set current instance millisecond to the given value.
 * @method        CarbonInterface  milli(int $value)                                                                  Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMillis(int $value)                                                              Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMilli(int $value)                                                               Set current instance millisecond to the given value.
 * @method        CarbonInterface  milliseconds(int $value)                                                           Set current instance millisecond to the given value.
 * @method        CarbonInterface  millisecond(int $value)                                                            Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMilliseconds(int $value)                                                        Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMillisecond(int $value)                                                         Set current instance millisecond to the given value.
 * @method        CarbonInterface  micros(int $value)                                                                 Set current instance microsecond to the given value.
 * @method        CarbonInterface  micro(int $value)                                                                  Set current instance microsecond to the given value.
 * @method        CarbonInterface  setMicros(int $value)                                                              Set current instance microsecond to the given value.
 * @method        CarbonInterface  setMicro(int $value)                                                               Set current instance microsecond to the given value.
 * @method        CarbonInterface  microseconds(int $value)                                                           Set current instance microsecond to the given value.
 * @method        CarbonInterface  microsecond(int $value)                                                            Set current instance microsecond to the given value.
 * @method        CarbonInterface  setMicroseconds(int $value)                                                        Set current instance microsecond to the given value.
 * @method        self             setMicrosecond(int $value)                                                         Set current instance microsecond to the given value.
 * @method        CarbonInterface  addYears(int|float $value = 1)                                                     Add years (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addYear()                                                                          Add one year to the instance (using date interval).
 * @method        CarbonInterface  subYears(int|float $value = 1)                                                     Sub years (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subYear()                                                                          Sub one year to the instance (using date interval).
 * @method        CarbonInterface  addYearsWithOverflow(int|float $value = 1)                                         Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addYearWithOverflow()                                                              Add one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subYearsWithOverflow(int|float $value = 1)                                         Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subYearWithOverflow()                                                              Sub one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addYearsWithoutOverflow(int|float $value = 1)                                      Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearWithoutOverflow()                                                           Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearsWithoutOverflow(int|float $value = 1)                                      Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearWithoutOverflow()                                                           Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearsWithNoOverflow(int|float $value = 1)                                       Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearWithNoOverflow()                                                            Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearsWithNoOverflow(int|float $value = 1)                                       Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearWithNoOverflow()                                                            Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearsNoOverflow(int|float $value = 1)                                           Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearNoOverflow()                                                                Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearsNoOverflow(int|float $value = 1)                                           Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearNoOverflow()                                                                Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonths(int|float $value = 1)                                                    Add months (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMonth()                                                                         Add one month to the instance (using date interval).
 * @method        CarbonInterface  subMonths(int|float $value = 1)                                                    Sub months (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMonth()                                                                         Sub one month to the instance (using date interval).
 * @method        CarbonInterface  addMonthsWithOverflow(int|float $value = 1)                                        Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMonthWithOverflow()                                                             Add one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMonthsWithOverflow(int|float $value = 1)                                        Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMonthWithOverflow()                                                             Sub one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMonthsWithoutOverflow(int|float $value = 1)                                     Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthWithoutOverflow()                                                          Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthsWithoutOverflow(int|float $value = 1)                                     Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthWithoutOverflow()                                                          Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthsWithNoOverflow(int|float $value = 1)                                      Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthWithNoOverflow()                                                           Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthsWithNoOverflow(int|float $value = 1)                                      Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthWithNoOverflow()                                                           Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthsNoOverflow(int|float $value = 1)                                          Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthNoOverflow()                                                               Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthsNoOverflow(int|float $value = 1)                                          Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthNoOverflow()                                                               Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDays(int|float $value = 1)                                                      Add days (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addDay()                                                                           Add one day to the instance (using date interval).
 * @method        CarbonInterface  subDays(int|float $value = 1)                                                      Sub days (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subDay()                                                                           Sub one day to the instance (using date interval).
 * @method        CarbonInterface  addHours(int|float $value = 1)                                                     Add hours (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addHour()                                                                          Add one hour to the instance (using date interval).
 * @method        CarbonInterface  subHours(int|float $value = 1)                                                     Sub hours (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subHour()                                                                          Sub one hour to the instance (using date interval).
 * @method        CarbonInterface  addMinutes(int|float $value = 1)                                                   Add minutes (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMinute()                                                                        Add one minute to the instance (using date interval).
 * @method        CarbonInterface  subMinutes(int|float $value = 1)                                                   Sub minutes (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMinute()                                                                        Sub one minute to the instance (using date interval).
 * @method        CarbonInterface  addSeconds(int|float $value = 1)                                                   Add seconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addSecond()                                                                        Add one second to the instance (using date interval).
 * @method        CarbonInterface  subSeconds(int|float $value = 1)                                                   Sub seconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subSecond()                                                                        Sub one second to the instance (using date interval).
 * @method        CarbonInterface  addMillis(int|float $value = 1)                                                    Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMilli()                                                                         Add one millisecond to the instance (using date interval).
 * @method        CarbonInterface  subMillis(int|float $value = 1)                                                    Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMilli()                                                                         Sub one millisecond to the instance (using date interval).
 * @method        CarbonInterface  addMilliseconds(int|float $value = 1)                                              Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMillisecond()                                                                   Add one millisecond to the instance (using date interval).
 * @method        CarbonInterface  subMilliseconds(int|float $value = 1)                                              Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMillisecond()                                                                   Sub one millisecond to the instance (using date interval).
 * @method        CarbonInterface  addMicros(int|float $value = 1)                                                    Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMicro()                                                                         Add one microsecond to the instance (using date interval).
 * @method        CarbonInterface  subMicros(int|float $value = 1)                                                    Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMicro()                                                                         Sub one microsecond to the instance (using date interval).
 * @method        CarbonInterface  addMicroseconds(int|float $value = 1)                                              Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMicrosecond()                                                                   Add one microsecond to the instance (using date interval).
 * @method        CarbonInterface  subMicroseconds(int|float $value = 1)                                              Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMicrosecond()                                                                   Sub one microsecond to the instance (using date interval).
 * @method        CarbonInterface  addMillennia(int|float $value = 1)                                                 Add millennia (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMillennium()                                                                    Add one millennium to the instance (using date interval).
 * @method        CarbonInterface  subMillennia(int|float $value = 1)                                                 Sub millennia (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMillennium()                                                                    Sub one millennium to the instance (using date interval).
 * @method        CarbonInterface  addMillenniaWithOverflow(int|float $value = 1)                                     Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMillenniumWithOverflow()                                                        Add one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMillenniaWithOverflow(int|float $value = 1)                                     Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMillenniumWithOverflow()                                                        Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMillenniaWithoutOverflow(int|float $value = 1)                                  Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniumWithoutOverflow()                                                     Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniaWithoutOverflow(int|float $value = 1)                                  Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniumWithoutOverflow()                                                     Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniaWithNoOverflow(int|float $value = 1)                                   Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniumWithNoOverflow()                                                      Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniaWithNoOverflow(int|float $value = 1)                                   Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniumWithNoOverflow()                                                      Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniaNoOverflow(int|float $value = 1)                                       Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniumNoOverflow()                                                          Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniaNoOverflow(int|float $value = 1)                                       Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniumNoOverflow()                                                          Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturies(int|float $value = 1)                                                 Add centuries (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addCentury()                                                                       Add one century to the instance (using date interval).
 * @method        CarbonInterface  subCenturies(int|float $value = 1)                                                 Sub centuries (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subCentury()                                                                       Sub one century to the instance (using date interval).
 * @method        CarbonInterface  addCenturiesWithOverflow(int|float $value = 1)                                     Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addCenturyWithOverflow()                                                           Add one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subCenturiesWithOverflow(int|float $value = 1)                                     Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subCenturyWithOverflow()                                                           Sub one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addCenturiesWithoutOverflow(int|float $value = 1)                                  Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturyWithoutOverflow()                                                        Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturiesWithoutOverflow(int|float $value = 1)                                  Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturyWithoutOverflow()                                                        Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturiesWithNoOverflow(int|float $value = 1)                                   Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturyWithNoOverflow()                                                         Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturiesWithNoOverflow(int|float $value = 1)                                   Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturyWithNoOverflow()                                                         Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturiesNoOverflow(int|float $value = 1)                                       Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturyNoOverflow()                                                             Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturiesNoOverflow(int|float $value = 1)                                       Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturyNoOverflow()                                                             Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecades(int|float $value = 1)                                                   Add decades (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addDecade()                                                                        Add one decade to the instance (using date interval).
 * @method        CarbonInterface  subDecades(int|float $value = 1)                                                   Sub decades (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subDecade()                                                                        Sub one decade to the instance (using date interval).
 * @method        CarbonInterface  addDecadesWithOverflow(int|float $value = 1)                                       Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addDecadeWithOverflow()                                                            Add one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subDecadesWithOverflow(int|float $value = 1)                                       Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subDecadeWithOverflow()                                                            Sub one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addDecadesWithoutOverflow(int|float $value = 1)                                    Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadeWithoutOverflow()                                                         Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadesWithoutOverflow(int|float $value = 1)                                    Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadeWithoutOverflow()                                                         Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadesWithNoOverflow(int|float $value = 1)                                     Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadeWithNoOverflow()                                                          Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadesWithNoOverflow(int|float $value = 1)                                     Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadeWithNoOverflow()                                                          Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadesNoOverflow(int|float $value = 1)                                         Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadeNoOverflow()                                                              Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadesNoOverflow(int|float $value = 1)                                         Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadeNoOverflow()                                                              Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarters(int|float $value = 1)                                                  Add quarters (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addQuarter()                                                                       Add one quarter to the instance (using date interval).
 * @method        CarbonInterface  subQuarters(int|float $value = 1)                                                  Sub quarters (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subQuarter()                                                                       Sub one quarter to the instance (using date interval).
 * @method        CarbonInterface  addQuartersWithOverflow(int|float $value = 1)                                      Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addQuarterWithOverflow()                                                           Add one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subQuartersWithOverflow(int|float $value = 1)                                      Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subQuarterWithOverflow()                                                           Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addQuartersWithoutOverflow(int|float $value = 1)                                   Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarterWithoutOverflow()                                                        Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuartersWithoutOverflow(int|float $value = 1)                                   Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuarterWithoutOverflow()                                                        Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuartersWithNoOverflow(int|float $value = 1)                                    Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarterWithNoOverflow()                                                         Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuartersWithNoOverflow(int|float $value = 1)                                    Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuarterWithNoOverflow()                                                         Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuartersNoOverflow(int|float $value = 1)                                        Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarterNoOverflow()                                                             Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuartersNoOverflow(int|float $value = 1)                                        Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuarterNoOverflow()                                                             Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addWeeks(int|float $value = 1)                                                     Add weeks (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addWeek()                                                                          Add one week to the instance (using date interval).
 * @method        CarbonInterface  subWeeks(int|float $value = 1)                                                     Sub weeks (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subWeek()                                                                          Sub one week to the instance (using date interval).
 * @method        CarbonInterface  addWeekdays(int|float $value = 1)                                                  Add weekdays (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addWeekday()                                                                       Add one weekday to the instance (using date interval).
 * @method        CarbonInterface  subWeekdays(int|float $value = 1)                                                  Sub weekdays (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subWeekday()                                                                       Sub one weekday to the instance (using date interval).
 * @method        CarbonInterface  addUTCMicros(int|float $value = 1)                                                 Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMicro()                                                                      Add one microsecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicros(int|float $value = 1)                                                 Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicro()                                                                      Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicros(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        CarbonInterface  addUTCMicroseconds(int|float $value = 1)                                           Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMicrosecond()                                                                Add one microsecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicroseconds(int|float $value = 1)                                           Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicrosecond()                                                                Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicroseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        CarbonInterface  addUTCMillis(int|float $value = 1)                                                 Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMilli()                                                                      Add one millisecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillis(int|float $value = 1)                                                 Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMilli()                                                                      Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMillis(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        CarbonInterface  addUTCMilliseconds(int|float $value = 1)                                           Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMillisecond()                                                                Add one millisecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMilliseconds(int|float $value = 1)                                           Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillisecond()                                                                Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMilliseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        CarbonInterface  addUTCSeconds(int|float $value = 1)                                                Add seconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCSecond()                                                                     Add one second to the instance (using timestamp).
 * @method        CarbonInterface  subUTCSeconds(int|float $value = 1)                                                Sub seconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCSecond()                                                                     Sub one second to the instance (using timestamp).
 * @method        CarbonPeriod     secondsUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
 * @method        float            diffInUTCSeconds(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of seconds.
 * @method        CarbonInterface  addUTCMinutes(int|float $value = 1)                                                Add minutes (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMinute()                                                                     Add one minute to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMinutes(int|float $value = 1)                                                Sub minutes (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMinute()                                                                     Sub one minute to the instance (using timestamp).
 * @method        CarbonPeriod     minutesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
 * @method        float            diffInUTCMinutes(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of minutes.
 * @method        CarbonInterface  addUTCHours(int|float $value = 1)                                                  Add hours (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCHour()                                                                       Add one hour to the instance (using timestamp).
 * @method        CarbonInterface  subUTCHours(int|float $value = 1)                                                  Sub hours (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCHour()                                                                       Sub one hour to the instance (using timestamp).
 * @method        CarbonPeriod     hoursUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
 * @method        float            diffInUTCHours(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of hours.
 * @method        CarbonInterface  addUTCDays(int|float $value = 1)                                                   Add days (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCDay()                                                                        Add one day to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDays(int|float $value = 1)                                                   Sub days (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDay()                                                                        Sub one day to the instance (using timestamp).
 * @method        CarbonPeriod     daysUntil($endDate = null, int|float $factor = 1)                                  Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
 * @method        float            diffInUTCDays(DateTimeInterface|string|null $date, bool $absolute = false)         Convert current and given date in UTC timezone and return a floating number of days.
 * @method        CarbonInterface  addUTCWeeks(int|float $value = 1)                                                  Add weeks (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCWeek()                                                                       Add one week to the instance (using timestamp).
 * @method        CarbonInterface  subUTCWeeks(int|float $value = 1)                                                  Sub weeks (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCWeek()                                                                       Sub one week to the instance (using timestamp).
 * @method        CarbonPeriod     weeksUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
 * @method        float            diffInUTCWeeks(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of weeks.
 * @method        CarbonInterface  addUTCMonths(int|float $value = 1)                                                 Add months (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMonth()                                                                      Add one month to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMonths(int|float $value = 1)                                                 Sub months (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMonth()                                                                      Sub one month to the instance (using timestamp).
 * @method        CarbonPeriod     monthsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
 * @method        float            diffInUTCMonths(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of months.
 * @method        CarbonInterface  addUTCQuarters(int|float $value = 1)                                               Add quarters (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCQuarter()                                                                    Add one quarter to the instance (using timestamp).
 * @method        CarbonInterface  subUTCQuarters(int|float $value = 1)                                               Sub quarters (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCQuarter()                                                                    Sub one quarter to the instance (using timestamp).
 * @method        CarbonPeriod     quartersUntil($endDate = null, int|float $factor = 1)                              Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
 * @method        float            diffInUTCQuarters(DateTimeInterface|string|null $date, bool $absolute = false)     Convert current and given date in UTC timezone and return a floating number of quarters.
 * @method        CarbonInterface  addUTCYears(int|float $value = 1)                                                  Add years (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCYear()                                                                       Add one year to the instance (using timestamp).
 * @method        CarbonInterface  subUTCYears(int|float $value = 1)                                                  Sub years (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCYear()                                                                       Sub one year to the instance (using timestamp).
 * @method        CarbonPeriod     yearsUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
 * @method        float            diffInUTCYears(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of years.
 * @method        CarbonInterface  addUTCDecades(int|float $value = 1)                                                Add decades (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCDecade()                                                                     Add one decade to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDecades(int|float $value = 1)                                                Sub decades (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDecade()                                                                     Sub one decade to the instance (using timestamp).
 * @method        CarbonPeriod     decadesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
 * @method        float            diffInUTCDecades(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of decades.
 * @method        CarbonInterface  addUTCCenturies(int|float $value = 1)                                              Add centuries (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCCentury()                                                                    Add one century to the instance (using timestamp).
 * @method        CarbonInterface  subUTCCenturies(int|float $value = 1)                                              Sub centuries (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCCentury()                                                                    Sub one century to the instance (using timestamp).
 * @method        CarbonPeriod     centuriesUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
 * @method        float            diffInUTCCenturies(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of centuries.
 * @method        CarbonInterface  addUTCMillennia(int|float $value = 1)                                              Add millennia (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMillennium()                                                                 Add one millennium to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillennia(int|float $value = 1)                                              Sub millennia (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillennium()                                                                 Sub one millennium to the instance (using timestamp).
 * @method        CarbonPeriod     millenniaUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
 * @method        float            diffInUTCMillennia(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of millennia.
 * @method        CarbonInterface  roundYear(float $precision = 1, string $function = "round")                        Round the current instance year with given precision using the given function.
 * @method        CarbonInterface  roundYears(float $precision = 1, string $function = "round")                       Round the current instance year with given precision using the given function.
 * @method        CarbonInterface  floorYear(float $precision = 1)                                                    Truncate the current instance year with given precision.
 * @method        CarbonInterface  floorYears(float $precision = 1)                                                   Truncate the current instance year with given precision.
 * @method        CarbonInterface  ceilYear(float $precision = 1)                                                     Ceil the current instance year with given precision.
 * @method        CarbonInterface  ceilYears(float $precision = 1)                                                    Ceil the current instance year with given precision.
 * @method        CarbonInterface  roundMonth(float $precision = 1, string $function = "round")                       Round the current instance month with given precision using the given function.
 * @method        CarbonInterface  roundMonths(float $precision = 1, string $function = "round")                      Round the current instance month with given precision using the given function.
 * @method        CarbonInterface  floorMonth(float $precision = 1)                                                   Truncate the current instance month with given precision.
 * @method        CarbonInterface  floorMonths(float $precision = 1)                                                  Truncate the current instance month with given precision.
 * @method        CarbonInterface  ceilMonth(float $precision = 1)                                                    Ceil the current instance month with given precision.
 * @method        CarbonInterface  ceilMonths(float $precision = 1)                                                   Ceil the current instance month with given precision.
 * @method        CarbonInterface  roundDay(float $precision = 1, string $function = "round")                         Round the current instance day with given precision using the given function.
 * @method        CarbonInterface  roundDays(float $precision = 1, string $function = "round")                        Round the current instance day with given precision using the given function.
 * @method        CarbonInterface  floorDay(float $precision = 1)                                                     Truncate the current instance day with given precision.
 * @method        CarbonInterface  floorDays(float $precision = 1)                                                    Truncate the current instance day with given precision.
 * @method        CarbonInterface  ceilDay(float $precision = 1)                                                      Ceil the current instance day with given precision.
 * @method        CarbonInterface  ceilDays(float $precision = 1)                                                     Ceil the current instance day with given precision.
 * @method        CarbonInterface  roundHour(float $precision = 1, string $function = "round")                        Round the current instance hour with given precision using the given function.
 * @method        CarbonInterface  roundHours(float $precision = 1, string $function = "round")                       Round the current instance hour with given precision using the given function.
 * @method        CarbonInterface  floorHour(float $precision = 1)                                                    Truncate the current instance hour with given precision.
 * @method        CarbonInterface  floorHours(float $precision = 1)                                                   Truncate the current instance hour with given precision.
 * @method        CarbonInterface  ceilHour(float $precision = 1)                                                     Ceil the current instance hour with given precision.
 * @method        CarbonInterface  ceilHours(float $precision = 1)                                                    Ceil the current instance hour with given precision.
 * @method        CarbonInterface  roundMinute(float $precision = 1, string $function = "round")                      Round the current instance minute with given precision using the given function.
 * @method        CarbonInterface  roundMinutes(float $precision = 1, string $function = "round")                     Round the current instance minute with given precision using the given function.
 * @method        CarbonInterface  floorMinute(float $precision = 1)                                                  Truncate the current instance minute with given precision.
 * @method        CarbonInterface  floorMinutes(float $precision = 1)                                                 Truncate the current instance minute with given precision.
 * @method        CarbonInterface  ceilMinute(float $precision = 1)                                                   Ceil the current instance minute with given precision.
 * @method        CarbonInterface  ceilMinutes(float $precision = 1)                                                  Ceil the current instance minute with given precision.
 * @method        CarbonInterface  roundSecond(float $precision = 1, string $function = "round")                      Round the current instance second with given precision using the given function.
 * @method        CarbonInterface  roundSeconds(float $precision = 1, string $function = "round")                     Round the current instance second with given precision using the given function.
 * @method        CarbonInterface  floorSecond(float $precision = 1)                                                  Truncate the current instance second with given precision.
 * @method        CarbonInterface  floorSeconds(float $precision = 1)                                                 Truncate the current instance second with given precision.
 * @method        CarbonInterface  ceilSecond(float $precision = 1)                                                   Ceil the current instance second with given precision.
 * @method        CarbonInterface  ceilSeconds(float $precision = 1)                                                  Ceil the current instance second with given precision.
 * @method        CarbonInterface  roundMillennium(float $precision = 1, string $function = "round")                  Round the current instance millennium with given precision using the given function.
 * @method        CarbonInterface  roundMillennia(float $precision = 1, string $function = "round")                   Round the current instance millennium with given precision using the given function.
 * @method        CarbonInterface  floorMillennium(float $precision = 1)                                              Truncate the current instance millennium with given precision.
 * @method        CarbonInterface  floorMillennia(float $precision = 1)                                               Truncate the current instance millennium with given precision.
 * @method        CarbonInterface  ceilMillennium(float $precision = 1)                                               Ceil the current instance millennium with given precision.
 * @method        CarbonInterface  ceilMillennia(float $precision = 1)                                                Ceil the current instance millennium with given precision.
 * @method        CarbonInterface  roundCentury(float $precision = 1, string $function = "round")                     Round the current instance century with given precision using the given function.
 * @method        CarbonInterface  roundCenturies(float $precision = 1, string $function = "round")                   Round the current instance century with given precision using the given function.
 * @method        CarbonInterface  floorCentury(float $precision = 1)                                                 Truncate the current instance century with given precision.
 * @method        CarbonInterface  floorCenturies(float $precision = 1)                                               Truncate the current instance century with given precision.
 * @method        CarbonInterface  ceilCentury(float $precision = 1)                                                  Ceil the current instance century with given precision.
 * @method        CarbonInterface  ceilCenturies(float $precision = 1)                                                Ceil the current instance century with given precision.
 * @method        CarbonInterface  roundDecade(float $precision = 1, string $function = "round")                      Round the current instance decade with given precision using the given function.
 * @method        CarbonInterface  roundDecades(float $precision = 1, string $function = "round")                     Round the current instance decade with given precision using the given function.
 * @method        CarbonInterface  floorDecade(float $precision = 1)                                                  Truncate the current instance decade with given precision.
 * @method        CarbonInterface  floorDecades(float $precision = 1)                                                 Truncate the current instance decade with given precision.
 * @method        CarbonInterface  ceilDecade(float $precision = 1)                                                   Ceil the current instance decade with given precision.
 * @method        CarbonInterface  ceilDecades(float $precision = 1)                                                  Ceil the current instance decade with given precision.
 * @method        CarbonInterface  roundQuarter(float $precision = 1, string $function = "round")                     Round the current instance quarter with given precision using the given function.
 * @method        CarbonInterface  roundQuarters(float $precision = 1, string $function = "round")                    Round the current instance quarter with given precision using the given function.
 * @method        CarbonInterface  floorQuarter(float $precision = 1)                                                 Truncate the current instance quarter with given precision.
 * @method        CarbonInterface  floorQuarters(float $precision = 1)                                                Truncate the current instance quarter with given precision.
 * @method        CarbonInterface  ceilQuarter(float $precision = 1)                                                  Ceil the current instance quarter with given precision.
 * @method        CarbonInterface  ceilQuarters(float $precision = 1)                                                 Ceil the current instance quarter with given precision.
 * @method        CarbonInterface  roundMillisecond(float $precision = 1, string $function = "round")                 Round the current instance millisecond with given precision using the given function.
 * @method        CarbonInterface  roundMilliseconds(float $precision = 1, string $function = "round")                Round the current instance millisecond with given precision using the given function.
 * @method        CarbonInterface  floorMillisecond(float $precision = 1)                                             Truncate the current instance millisecond with given precision.
 * @method        CarbonInterface  floorMilliseconds(float $precision = 1)                                            Truncate the current instance millisecond with given precision.
 * @method        CarbonInterface  ceilMillisecond(float $precision = 1)                                              Ceil the current instance millisecond with given precision.
 * @method        CarbonInterface  ceilMilliseconds(float $precision = 1)                                             Ceil the current instance millisecond with given precision.
 * @method        CarbonInterface  roundMicrosecond(float $precision = 1, string $function = "round")                 Round the current instance microsecond with given precision using the given function.
 * @method        CarbonInterface  roundMicroseconds(float $precision = 1, string $function = "round")                Round the current instance microsecond with given precision using the given function.
 * @method        CarbonInterface  floorMicrosecond(float $precision = 1)                                             Truncate the current instance microsecond with given precision.
 * @method        CarbonInterface  floorMicroseconds(float $precision = 1)                                            Truncate the current instance microsecond with given precision.
 * @method        CarbonInterface  ceilMicrosecond(float $precision = 1)                                              Ceil the current instance microsecond with given precision.
 * @method        CarbonInterface  ceilMicroseconds(float $precision = 1)                                             Ceil the current instance microsecond with given precision.
 * @method        string           shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)   Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)    Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1)  Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        int              centuriesInMillennium()                                                            Return the number of centuries contained in the current millennium
 * @method        int|static       centuryOfMillennium(?int $century = null)                                          Return the value of the century starting from the beginning of the current millennium when called with no parameters, change the current century when called with an integer value
 * @method        int|static       dayOfCentury(?int $day = null)                                                     Return the value of the day starting from the beginning of the current century when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfDecade(?int $day = null)                                                      Return the value of the day starting from the beginning of the current decade when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMillennium(?int $day = null)                                                  Return the value of the day starting from the beginning of the current millennium when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMonth(?int $day = null)                                                       Return the value of the day starting from the beginning of the current month when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfQuarter(?int $day = null)                                                     Return the value of the day starting from the beginning of the current quarter when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfWeek(?int $day = null)                                                        Return the value of the day starting from the beginning of the current week when called with no parameters, change the current day when called with an integer value
 * @method        int              daysInCentury()                                                                    Return the number of days contained in the current century
 * @method        int              daysInDecade()                                                                     Return the number of days contained in the current decade
 * @method        int              daysInMillennium()                                                                 Return the number of days contained in the current millennium
 * @method        int              daysInMonth()                                                                      Return the number of days contained in the current month
 * @method        int              daysInQuarter()                                                                    Return the number of days contained in the current quarter
 * @method        int              daysInWeek()                                                                       Return the number of days contained in the current week
 * @method        int              daysInYear()                                                                       Return the number of days contained in the current year
 * @method        int|static       decadeOfCentury(?int $decade = null)                                               Return the value of the decade starting from the beginning of the current century when called with no parameters, change the current decade when called with an integer value
 * @method        int|static       decadeOfMillennium(?int $decade = null)                                            Return the value of the decade starting from the beginning of the current millennium when called with no parameters, change the current decade when called with an integer value
 * @method        int              decadesInCentury()                                                                 Return the number of decades contained in the current century
 * @method        int              decadesInMillennium()                                                              Return the number of decades contained in the current millennium
 * @method        int|static       hourOfCentury(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current century when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDay(?int $hour = null)                                                       Return the value of the hour starting from the beginning of the current day when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDecade(?int $hour = null)                                                    Return the value of the hour starting from the beginning of the current decade when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMillennium(?int $hour = null)                                                Return the value of the hour starting from the beginning of the current millennium when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMonth(?int $hour = null)                                                     Return the value of the hour starting from the beginning of the current month when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfQuarter(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current quarter when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfWeek(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current week when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfYear(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current year when called with no parameters, change the current hour when called with an integer value
 * @method        int              hoursInCentury()                                                                   Return the number of hours contained in the current century
 * @method        int              hoursInDay()                                                                       Return the number of hours contained in the current day
 * @method        int              hoursInDecade()                                                                    Return the number of hours contained in the current decade
 * @method        int              hoursInMillennium()                                                                Return the number of hours contained in the current millennium
 * @method        int              hoursInMonth()                                                                     Return the number of hours contained in the current month
 * @method        int              hoursInQuarter()                                                                   Return the number of hours contained in the current quarter
 * @method        int              hoursInWeek()                                                                      Return the number of hours contained in the current week
 * @method        int              hoursInYear()                                                                      Return the number of hours contained in the current year
 * @method        int|static       microsecondOfCentury(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current century when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDay(?int $microsecond = null)                                         Return the value of the microsecond starting from the beginning of the current day when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDecade(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current decade when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfHour(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current hour when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillennium(?int $microsecond = null)                                  Return the value of the microsecond starting from the beginning of the current millennium when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillisecond(?int $microsecond = null)                                 Return the value of the microsecond starting from the beginning of the current millisecond when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMinute(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current minute when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMonth(?int $microsecond = null)                                       Return the value of the microsecond starting from the beginning of the current month when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfQuarter(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current quarter when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfSecond(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current second when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfWeek(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current week when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfYear(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current year when called with no parameters, change the current microsecond when called with an integer value
 * @method        int              microsecondsInCentury()                                                            Return the number of microseconds contained in the current century
 * @method        int              microsecondsInDay()                                                                Return the number of microseconds contained in the current day
 * @method        int              microsecondsInDecade()                                                             Return the number of microseconds contained in the current decade
 * @method        int              microsecondsInHour()                                                               Return the number of microseconds contained in the current hour
 * @method        int              microsecondsInMillennium()                                                         Return the number of microseconds contained in the current millennium
 * @method        int              microsecondsInMillisecond()                                                        Return the number of microseconds contained in the current millisecond
 * @method        int              microsecondsInMinute()                                                             Return the number of microseconds contained in the current minute
 * @method        int              microsecondsInMonth()                                                              Return the number of microseconds contained in the current month
 * @method        int              microsecondsInQuarter()                                                            Return the number of microseconds contained in the current quarter
 * @method        int              microsecondsInSecond()                                                             Return the number of microseconds contained in the current second
 * @method        int              microsecondsInWeek()                                                               Return the number of microseconds contained in the current week
 * @method        int              microsecondsInYear()                                                               Return the number of microseconds contained in the current year
 * @method        int|static       millisecondOfCentury(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current century when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDay(?int $millisecond = null)                                         Return the value of the millisecond starting from the beginning of the current day when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDecade(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current decade when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfHour(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current hour when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMillennium(?int $millisecond = null)                                  Return the value of the millisecond starting from the beginning of the current millennium when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMinute(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current minute when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMonth(?int $millisecond = null)                                       Return the value of the millisecond starting from the beginning of the current month when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfQuarter(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current quarter when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfSecond(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current second when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfWeek(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current week when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfYear(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current year when called with no parameters, change the current millisecond when called with an integer value
 * @method        int              millisecondsInCentury()                                                            Return the number of milliseconds contained in the current century
 * @method        int              millisecondsInDay()                                                                Return the number of milliseconds contained in the current day
 * @method        int              millisecondsInDecade()                                                             Return the number of milliseconds contained in the current decade
 * @method        int              millisecondsInHour()                                                               Return the number of milliseconds contained in the current hour
 * @method        int              millisecondsInMillennium()                                                         Return the number of milliseconds contained in the current millennium
 * @method        int              millisecondsInMinute()                                                             Return the number of milliseconds contained in the current minute
 * @method        int              millisecondsInMonth()                                                              Return the number of milliseconds contained in the current month
 * @method        int              millisecondsInQuarter()                                                            Return the number of milliseconds contained in the current quarter
 * @method        int              millisecondsInSecond()                                                             Return the number of milliseconds contained in the current second
 * @method        int              millisecondsInWeek()                                                               Return the number of milliseconds contained in the current week
 * @method        int              millisecondsInYear()                                                               Return the number of milliseconds contained in the current year
 * @method        int|static       minuteOfCentury(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current century when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDay(?int $minute = null)                                                   Return the value of the minute starting from the beginning of the current day when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDecade(?int $minute = null)                                                Return the value of the minute starting from the beginning of the current decade when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfHour(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current hour when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMillennium(?int $minute = null)                                            Return the value of the minute starting from the beginning of the current millennium when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMonth(?int $minute = null)                                                 Return the value of the minute starting from the beginning of the current month when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfQuarter(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current quarter when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfWeek(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current week when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfYear(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current year when called with no parameters, change the current minute when called with an integer value
 * @method        int              minutesInCentury()                                                                 Return the number of minutes contained in the current century
 * @method        int              minutesInDay()                                                                     Return the number of minutes contained in the current day
 * @method        int              minutesInDecade()                                                                  Return the number of minutes contained in the current decade
 * @method        int              minutesInHour()                                                                    Return the number of minutes contained in the current hour
 * @method        int              minutesInMillennium()                                                              Return the number of minutes contained in the current millennium
 * @method        int              minutesInMonth()                                                                   Return the number of minutes contained in the current month
 * @method        int              minutesInQuarter()                                                                 Return the number of minutes contained in the current quarter
 * @method        int              minutesInWeek()                                                                    Return the number of minutes contained in the current week
 * @method        int              minutesInYear()                                                                    Return the number of minutes contained in the current year
 * @method        int|static       monthOfCentury(?int $month = null)                                                 Return the value of the month starting from the beginning of the current century when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfDecade(?int $month = null)                                                  Return the value of the month starting from the beginning of the current decade when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfMillennium(?int $month = null)                                              Return the value of the month starting from the beginning of the current millennium when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfQuarter(?int $month = null)                                                 Return the value of the month starting from the beginning of the current quarter when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfYear(?int $month = null)                                                    Return the value of the month starting from the beginning of the current year when called with no parameters, change the current month when called with an integer value
 * @method        int              monthsInCentury()                                                                  Return the number of months contained in the current century
 * @method        int              monthsInDecade()                                                                   Return the number of months contained in the current decade
 * @method        int              monthsInMillennium()                                                               Return the number of months contained in the current millennium
 * @method        int              monthsInQuarter()                                                                  Return the number of months contained in the current quarter
 * @method        int              monthsInYear()                                                                     Return the number of months contained in the current year
 * @method        int|static       quarterOfCentury(?int $quarter = null)                                             Return the value of the quarter starting from the beginning of the current century when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfDecade(?int $quarter = null)                                              Return the value of the quarter starting from the beginning of the current decade when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfMillennium(?int $quarter = null)                                          Return the value of the quarter starting from the beginning of the current millennium when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfYear(?int $quarter = null)                                                Return the value of the quarter starting from the beginning of the current year when called with no parameters, change the current quarter when called with an integer value
 * @method        int              quartersInCentury()                                                                Return the number of quarters contained in the current century
 * @method        int              quartersInDecade()                                                                 Return the number of quarters contained in the current decade
 * @method        int              quartersInMillennium()                                                             Return the number of quarters contained in the current millennium
 * @method        int              quartersInYear()                                                                   Return the number of quarters contained in the current year
 * @method        int|static       secondOfCentury(?int $second = null)                                               Return the value of the second starting from the beginning of the current century when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDay(?int $second = null)                                                   Return the value of the second starting from the beginning of the current day when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDecade(?int $second = null)                                                Return the value of the second starting from the beginning of the current decade when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfHour(?int $second = null)                                                  Return the value of the second starting from the beginning of the current hour when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMillennium(?int $second = null)                                            Return the value of the second starting from the beginning of the current millennium when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMinute(?int $second = null)                                                Return the value of the second starting from the beginning of the current minute when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMonth(?int $second = null)                                                 Return the value of the second starting from the beginning of the current month when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfQuarter(?int $second = null)                                               Return the value of the second starting from the beginning of the current quarter when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfWeek(?int $second = null)                                                  Return the value of the second starting from the beginning of the current week when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfYear(?int $second = null)                                                  Return the value of the second starting from the beginning of the current year when called with no parameters, change the current second when called with an integer value
 * @method        int              secondsInCentury()                                                                 Return the number of seconds contained in the current century
 * @method        int              secondsInDay()                                                                     Return the number of seconds contained in the current day
 * @method        int              secondsInDecade()                                                                  Return the number of seconds contained in the current decade
 * @method        int              secondsInHour()                                                                    Return the number of seconds contained in the current hour
 * @method        int              secondsInMillennium()                                                              Return the number of seconds contained in the current millennium
 * @method        int              secondsInMinute()                                                                  Return the number of seconds contained in the current minute
 * @method        int              secondsInMonth()                                                                   Return the number of seconds contained in the current month
 * @method        int              secondsInQuarter()                                                                 Return the number of seconds contained in the current quarter
 * @method        int              secondsInWeek()                                                                    Return the number of seconds contained in the current week
 * @method        int              secondsInYear()                                                                    Return the number of seconds contained in the current year
 * @method        int|static       weekOfCentury(?int $week = null)                                                   Return the value of the week starting from the beginning of the current century when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfDecade(?int $week = null)                                                    Return the value of the week starting from the beginning of the current decade when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMillennium(?int $week = null)                                                Return the value of the week starting from the beginning of the current millennium when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMonth(?int $week = null)                                                     Return the value of the week starting from the beginning of the current month when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfQuarter(?int $week = null)                                                   Return the value of the week starting from the beginning of the current quarter when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfYear(?int $week = null)                                                      Return the value of the week starting from the beginning of the current year when called with no parameters, change the current week when called with an integer value
 * @method        int              weeksInCentury()                                                                   Return the number of weeks contained in the current century
 * @method        int              weeksInDecade()                                                                    Return the number of weeks contained in the current decade
 * @method        int              weeksInMillennium()                                                                Return the number of weeks contained in the current millennium
 * @method        int              weeksInMonth()                                                                     Return the number of weeks contained in the current month
 * @method        int              weeksInQuarter()                                                                   Return the number of weeks contained in the current quarter
 * @method        int|static       yearOfCentury(?int $year = null)                                                   Return the value of the year starting from the beginning of the current century when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfDecade(?int $year = null)                                                    Return the value of the year starting from the beginning of the current decade when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfMillennium(?int $year = null)                                                Return the value of the year starting from the beginning of the current millennium when called with no parameters, change the current year when called with an integer value
 * @method        int              yearsInCentury()                                                                   Return the number of years contained in the current century
 * @method        int              yearsInDecade()                                                                    Return the number of years contained in the current decade
 * @method        int              yearsInMillennium()                                                                Return the number of years contained in the current millennium
 *
 * </autodoc>
 */
trait Date
{
    use Boundaries;
    use Comparison;
    use Converter;
    use Creator;
    use Difference;
    use Macro;
    use MagicParameter;
    use Modifiers;
    use Mutability;
    use ObjectInitialisation;
    use Options;
    use Rounding;
    use Serialization;
    use Test;
    use Timestamp;
    use Units;
    use Week;

    /**
     * Names of days of the week.
     *
     * @var array
     */
    protected static $days = [
        // @call isDayOfWeek
        CarbonInterface::SUNDAY => 'Sunday',
        // @call isDayOfWeek
        CarbonInterface::MONDAY => 'Monday',
        // @call isDayOfWeek
        CarbonInterface::TUESDAY => 'Tuesday',
        // @call isDayOfWeek
        CarbonInterface::WEDNESDAY => 'Wednesday',
        // @call isDayOfWeek
        CarbonInterface::THURSDAY => 'Thursday',
        // @call isDayOfWeek
        CarbonInterface::FRIDAY => 'Friday',
        // @call isDayOfWeek
        CarbonInterface::SATURDAY => 'Saturday',
    ];

    /**
     * List of unit and magic methods associated as doc-comments.
     *
     * @var array
     */
    protected static $units = [
        // @call setUnit
        // @call addUnit
        'year',
        // @call setUnit
        // @call addUnit
        'month',
        // @call setUnit
        // @call addUnit
        'day',
        // @call setUnit
        // @call addUnit
        'hour',
        // @call setUnit
        // @call addUnit
        'minute',
        // @call setUnit
        // @call addUnit
        'second',
        // @call setUnit
        // @call addUnit
        'milli',
        // @call setUnit
        // @call addUnit
        'millisecond',
        // @call setUnit
        // @call addUnit
        'micro',
        // @call setUnit
        // @call addUnit
        'microsecond',
    ];

    /**
     * Creates a DateTimeZone from a string, DateTimeZone or integer offset.
     *
     * @param DateTimeZone|string|int|false|null $object     original value to get CarbonTimeZone from it.
     * @param DateTimeZone|string|int|false|null $objectDump dump of the object for error messages.
     *
     * @throws InvalidTimeZoneException
     *
     * @return CarbonTimeZone|null
     */
    protected static function safeCreateDateTimeZone(
        DateTimeZone|string|int|false|null $object,
        DateTimeZone|string|int|false|null $objectDump = null,
    ): ?CarbonTimeZone {
        return CarbonTimeZone::instance($object, $objectDump);
    }

    /**
     * Get the TimeZone associated with the Carbon instance (as CarbonTimeZone).
     *
     * @link https://php.net/manual/en/datetime.gettimezone.php
     */
    public function getTimezone(): CarbonTimeZone
    {
        return $this->transmitFactory(fn () => CarbonTimeZone::instance(parent::getTimezone()));
    }

    /**
     * List of minimum and maximums for each unit.
     */
    protected static function getRangesByUnit(int $daysInMonth = 31): array
    {
        return [
            // @call roundUnit
            'year' => [1, 9999],
            // @call roundUnit
            'month' => [1, static::MONTHS_PER_YEAR],
            // @call roundUnit
            'day' => [1, $daysInMonth],
            // @call roundUnit
            'hour' => [0, static::HOURS_PER_DAY - 1],
            // @call roundUnit
            'minute' => [0, static::MINUTES_PER_HOUR - 1],
            // @call roundUnit
            'second' => [0, static::SECONDS_PER_MINUTE - 1],
        ];
    }

    /**
     * Get a copy of the instance.
     *
     * @return static
     */
    public function copy()
    {
        return clone $this;
    }

    /**
     * @alias copy
     *
     * Get a copy of the instance.
     *
     * @return static
     */
    public function clone()
    {
        return clone $this;
    }

    /**
     * Clone the current instance if it's mutable.
     *
     * This method is convenient to ensure you don't mutate the initial object
     * but avoid to make a useless copy of it if it's already immutable.
     *
     * @return static
     */
    public function avoidMutation(): static
    {
        if ($this instanceof DateTimeImmutable) {
            return $this;
        }

        return clone $this;
    }

    /**
     * Returns a present instance in the same timezone.
     *
     * @return static
     */
    public function nowWithSameTz(): static
    {
        $timezone = $this->getTimezone();

        return $this->getClock()?->nowAs(static::class, $timezone) ?? static::now($timezone);
    }

    /**
     * Return the Carbon instance passed through, a now instance in the same timezone
     * if null given or parse the input if string given.
     *
     * @param Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|DateTimeInterface|string|null $date
     *
     * @return static
     */
    public function carbonize($date = null)
    {
        if ($date instanceof DateInterval) {
            return $this->avoidMutation()->add($date);
        }

        if ($date instanceof DatePeriod || $date instanceof CarbonPeriod) {
            $date = $date->getStartDate();
        }

        return $this->resolveCarbon($date);
    }

    ///////////////////////////////////////////////////////////////////
    ///////////////////////// GETTERS AND SETTERS /////////////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Get a part of the Carbon object.
     *
     * @throws UnknownGetterException
     *
     * @return string|int|bool|DateTimeZone|null
     */
    public function __get(string $name): mixed
    {
        return $this->get($name);
    }

    /**
     * Get a part of the Carbon object.
     *
     * @throws UnknownGetterException
     *
     * @return string|int|bool|DateTimeZone
     */
    public function get(Unit|string $name): mixed
    {
        static $localizedFormats = [
            // @property string the day of week in current locale
            'localeDayOfWeek' => 'dddd',
            // @property string the abbreviated day of week in current locale
            'shortLocaleDayOfWeek' => 'ddd',
            // @property string the month in current locale
            'localeMonth' => 'MMMM',
            // @property string the abbreviated month in current locale
            'shortLocaleMonth' => 'MMM',
        ];

        $name = Unit::toName($name);

        if (isset($localizedFormats[$name])) {
            return $this->isoFormat($localizedFormats[$name]);
        }

        static $formats = [
            // @property int
            'year' => 'Y',
            // @property int
            'yearIso' => 'o',
            // @--property-read int
            // @--property-write Month|int
            // @property int
            'month' => 'n',
            // @property int
            'day' => 'j',
            // @property int
            'hour' => 'G',
            // @property int
            'minute' => 'i',
            // @property int
            'second' => 's',
            // @property int
            'micro' => 'u',
            // @property int
            'microsecond' => 'u',
            // @property int 0 (for Sunday) through 6 (for Saturday)
            'dayOfWeek' => 'w',
            // @property int 1 (for Monday) through 7 (for Sunday)
            'dayOfWeekIso' => 'N',
            // @property int ISO-8601 week number of year, weeks starting on Monday
            'weekOfYear' => 'W',
            // @property-read int number of days in the given month
            'daysInMonth' => 't',
            // @property int|float|string seconds since the Unix Epoch
            'timestamp' => 'U',
            // @property-read string "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
            'latinMeridiem' => 'a',
            // @property-read string "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
            'latinUpperMeridiem' => 'A',
            // @property string the day of week in English
            'englishDayOfWeek' => 'l',
            // @property string the abbreviated day of week in English
            'shortEnglishDayOfWeek' => 'D',
            // @property string the month in English
            'englishMonth' => 'F',
            // @property string the abbreviated month in English
            'shortEnglishMonth' => 'M',
            // @property-read string $timezoneAbbreviatedName the current timezone abbreviated name
            'timezoneAbbreviatedName' => 'T',
            // @property-read string $tzAbbrName alias of $timezoneAbbreviatedName
            'tzAbbrName' => 'T',
        ];

        switch (true) {
            case isset($formats[$name]):
                $value = $this->rawFormat($formats[$name]);

                return is_numeric($value) ? (int) $value : $value;

            // @property-read string long name of weekday translated according to Carbon locale, in english if no translation available for current language
            case $name === 'dayName':
                return $this->getTranslatedDayName();
            // @property-read string short name of weekday translated according to Carbon locale, in english if no translation available for current language
            case $name === 'shortDayName':
                return $this->getTranslatedShortDayName();
            // @property-read string very short name of weekday translated according to Carbon locale, in english if no translation available for current language
            case $name === 'minDayName':
                return $this->getTranslatedMinDayName();
            // @property-read string long name of month translated according to Carbon locale, in english if no translation available for current language
            case $name === 'monthName':
                return $this->getTranslatedMonthName();
            // @property-read string short name of month translated according to Carbon locale, in english if no translation available for current language
            case $name === 'shortMonthName':
                return $this->getTranslatedShortMonthName();
            // @property-read string lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
            case $name === 'meridiem':
                return $this->meridiem(true);
            // @property-read string uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
            case $name === 'upperMeridiem':
                return $this->meridiem();
            // @property-read int current hour from 1 to 24
            case $name === 'noZeroHour':
                return $this->hour ?: 24;
            // @property int
            case $name === 'milliseconds':
                // @property int
            case $name === 'millisecond':
            // @property int
            case $name === 'milli':
                return (int) floor(((int) $this->rawFormat('u')) / 1000);

            // @property int 1 through 53
            case $name === 'week':
                return (int) $this->week();

            // @property int 1 through 53
            case $name === 'isoWeek':
                return (int) $this->isoWeek();

            // @property int year according to week format
            case $name === 'weekYear':
                return (int) $this->weekYear();

            // @property int year according to ISO week format
            case $name === 'isoWeekYear':
                return (int) $this->isoWeekYear();

            // @property-read int 51 through 53
            case $name === 'weeksInYear':
                return $this->weeksInYear();

            // @property-read int 51 through 53
            case $name === 'isoWeeksInYear':
                return $this->isoWeeksInYear();

            // @property int 1 through 5
            case $name === 'weekOfMonth':
                return (int) ceil($this->day / static::DAYS_PER_WEEK);

            // @property-read int 1 through 5
            case $name === 'weekNumberInMonth':
                return (int) ceil(($this->day + $this->avoidMutation()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);

            // @property-read int 0 through 6
            case $name === 'firstWeekDay':
                return (int) $this->getTranslationMessage('first_day_of_week');

            // @property-read int 0 through 6
            case $name === 'lastWeekDay':
                return $this->transmitFactory(fn () => static::weekRotate((int) $this->getTranslationMessage('first_day_of_week'), -1));

            // @property int 1 through 366
            case $name === 'dayOfYear':
                return 1 + (int) ($this->rawFormat('z'));

            // @property-read int 365 or 366
            case $name === 'daysInYear':
                return static::DAYS_PER_YEAR + ($this->isLeapYear() ? 1 : 0);

            // @property int does a diffInYears() with default parameters
            case $name === 'age':
                return (int) $this->diffInYears();

            // @property-read int the quarter of this instance, 1 - 4
            case $name === 'quarter':
                return (int) ceil($this->month / static::MONTHS_PER_QUARTER);

            // @property-read int the decade of this instance
            // @call isSameUnit
            case $name === 'decade':
                return (int) ceil($this->year / static::YEARS_PER_DECADE);

            // @property-read int the century of this instance
            // @call isSameUnit
            case $name === 'century':
                $factor = 1;
                $year = $this->year;

                if ($year < 0) {
                    $year = -$year;
                    $factor = -1;
                }

                return (int) ($factor * ceil($year / static::YEARS_PER_CENTURY));

            // @property-read int the millennium of this instance
            // @call isSameUnit
            case $name === 'millennium':
                $factor = 1;
                $year = $this->year;

                if ($year < 0) {
                    $year = -$year;
                    $factor = -1;
                }

                return (int) ($factor * ceil($year / static::YEARS_PER_MILLENNIUM));

            // @property int the timezone offset in seconds from UTC
            case $name === 'offset':
                return $this->getOffset();

            // @property int the timezone offset in minutes from UTC
            case $name === 'offsetMinutes':
                return $this->getOffset() / static::SECONDS_PER_MINUTE;

            // @property int the timezone offset in hours from UTC
            case $name === 'offsetHours':
                return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR;

            // @property-read bool daylight savings time indicator, true if DST, false otherwise
            case $name === 'dst':
                return $this->rawFormat('I') === '1';

            // @property-read bool checks if the timezone is local, true if local, false otherwise
            case $name === 'local':
                return $this->getOffset() === $this->avoidMutation()->setTimezone(date_default_timezone_get())->getOffset();

            // @property-read bool checks if the timezone is UTC, true if UTC, false otherwise
            case $name === 'utc':
                return $this->getOffset() === 0;

            // @--property-write DateTimeZone|string|int $timezone the current timezone
            // @--property-write DateTimeZone|string|int $tz alias of $timezone
            // @--property-read CarbonTimeZone $timezone the current timezone
            // @--property-read CarbonTimeZone $tz alias of $timezone
            // @property CarbonTimeZone $timezone the current timezone
            // @property CarbonTimeZone $tz alias of $timezone
            case $name === 'timezone' || $name === 'tz':
                return $this->getTimezone();

            // @property-read string $timezoneName the current timezone name
            // @property-read string $tzName alias of $timezoneName
            case $name === 'timezoneName' || $name === 'tzName':
                return $this->getTimezone()->getName();

            // @property-read string locale of the current instance
            case $name === 'locale':
                return $this->getTranslatorLocale();

            case preg_match('/^([a-z]{2,})(In|Of)([A-Z][a-z]+)$/', $name, $match):
                [, $firstUnit, $operator, $secondUnit] = $match;

                try {
                    $start = $this->avoidMutation()->startOf($secondUnit);
                    $value = $operator === 'Of'
                        ? (\in_array($firstUnit, [
                            // Unit with indexes starting at 1 (other units start at 0)
                            'day',
                            'week',
                            'month',
                            'quarter',
                        ], true) ? 1 : 0) + floor($start->diffInUnit($firstUnit, $this))
                        : round($start->diffInUnit($firstUnit, $start->avoidMutation()->add($secondUnit, 1)));

                    return (int) $value;
                } catch (UnknownUnitException) {
                    // default to macro
                }

            default:
                $macro = $this->getLocalMacro('get'.ucfirst($name));

                if ($macro) {
                    return $this->executeCallableWithContext($macro);
                }

                throw new UnknownGetterException($name);
        }
    }

    /**
     * Check if an attribute exists on the object
     *
     * @param string $name
     *
     * @return bool
     */
    public function __isset($name)
    {
        try {
            $this->__get($name);
        } catch (UnknownGetterException | ReflectionException) {
            return false;
        }

        return true;
    }

    /**
     * Set a part of the Carbon object
     *
     * @param string                  $name
     * @param string|int|DateTimeZone $value
     *
     * @throws UnknownSetterException|ReflectionException
     *
     * @return void
     */
    public function __set($name, $value)
    {
        if ($this->constructedObjectId === spl_object_hash($this)) {
            $this->set($name, $value);

            return;
        }

        $this->$name = $value;
    }

    /**
     * Set a part of the Carbon object.
     *
     * @throws ImmutableException|UnknownSetterException
     *
     * @return $this
     */
    public function set(Unit|array|string $name, DateTimeZone|Month|string|int|float|null $value = null): static
    {
        if ($this->isImmutable()) {
            throw new ImmutableException(\sprintf('%s class', static::class));
        }

        if (\is_array($name)) {
            foreach ($name as $key => $value) {
                $this->set($key, $value);
            }

            return $this;
        }

        $name = Unit::toName($name);

        switch ($name) {
            case 'milliseconds':
            case 'millisecond':
            case 'milli':
            case 'microseconds':
            case 'microsecond':
            case 'micro':
                if (str_starts_with($name, 'milli')) {
                    $value *= 1000;
                }

                while ($value < 0) {
                    $this->subSecond();
                    $value += static::MICROSECONDS_PER_SECOND;
                }

                while ($value >= static::MICROSECONDS_PER_SECOND) {
                    $this->addSecond();
                    $value -= static::MICROSECONDS_PER_SECOND;
                }

                $this->modify($this->rawFormat('H:i:s.').str_pad((string) round($value), 6, '0', STR_PAD_LEFT));

                break;

            case 'year':
            case 'month':
            case 'day':
            case 'hour':
            case 'minute':
            case 'second':
                [$year, $month, $day, $hour, $minute, $second] = array_map('intval', explode('-', $this->rawFormat('Y-n-j-G-i-s')));
                $$name = self::monthToInt($value, $name);
                $this->setDateTime($year, $month, $day, $hour, $minute, $second);

                break;

            case 'week':
                $this->week($value);

                break;

            case 'isoWeek':
                $this->isoWeek($value);

                break;

            case 'weekYear':
                $this->weekYear($value);

                break;

            case 'isoWeekYear':
                $this->isoWeekYear($value);

                break;

            case 'dayOfYear':
                $this->addDays($value - $this->dayOfYear);

                break;

            case 'dayOfWeek':
                $this->addDays($value - $this->dayOfWeek);

                break;

            case 'dayOfWeekIso':
                $this->addDays($value - $this->dayOfWeekIso);

                break;

            case 'timestamp':
                $this->setTimestamp($value);

                break;

            case 'offset':
                $this->setTimezone(static::safeCreateDateTimeZone($value / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR));

                break;

            case 'offsetMinutes':
                $this->setTimezone(static::safeCreateDateTimeZone($value / static::MINUTES_PER_HOUR));

                break;

            case 'offsetHours':
                $this->setTimezone(static::safeCreateDateTimeZone($value));

                break;

            case 'timezone':
            case 'tz':
                $this->setTimezone($value);

                break;

            default:
                if (preg_match('/^([a-z]{2,})Of([A-Z][a-z]+)$/', $name, $match)) {
                    [, $firstUnit, $secondUnit] = $match;

                    try {
                        $start = $this->avoidMutation()->startOf($secondUnit);
                        $currentValue = (\in_array($firstUnit, [
                            // Unit with indexes starting at 1 (other units start at 0)
                            'day',
                            'week',
                            'month',
                            'quarter',
                        ], true) ? 1 : 0) + (int) floor($start->diffInUnit($firstUnit, $this));

                        // We check $value a posteriori to give precedence to UnknownUnitException
                        if (!\is_int($value)) {
                            throw new UnitException("->$name expects integer value");
                        }

                        $this->addUnit($firstUnit, $value - $currentValue);

                        break;
                    } catch (UnknownUnitException) {
                        // default to macro
                    }
                }

                $macro = $this->getLocalMacro('set'.ucfirst($name));

                if ($macro) {
                    $this->executeCallableWithContext($macro, $value);

                    break;
                }

                if ($this->isLocalStrictModeEnabled()) {
                    throw new UnknownSetterException($name);
                }

                $this->$name = $value;
        }

        return $this;
    }

    /**
     * Get the translation of the current week day name (with context for languages with multiple forms).
     *
     * @param string|null $context      whole format string
     * @param string      $keySuffix    "", "_short" or "_min"
     * @param string|null $defaultValue default value if translation missing
     */
    public function getTranslatedDayName(
        ?string $context = null,
        string $keySuffix = '',
        ?string $defaultValue = null,
    ): string {
        return $this->getTranslatedFormByRegExp('weekdays', $keySuffix, $context, $this->dayOfWeek, $defaultValue ?: $this->englishDayOfWeek);
    }

    /**
     * Get the translation of the current short week day name (with context for languages with multiple forms).
     *
     * @param string|null $context whole format string
     */
    public function getTranslatedShortDayName(?string $context = null): string
    {
        return $this->getTranslatedDayName($context, '_short', $this->shortEnglishDayOfWeek);
    }

    /**
     * Get the translation of the current abbreviated week day name (with context for languages with multiple forms).
     *
     * @param string|null $context whole format string
     */
    public function getTranslatedMinDayName(?string $context = null): string
    {
        return $this->getTranslatedDayName($context, '_min', $this->shortEnglishDayOfWeek);
    }

    /**
     * Get the translation of the current month day name (with context for languages with multiple forms).
     *
     * @param string|null $context      whole format string
     * @param string      $keySuffix    "" or "_short"
     * @param string|null $defaultValue default value if translation missing
     */
    public function getTranslatedMonthName(
        ?string $context = null,
        string $keySuffix = '',
        ?string $defaultValue = null,
    ): string {
        return $this->getTranslatedFormByRegExp('months', $keySuffix, $context, $this->month - 1, $defaultValue ?: $this->englishMonth);
    }

    /**
     * Get the translation of the current short month day name (with context for languages with multiple forms).
     *
     * @param string|null $context whole format string
     */
    public function getTranslatedShortMonthName(?string $context = null): string
    {
        return $this->getTranslatedMonthName($context, '_short', $this->shortEnglishMonth);
    }

    /**
     * Get/set the day of year.
     *
     * @template T of int|null
     *
     * @param int|null $value new value for day of year if using as setter.
     *
     * @psalm-param T $value
     *
     * @return static|int
     *
     * @psalm-return (T is int ? static : int)
     */
    public function dayOfYear(?int $value = null): static|int
    {
        $dayOfYear = $this->dayOfYear;

        return $value === null ? $dayOfYear : $this->addDays($value - $dayOfYear);
    }

    /**
     * Get/set the weekday from 0 (Sunday) to 6 (Saturday).
     *
     * @param WeekDay|int|null $value new value for weekday if using as setter.
     */
    public function weekday(WeekDay|int|null $value = null): static|int
    {
        if ($value === null) {
            return $this->dayOfWeek;
        }

        $firstDay = (int) ($this->getTranslationMessage('first_day_of_week') ?? 0);
        $dayOfWeek = ($this->dayOfWeek + 7 - $firstDay) % 7;

        return $this->addDays(((WeekDay::int($value) + 7 - $firstDay) % 7) - $dayOfWeek);
    }

    /**
     * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday).
     *
     * @param WeekDay|int|null $value new value for weekday if using as setter.
     */
    public function isoWeekday(WeekDay|int|null $value = null): static|int
    {
        $dayOfWeekIso = $this->dayOfWeekIso;

        return $value === null ? $dayOfWeekIso : $this->addDays(WeekDay::int($value) - $dayOfWeekIso);
    }

    /**
     * Return the number of days since the start of the week (using the current locale or the first parameter
     * if explicitly given).
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week,
     *                                       if not provided, start of week is inferred from the locale
     *                                       (Sunday for en_US, Monday for de_DE, etc.)
     */
    public function getDaysFromStartOfWeek(WeekDay|int|null $weekStartsAt = null): int
    {
        $firstDay = (int) (WeekDay::int($weekStartsAt) ?? $this->getTranslationMessage('first_day_of_week') ?? 0);

        return ($this->dayOfWeek + 7 - $firstDay) % 7;
    }

    /**
     * Set the day (keeping the current time) to the start of the week + the number of days passed as the first
     * parameter. First day of week is driven by the locale unless explicitly set with the second parameter.
     *
     * @param int              $numberOfDays number of days to add after the start of the current week
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week,
     *                                       if not provided, start of week is inferred from the locale
     *                                       (Sunday for en_US, Monday for de_DE, etc.)
     */
    public function setDaysFromStartOfWeek(int $numberOfDays, WeekDay|int|null $weekStartsAt = null): static
    {
        return $this->addDays($numberOfDays - $this->getDaysFromStartOfWeek(WeekDay::int($weekStartsAt)));
    }

    /**
     * Set any unit to a new value without overflowing current other unit given.
     *
     * @param string $valueUnit    unit name to modify
     * @param int    $value        new value for the input unit
     * @param string $overflowUnit unit name to not overflow
     */
    public function setUnitNoOverflow(string $valueUnit, int $value, string $overflowUnit): static
    {
        try {
            $start = $this->avoidMutation()->startOf($overflowUnit);
            $end = $this->avoidMutation()->endOf($overflowUnit);
            /** @var static $date */
            $date = $this->$valueUnit($value);

            if ($date < $start) {
                return $date->mutateIfMutable($start);
            }

            if ($date > $end) {
                return $date->mutateIfMutable($end);
            }

            return $date;
        } catch (BadMethodCallException | ReflectionException $exception) {
            throw new UnknownUnitException($valueUnit, 0, $exception);
        }
    }

    /**
     * Add any unit to a new value without overflowing current other unit given.
     *
     * @param string $valueUnit    unit name to modify
     * @param int    $value        amount to add to the input unit
     * @param string $overflowUnit unit name to not overflow
     */
    public function addUnitNoOverflow(string $valueUnit, int $value, string $overflowUnit): static
    {
        return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit + $value, $overflowUnit);
    }

    /**
     * Subtract any unit to a new value without overflowing current other unit given.
     *
     * @param string $valueUnit    unit name to modify
     * @param int    $value        amount to subtract to the input unit
     * @param string $overflowUnit unit name to not overflow
     */
    public function subUnitNoOverflow(string $valueUnit, int $value, string $overflowUnit): static
    {
        return $this->setUnitNoOverflow($valueUnit, $this->$valueUnit - $value, $overflowUnit);
    }

    /**
     * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed.
     */
    public function utcOffset(?int $minuteOffset = null): static|int
    {
        if ($minuteOffset === null) {
            return $this->offsetMinutes;
        }

        return $this->setTimezone(CarbonTimeZone::createFromMinuteOffset($minuteOffset));
    }

    /**
     * Set the date with gregorian year, month and day numbers.
     *
     * @see https://php.net/manual/en/datetime.setdate.php
     */
    public function setDate(int $year, int $month, int $day): static
    {
        return parent::setDate($year, $month, $day);
    }

    /**
     * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates.
     *
     * @see https://php.net/manual/en/datetime.setisodate.php
     */
    public function setISODate(int $year, int $week, int $day = 1): static
    {
        return parent::setISODate($year, $week, $day);
    }

    /**
     * Set the date and time all together.
     */
    public function setDateTime(
        int $year,
        int $month,
        int $day,
        int $hour,
        int $minute,
        int $second = 0,
        int $microseconds = 0,
    ): static {
        return $this->setDate($year, $month, $day)->setTime($hour, $minute, $second, $microseconds);
    }

    /**
     * Resets the current time of the DateTime object to a different time.
     *
     * @see https://php.net/manual/en/datetime.settime.php
     */
    public function setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0): static
    {
        return parent::setTime($hour, $minute, $second, $microseconds);
    }

    /**
     * Set the instance's timestamp.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public function setTimestamp(float|int|string $timestamp): static
    {
        [$seconds, $microseconds] = self::getIntegerAndDecimalParts($timestamp);

        return parent::setTimestamp((int) $seconds)->setMicroseconds((int) $microseconds);
    }

    /**
     * Set the time by time string.
     */
    public function setTimeFromTimeString(string $time): static
    {
        if (!str_contains($time, ':')) {
            $time .= ':0';
        }

        return $this->modify($time);
    }

    /**
     * @alias setTimezone
     */
    public function timezone(DateTimeZone|string|int $value): static
    {
        return $this->setTimezone($value);
    }

    /**
     * Set the timezone or returns the timezone name if no arguments passed.
     *
     * @return ($value is null ? string : static)
     */
    public function tz(DateTimeZone|string|int|null $value = null): static|string
    {
        if ($value === null) {
            return $this->tzName;
        }

        return $this->setTimezone($value);
    }

    /**
     * Set the instance's timezone from a string or object.
     */
    public function setTimezone(DateTimeZone|string|int $timeZone): static
    {
        return parent::setTimezone(static::safeCreateDateTimeZone($timeZone));
    }

    /**
     * Set the instance's timezone from a string or object and add/subtract the offset difference.
     */
    public function shiftTimezone(DateTimeZone|string $value): static
    {
        $dateTimeString = $this->format('Y-m-d H:i:s.u');

        return $this
            ->setTimezone($value)
            ->modify($dateTimeString);
    }

    /**
     * Set the instance's timezone to UTC.
     */
    public function utc(): static
    {
        return $this->setTimezone('UTC');
    }

    /**
     * Set the year, month, and date for this instance to that of the passed instance.
     */
    public function setDateFrom(DateTimeInterface|string $date): static
    {
        $date = $this->resolveCarbon($date);

        return $this->setDate($date->year, $date->month, $date->day);
    }

    /**
     * Set the hour, minute, second and microseconds for this instance to that of the passed instance.
     */
    public function setTimeFrom(DateTimeInterface|string $date): static
    {
        $date = $this->resolveCarbon($date);

        return $this->setTime($date->hour, $date->minute, $date->second, $date->microsecond);
    }

    /**
     * Set the date and time for this instance to that of the passed instance.
     */
    public function setDateTimeFrom(DateTimeInterface|string $date): static
    {
        $date = $this->resolveCarbon($date);

        return $this->modify($date->rawFormat('Y-m-d H:i:s.u'));
    }

    /**
     * Get the days of the week.
     */
    public static function getDays(): array
    {
        return static::$days;
    }

    ///////////////////////////////////////////////////////////////////
    /////////////////////// WEEK SPECIAL DAYS /////////////////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Get the first day of week.
     *
     * @return int
     */
    public static function getWeekStartsAt(?string $locale = null): int
    {
        return (int) static::getTranslationMessageWith(
            $locale ? Translator::get($locale) : static::getTranslator(),
            'first_day_of_week',
        );
    }

    /**
     * Get the last day of week.
     *
     * @param string $locale local to consider the last day of week.
     *
     * @return int
     */
    public static function getWeekEndsAt(?string $locale = null): int
    {
        return static::weekRotate(static::getWeekStartsAt($locale), -1);
    }

    /**
     * Get weekend days
     */
    public static function getWeekendDays(): array
    {
        return FactoryImmutable::getInstance()->getWeekendDays();
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather consider week-end is always saturday and sunday, and if you have some custom
     *             week-end days to handle, give to those days an other name and create a macro for them:
     *
     *             ```
     *             Carbon::macro('isDayOff', function ($date) {
     *                 return $date->isSunday() || $date->isMonday();
     *             });
     *             Carbon::macro('isNotDayOff', function ($date) {
     *                 return !$date->isDayOff();
     *             });
     *             if ($someDate->isDayOff()) ...
     *             if ($someDate->isNotDayOff()) ...
     *             // Add 5 not-off days
     *             $count = 5;
     *             while ($someDate->isDayOff() || ($count-- > 0)) {
     *                 $someDate->addDay();
     *             }
     *             ```
     *
     * Set weekend days
     */
    public static function setWeekendDays(array $days): void
    {
        FactoryImmutable::getDefaultInstance()->setWeekendDays($days);
    }

    /**
     * Determine if a time string will produce a relative date.
     *
     * @return bool true if time match a relative date, false if absolute or invalid time string
     */
    public static function hasRelativeKeywords(?string $time): bool
    {
        if (!$time || strtotime($time) === false) {
            return false;
        }

        $date1 = new DateTime('2000-01-01T00:00:00Z');
        $date1->modify($time);
        $date2 = new DateTime('2001-12-25T00:00:00Z');
        $date2->modify($time);

        return $date1 != $date2;
    }

    ///////////////////////////////////////////////////////////////////
    /////////////////////// STRING FORMATTING /////////////////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Returns list of locale formats for ISO formatting.
     *
     * @param string|null $locale current locale used if null
     */
    public function getIsoFormats(?string $locale = null): array
    {
        return [
            'LT' => $this->getTranslationMessage('formats.LT', $locale),
            'LTS' => $this->getTranslationMessage('formats.LTS', $locale),
            'L' => $this->getTranslationMessage('formats.L', $locale),
            'LL' => $this->getTranslationMessage('formats.LL', $locale),
            'LLL' => $this->getTranslationMessage('formats.LLL', $locale),
            'LLLL' => $this->getTranslationMessage('formats.LLLL', $locale),
            'l' => $this->getTranslationMessage('formats.l', $locale),
            'll' => $this->getTranslationMessage('formats.ll', $locale),
            'lll' => $this->getTranslationMessage('formats.lll', $locale),
            'llll' => $this->getTranslationMessage('formats.llll', $locale),
        ];
    }

    /**
     * Returns list of calendar formats for ISO formatting.
     *
     * @param string|null $locale current locale used if null
     */
    public function getCalendarFormats(?string $locale = null): array
    {
        return [
            'sameDay' => $this->getTranslationMessage('calendar.sameDay', $locale, '[Today at] LT'),
            'nextDay' => $this->getTranslationMessage('calendar.nextDay', $locale, '[Tomorrow at] LT'),
            'nextWeek' => $this->getTranslationMessage('calendar.nextWeek', $locale, 'dddd [at] LT'),
            'lastDay' => $this->getTranslationMessage('calendar.lastDay', $locale, '[Yesterday at] LT'),
            'lastWeek' => $this->getTranslationMessage('calendar.lastWeek', $locale, '[Last] dddd [at] LT'),
            'sameElse' => $this->getTranslationMessage('calendar.sameElse', $locale, 'L'),
        ];
    }

    /**
     * Returns list of locale units for ISO formatting.
     */
    public static function getIsoUnits(): array
    {
        static $units = null;

        $units ??= [
            'OD' => ['getAltNumber', ['day']],
            'OM' => ['getAltNumber', ['month']],
            'OY' => ['getAltNumber', ['year']],
            'OH' => ['getAltNumber', ['hour']],
            'Oh' => ['getAltNumber', ['h']],
            'Om' => ['getAltNumber', ['minute']],
            'Os' => ['getAltNumber', ['second']],
            'D' => 'day',
            'DD' => ['rawFormat', ['d']],
            'Do' => ['ordinal', ['day', 'D']],
            'd' => 'dayOfWeek',
            'dd' => static fn (CarbonInterface $date, $originalFormat = null) => $date->getTranslatedMinDayName(
                $originalFormat,
            ),
            'ddd' => static fn (CarbonInterface $date, $originalFormat = null) => $date->getTranslatedShortDayName(
                $originalFormat,
            ),
            'dddd' => static fn (CarbonInterface $date, $originalFormat = null) => $date->getTranslatedDayName(
                $originalFormat,
            ),
            'DDD' => 'dayOfYear',
            'DDDD' => ['getPaddedUnit', ['dayOfYear', 3]],
            'DDDo' => ['ordinal', ['dayOfYear', 'DDD']],
            'e' => ['weekday', []],
            'E' => 'dayOfWeekIso',
            'H' => ['rawFormat', ['G']],
            'HH' => ['rawFormat', ['H']],
            'h' => ['rawFormat', ['g']],
            'hh' => ['rawFormat', ['h']],
            'k' => 'noZeroHour',
            'kk' => ['getPaddedUnit', ['noZeroHour']],
            'hmm' => ['rawFormat', ['gi']],
            'hmmss' => ['rawFormat', ['gis']],
            'Hmm' => ['rawFormat', ['Gi']],
            'Hmmss' => ['rawFormat', ['Gis']],
            'm' => 'minute',
            'mm' => ['rawFormat', ['i']],
            'a' => 'meridiem',
            'A' => 'upperMeridiem',
            's' => 'second',
            'ss' => ['getPaddedUnit', ['second']],
            'S' => static fn (CarbonInterface $date) => (string) floor($date->micro / 100000),
            'SS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro / 10000, 2),
            'SSS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro / 1000, 3),
            'SSSS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro / 100, 4),
            'SSSSS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro / 10, 5),
            'SSSSSS' => ['getPaddedUnit', ['micro', 6]],
            'SSSSSSS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro * 10, 7),
            'SSSSSSSS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro * 100, 8),
            'SSSSSSSSS' => static fn (CarbonInterface $date) => self::floorZeroPad($date->micro * 1000, 9),
            'M' => 'month',
            'MM' => ['rawFormat', ['m']],
            'MMM' => static function (CarbonInterface $date, $originalFormat = null) {
                $month = $date->getTranslatedShortMonthName($originalFormat);
                $suffix = $date->getTranslationMessage('mmm_suffix');
                if ($suffix && $month !== $date->monthName) {
                    $month .= $suffix;
                }

                return $month;
            },
            'MMMM' => static fn (CarbonInterface $date, $originalFormat = null) => $date->getTranslatedMonthName(
                $originalFormat,
            ),
            'Mo' => ['ordinal', ['month', 'M']],
            'Q' => 'quarter',
            'Qo' => ['ordinal', ['quarter', 'M']],
            'G' => 'isoWeekYear',
            'GG' => ['getPaddedUnit', ['isoWeekYear']],
            'GGG' => ['getPaddedUnit', ['isoWeekYear', 3]],
            'GGGG' => ['getPaddedUnit', ['isoWeekYear', 4]],
            'GGGGG' => ['getPaddedUnit', ['isoWeekYear', 5]],
            'g' => 'weekYear',
            'gg' => ['getPaddedUnit', ['weekYear']],
            'ggg' => ['getPaddedUnit', ['weekYear', 3]],
            'gggg' => ['getPaddedUnit', ['weekYear', 4]],
            'ggggg' => ['getPaddedUnit', ['weekYear', 5]],
            'W' => 'isoWeek',
            'WW' => ['getPaddedUnit', ['isoWeek']],
            'Wo' => ['ordinal', ['isoWeek', 'W']],
            'w' => 'week',
            'ww' => ['getPaddedUnit', ['week']],
            'wo' => ['ordinal', ['week', 'w']],
            'x' => ['valueOf', []],
            'X' => 'timestamp',
            'Y' => 'year',
            'YY' => ['rawFormat', ['y']],
            'YYYY' => ['getPaddedUnit', ['year', 4]],
            'YYYYY' => ['getPaddedUnit', ['year', 5]],
            'YYYYYY' => static fn (CarbonInterface $date) => ($date->year < 0 ? '' : '+').
                $date->getPaddedUnit('year', 6),
            'z' => ['rawFormat', ['T']],
            'zz' => 'tzName',
            'Z' => ['getOffsetString', []],
            'ZZ' => ['getOffsetString', ['']],
        ];

        return $units;
    }

    /**
     * Returns a unit of the instance padded with 0 by default or any other string if specified.
     *
     * @param string $unit      Carbon unit name
     * @param int    $length    Length of the output (2 by default)
     * @param string $padString String to use for padding ("0" by default)
     * @param int    $padType   Side(s) to pad (STR_PAD_LEFT by default)
     */
    public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = STR_PAD_LEFT): string
    {
        return ($this->$unit < 0 ? '-' : '').str_pad((string) abs($this->$unit), $length, $padString, $padType);
    }

    /**
     * Return a property with its ordinal.
     */
    public function ordinal(string $key, ?string $period = null): string
    {
        $number = $this->$key;
        $result = $this->translate('ordinal', [
            ':number' => $number,
            ':period' => (string) $period,
        ]);

        return (string) ($result === 'ordinal' ? $number : $result);
    }

    /**
     * Return the meridiem of the current time in the current locale.
     *
     * @param bool $isLower if true, returns lowercase variant if available in the current locale.
     */
    public function meridiem(bool $isLower = false): string
    {
        $hour = $this->hour;
        $index = $hour < static::HOURS_PER_DAY / 2 ? 0 : 1;

        if ($isLower) {
            $key = 'meridiem.'.($index + 2);
            $result = $this->translate($key);

            if ($result !== $key) {
                return $result;
            }
        }

        $key = "meridiem.$index";
        $result = $this->translate($key);
        if ($result === $key) {
            $result = $this->translate('meridiem', [
                ':hour' => $this->hour,
                ':minute' => $this->minute,
                ':isLower' => $isLower,
            ]);

            if ($result === 'meridiem') {
                return $isLower ? $this->latinMeridiem : $this->latinUpperMeridiem;
            }
        } elseif ($isLower) {
            $result = mb_strtolower($result);
        }

        return $result;
    }

    /**
     * Returns the alternative number for a given date property if available in the current locale.
     *
     * @param string $key date property
     */
    public function getAltNumber(string $key): string
    {
        return $this->translateNumber((int) (\strlen($key) > 1 ? $this->$key : $this->rawFormat($key)));
    }

    /**
     * Format in the current language using ISO replacement patterns.
     *
     * @param string|null $originalFormat provide context if a chunk has been passed alone
     */
    public function isoFormat(string $format, ?string $originalFormat = null): string
    {
        $result = '';
        $length = mb_strlen($format);
        $originalFormat ??= $format;
        $inEscaped = false;
        $formats = null;
        $units = null;

        for ($i = 0; $i < $length; $i++) {
            $char = mb_substr($format, $i, 1);

            if ($char === '\\') {
                $result .= mb_substr($format, ++$i, 1);

                continue;
            }

            if ($char === '[' && !$inEscaped) {
                $inEscaped = true;

                continue;
            }

            if ($char === ']' && $inEscaped) {
                $inEscaped = false;

                continue;
            }

            if ($inEscaped) {
                $result .= $char;

                continue;
            }

            $input = mb_substr($format, $i);

            if (preg_match('/^(LTS|LT|l{1,4}|L{1,4})/', $input, $match)) {
                if ($formats === null) {
                    $formats = $this->getIsoFormats();
                }

                $code = $match[0];
                $sequence = $formats[$code] ?? preg_replace_callback(
                    '/MMMM|MM|DD|dddd/',
                    static fn ($code) => mb_substr($code[0], 1),
                    $formats[strtoupper($code)] ?? '',
                );
                $rest = mb_substr($format, $i + mb_strlen($code));
                $format = mb_substr($format, 0, $i).$sequence.$rest;
                $length = mb_strlen($format);
                $input = $sequence.$rest;
            }

            if (preg_match('/^'.CarbonInterface::ISO_FORMAT_REGEXP.'/', $input, $match)) {
                $code = $match[0];

                if ($units === null) {
                    $units = static::getIsoUnits();
                }

                $sequence = $units[$code] ?? '';

                if ($sequence instanceof Closure) {
                    $sequence = $sequence($this, $originalFormat);
                } elseif (\is_array($sequence)) {
                    try {
                        $sequence = $this->{$sequence[0]}(...$sequence[1]);
                    } catch (ReflectionException | InvalidArgumentException | BadMethodCallException) {
                        $sequence = '';
                    }
                } elseif (\is_string($sequence)) {
                    $sequence = $this->$sequence ?? $code;
                }

                $format = mb_substr($format, 0, $i).$sequence.mb_substr($format, $i + mb_strlen($code));
                $i += mb_strlen((string) $sequence) - 1;
                $length = mb_strlen($format);
                $char = $sequence;
            }

            $result .= $char;
        }

        return $result;
    }

    /**
     * List of replacements from date() format to isoFormat().
     */
    public static function getFormatsToIsoReplacements(): array
    {
        static $replacements = null;

        $replacements ??= [
            'd' => true,
            'D' => 'ddd',
            'j' => true,
            'l' => 'dddd',
            'N' => true,
            'S' => static fn ($date) => str_replace((string) $date->rawFormat('j'), '', $date->isoFormat('Do')),
            'w' => true,
            'z' => true,
            'W' => true,
            'F' => 'MMMM',
            'm' => true,
            'M' => 'MMM',
            'n' => true,
            't' => true,
            'L' => true,
            'o' => true,
            'Y' => true,
            'y' => true,
            'a' => 'a',
            'A' => 'A',
            'B' => true,
            'g' => true,
            'G' => true,
            'h' => true,
            'H' => true,
            'i' => true,
            's' => true,
            'u' => true,
            'v' => true,
            'E' => true,
            'I' => true,
            'O' => true,
            'P' => true,
            'Z' => true,
            'c' => true,
            'r' => true,
            'U' => true,
            'T' => true,
        ];

        return $replacements;
    }

    /**
     * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
     * but translate words whenever possible (months, day names, etc.) using the current locale.
     */
    public function translatedFormat(string $format): string
    {
        $replacements = static::getFormatsToIsoReplacements();
        $context = '';
        $isoFormat = '';
        $length = mb_strlen($format);

        for ($i = 0; $i < $length; $i++) {
            $char = mb_substr($format, $i, 1);

            if ($char === '\\') {
                $replacement = mb_substr($format, $i, 2);
                $isoFormat .= $replacement;
                $i++;

                continue;
            }

            if (!isset($replacements[$char])) {
                $replacement = preg_match('/^[A-Za-z]$/', $char) ? "\\$char" : $char;
                $isoFormat .= $replacement;
                $context .= $replacement;

                continue;
            }

            $replacement = $replacements[$char];

            if ($replacement === true) {
                static $contextReplacements = null;

                if ($contextReplacements === null) {
                    $contextReplacements = [
                        'm' => 'MM',
                        'd' => 'DD',
                        't' => 'D',
                        'j' => 'D',
                        'N' => 'e',
                        'w' => 'e',
                        'n' => 'M',
                        'o' => 'YYYY',
                        'Y' => 'YYYY',
                        'y' => 'YY',
                        'g' => 'h',
                        'G' => 'H',
                        'h' => 'hh',
                        'H' => 'HH',
                        'i' => 'mm',
                        's' => 'ss',
                    ];
                }

                $isoFormat .= '['.$this->rawFormat($char).']';
                $context .= $contextReplacements[$char] ?? ' ';

                continue;
            }

            if ($replacement instanceof Closure) {
                $replacement = '['.$replacement($this).']';
                $isoFormat .= $replacement;
                $context .= $replacement;

                continue;
            }

            $isoFormat .= $replacement;
            $context .= $replacement;
        }

        return $this->isoFormat($isoFormat, $context);
    }

    /**
     * Returns the offset hour and minute formatted with +/- and a given separator (":" by default).
     * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first
     * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something
     * like "-12:00".
     *
     * @param string $separator string to place between hours and minutes (":" by default)
     */
    public function getOffsetString(string $separator = ':'): string
    {
        $second = $this->getOffset();
        $symbol = $second < 0 ? '-' : '+';
        $minute = abs($second) / static::SECONDS_PER_MINUTE;
        $hour = self::floorZeroPad($minute / static::MINUTES_PER_HOUR, 2);
        $minute = self::floorZeroPad(((int) $minute) % static::MINUTES_PER_HOUR, 2);

        return "$symbol$hour$separator$minute";
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param string $method     magic method name called
     * @param array  $parameters parameters list
     *
     * @throws BadMethodCallException
     */
    public static function __callStatic(string $method, array $parameters): mixed
    {
        if (!static::hasMacro($method)) {
            foreach (static::getGenericMacros() as $callback) {
                try {
                    return static::executeStaticCallable($callback, $method, ...$parameters);
                } catch (BadMethodCallException) {
                    continue;
                }
            }

            if (static::isStrictModeEnabled()) {
                throw new UnknownMethodException(\sprintf('%s::%s', static::class, $method));
            }

            return null;
        }

        return static::executeStaticCallable(static::getMacro($method), ...$parameters);
    }

    /**
     * Set specified unit to new given value.
     *
     * @param string    $unit  year, month, day, hour, minute, second or microsecond
     * @param Month|int $value new value for given unit
     */
    public function setUnit(string $unit, Month|int|float|null $value = null): static
    {
        if (\is_float($value)) {
            $int = (int) $value;

            if ((float) $int !== $value) {
                throw new InvalidArgumentException(
                    "$unit cannot be changed to float value $value, integer expected",
                );
            }

            $value = $int;
        }

        $unit = static::singularUnit($unit);
        $value = self::monthToInt($value, $unit);
        $dateUnits = ['year', 'month', 'day'];

        if (\in_array($unit, $dateUnits)) {
            return $this->setDate(...array_map(
                fn ($name) => (int) ($name === $unit ? $value : $this->$name),
                $dateUnits,
            ));
        }

        $units = ['hour', 'minute', 'second', 'micro'];

        if ($unit === 'millisecond' || $unit === 'milli') {
            $value *= 1000;
            $unit = 'micro';
        } elseif ($unit === 'microsecond') {
            $unit = 'micro';
        }

        return $this->setTime(...array_map(
            fn ($name) => (int) ($name === $unit ? $value : $this->$name),
            $units,
        ));
    }

    /**
     * Returns standardized singular of a given singular/plural unit name (in English).
     */
    public static function singularUnit(string $unit): string
    {
        $unit = rtrim(mb_strtolower($unit), 's');

        return match ($unit) {
            'centurie' => 'century',
            'millennia' => 'millennium',
            default => $unit,
        };
    }

    /**
     * Returns standardized plural of a given singular/plural unit name (in English).
     */
    public static function pluralUnit(string $unit): string
    {
        $unit = rtrim(strtolower($unit), 's');

        return match ($unit) {
            'century' => 'centuries',
            'millennium', 'millennia' => 'millennia',
            default => "{$unit}s",
        };
    }

    public static function sleep(int|float $seconds): void
    {
        if (static::hasTestNow()) {
            static::setTestNow(static::getTestNow()->avoidMutation()->addSeconds($seconds));

            return;
        }

        (new NativeClock('UTC'))->sleep($seconds);
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param string $method     magic method name called
     * @param array  $parameters parameters list
     *
     * @throws UnknownMethodException|BadMethodCallException|ReflectionException|Throwable
     */
    public function __call(string $method, array $parameters): mixed
    {
        $unit = rtrim($method, 's');

        return $this->callDiffAlias($unit, $parameters)
            ?? $this->callHumanDiffAlias($unit, $parameters)
            ?? $this->callRoundMethod($unit, $parameters)
            ?? $this->callIsMethod($unit, $parameters)
            ?? $this->callModifierMethod($unit, $parameters)
            ?? $this->callPeriodMethod($method, $parameters)
            ?? $this->callGetOrSetMethod($method, $parameters)
            ?? $this->callMacroMethod($method, $parameters);
    }

    /**
     * Return the Carbon instance passed through, a now instance in the same timezone
     * if null given or parse the input if string given.
     */
    protected function resolveCarbon(DateTimeInterface|string|null $date): self
    {
        if (!$date) {
            return $this->nowWithSameTz();
        }

        if (\is_string($date)) {
            return $this->transmitFactory(fn () => static::parse($date, $this->getTimezone()));
        }

        return $date instanceof self ? $date : $this->transmitFactory(static fn () => static::instance($date));
    }

    protected static function weekRotate(int $day, int $rotation): int
    {
        return (static::DAYS_PER_WEEK + $rotation % static::DAYS_PER_WEEK + $day) % static::DAYS_PER_WEEK;
    }

    protected function executeCallable(callable $macro, ...$parameters)
    {
        if ($macro instanceof Closure) {
            $boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);

            return \call_user_func_array($boundMacro ?: $macro, $parameters);
        }

        return \call_user_func_array($macro, $parameters);
    }

    protected function executeCallableWithContext(callable $macro, ...$parameters)
    {
        return static::bindMacroContext($this, function () use (&$macro, &$parameters) {
            return $this->executeCallable($macro, ...$parameters);
        });
    }

    protected function getAllGenericMacros(): Generator
    {
        yield from $this->localGenericMacros ?? [];
        yield from $this->transmitFactory(static fn () => static::getGenericMacros());
    }

    protected static function getGenericMacros(): Generator
    {
        foreach ((FactoryImmutable::getInstance()->getSettings()['genericMacros'] ?? []) as $list) {
            foreach ($list as $macro) {
                yield $macro;
            }
        }
    }

    protected static function executeStaticCallable(callable $macro, ...$parameters)
    {
        return static::bindMacroContext(null, function () use (&$macro, &$parameters) {
            if ($macro instanceof Closure) {
                $boundMacro = @Closure::bind($macro, null, static::class);

                return \call_user_func_array($boundMacro ?: $macro, $parameters);
            }

            return \call_user_func_array($macro, $parameters);
        });
    }

    protected function getTranslatedFormByRegExp($baseKey, $keySuffix, $context, $subKey, $defaultValue)
    {
        $key = $baseKey.$keySuffix;
        $standaloneKey = $key.'_standalone';
        $baseTranslation = $this->getTranslationMessage($key);

        if ($baseTranslation instanceof Closure) {
            return $baseTranslation($this, $context, $subKey) ?: $defaultValue;
        }

        if (
            $this->getTranslationMessage("$standaloneKey.$subKey") &&
            (!$context || (($regExp = $this->getTranslationMessage($baseKey.'_regexp')) && !preg_match($regExp, $context)))
        ) {
            $key = $standaloneKey;
        }

        return $this->getTranslationMessage("$key.$subKey", null, $defaultValue);
    }

    private function callGetOrSetMethod(string $method, array $parameters): mixed
    {
        if (preg_match('/^([a-z]{2,})(In|Of)([A-Z][a-z]+)$/', $method)) {
            $localStrictModeEnabled = $this->localStrictModeEnabled;
            $this->localStrictModeEnabled = true;

            try {
                return $this->callGetOrSet($method, $parameters[0] ?? null);
            } catch (UnknownGetterException|UnknownSetterException|ImmutableException) {
                // continue to macro
            } finally {
                $this->localStrictModeEnabled = $localStrictModeEnabled;
            }
        }

        return null;
    }

    private function callGetOrSet(string $name, mixed $value): mixed
    {
        if ($value !== null) {
            if (\is_string($value) || \is_int($value) || \is_float($value) || $value instanceof DateTimeZone || $value instanceof Month) {
                return $this->set($name, $value);
            }

            return null;
        }

        return $this->get($name);
    }

    private function getUTCUnit(string $unit): ?string
    {
        if (str_starts_with($unit, 'Real')) {
            return substr($unit, 4);
        }

        if (str_starts_with($unit, 'UTC')) {
            return substr($unit, 3);
        }

        return null;
    }

    private function callDiffAlias(string $method, array $parameters): mixed
    {
        if (preg_match('/^(diff|floatDiff)In(Real|UTC|Utc)?(.+)$/', $method, $match)) {
            $mode = strtoupper($match[2] ?? '');
            $betterMethod = $match[1] === 'floatDiff' ? str_replace('floatDiff', 'diff', $method) : null;

            if ($mode === 'REAL') {
                $mode = 'UTC';
                $betterMethod = str_replace($match[2], 'UTC', $betterMethod ?? $method);
            }

            if ($betterMethod) {
                @trigger_error(
                    "Use the method $betterMethod instead to make it more explicit about what it does.\n".
                    'On next major version, "float" prefix will be removed (as all diff are now returning floating numbers)'.
                    ' and "Real" methods will be removed in favor of "UTC" because what it actually does is to convert both'.
                    ' dates to UTC timezone before comparison, while by default it does it only if both dates don\'t have'.
                    ' exactly the same timezone (Note: 2 timezones with the same offset but different names are considered'.
                    " different as it's not safe to assume they will always have the same offset).",
                    \E_USER_DEPRECATED,
                );
            }

            $unit = self::pluralUnit($match[3]);
            $diffMethod = 'diffIn'.ucfirst($unit);

            if (\in_array($unit, ['days', 'weeks', 'months', 'quarters', 'years'])) {
                $parameters['utc'] = ($mode === 'UTC');
            }

            if (method_exists($this, $diffMethod)) {
                return $this->$diffMethod(...$parameters);
            }
        }

        return null;
    }

    private function callHumanDiffAlias(string $method, array $parameters): ?string
    {
        $diffSizes = [
            // @mode diffForHumans
            'short' => true,
            // @mode diffForHumans
            'long' => false,
        ];
        $diffSyntaxModes = [
            // @call diffForHumans
            'Absolute' => CarbonInterface::DIFF_ABSOLUTE,
            // @call diffForHumans
            'Relative' => CarbonInterface::DIFF_RELATIVE_AUTO,
            // @call diffForHumans
            'RelativeToNow' => CarbonInterface::DIFF_RELATIVE_TO_NOW,
            // @call diffForHumans
            'RelativeToOther' => CarbonInterface::DIFF_RELATIVE_TO_OTHER,
        ];
        $sizePattern = implode('|', array_keys($diffSizes));
        $syntaxPattern = implode('|', array_keys($diffSyntaxModes));

        if (preg_match("/^(?<size>$sizePattern)(?<syntax>$syntaxPattern)DiffForHuman$/", $method, $match)) {
            $dates = array_filter($parameters, function ($parameter) {
                return $parameter instanceof DateTimeInterface;
            });
            $other = null;

            if (\count($dates)) {
                $key = key($dates);
                $other = current($dates);
                array_splice($parameters, $key, 1);
            }

            return $this->diffForHumans($other, $diffSyntaxModes[$match['syntax']], $diffSizes[$match['size']], ...$parameters);
        }

        return null;
    }

    private function callIsMethod(string $unit, array $parameters): ?bool
    {
        if (!str_starts_with($unit, 'is')) {
            return null;
        }

        $word = substr($unit, 2);

        if (\in_array($word, static::$days, true)) {
            return $this->isDayOfWeek($word);
        }

        return match ($word) {
            // @call is Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
            'Utc', 'UTC' => $this->utc,
            // @call is Check if the current instance has non-UTC timezone.
            'Local' => $this->local,
            // @call is Check if the current instance is a valid date.
            'Valid' => $this->year !== 0,
            // @call is Check if the current instance is in a daylight saving time.
            'DST' => $this->dst,
            default => $this->callComparatorMethod($word, $parameters),
        };
    }

    private function callComparatorMethod(string $unit, array $parameters): ?bool
    {
        $start = substr($unit, 0, 4);
        $factor = -1;

        if ($start === 'Last') {
            $start = 'Next';
            $factor = 1;
        }

        if ($start === 'Next') {
            $lowerUnit = strtolower(substr($unit, 4));

            if (static::isModifiableUnit($lowerUnit)) {
                return $this->avoidMutation()->addUnit($lowerUnit, $factor, false)->isSameUnit($lowerUnit, ...($parameters ?: ['now']));
            }
        }

        if ($start === 'Same') {
            try {
                return $this->isSameUnit(strtolower(substr($unit, 4)), ...$parameters);
            } catch (BadComparisonUnitException) {
                // Try next
            }
        }

        if (str_starts_with($unit, 'Current')) {
            try {
                return $this->isCurrentUnit(strtolower(substr($unit, 7)));
            } catch (BadComparisonUnitException | BadMethodCallException) {
                // Try next
            }
        }

        return null;
    }

    private function callModifierMethod(string $unit, array $parameters): ?static
    {
        $action = substr($unit, 0, 3);
        $overflow = null;

        if ($action === 'set') {
            $unit = strtolower(substr($unit, 3));
        }

        if (\in_array($unit, static::$units, true)) {
            return $this->setUnit($unit, ...$parameters);
        }

        if ($action === 'add' || $action === 'sub') {
            $unit = substr($unit, 3);
            $utcUnit = $this->getUTCUnit($unit);

            if ($utcUnit) {
                $unit = static::singularUnit($utcUnit);

                return $this->{"{$action}UTCUnit"}($unit, ...$parameters);
            }

            if (preg_match('/^(Month|Quarter|Year|Decade|Century|Centurie|Millennium|Millennia)s?(No|With|Without|WithNo)Overflow$/', $unit, $match)) {
                $unit = $match[1];
                $overflow = $match[2] === 'With';
            }

            $unit = static::singularUnit($unit);
        }

        if (static::isModifiableUnit($unit)) {
            return $this->{"{$action}Unit"}($unit, $this->getMagicParameter($parameters, 0, 'value', 1), $overflow);
        }

        return null;
    }

    private function callPeriodMethod(string $method, array $parameters): ?CarbonPeriod
    {
        if (str_ends_with($method, 'Until')) {
            try {
                $unit = static::singularUnit(substr($method, 0, -5));

                return $this->range(
                    $this->getMagicParameter($parameters, 0, 'endDate', $this),
                    $this->getMagicParameter($parameters, 1, 'factor', 1),
                    $unit
                );
            } catch (InvalidArgumentException) {
                // Try macros
            }
        }

        return null;
    }

    private function callMacroMethod(string $method, array $parameters): mixed
    {
        return static::bindMacroContext($this, function () use (&$method, &$parameters) {
            $macro = $this->getLocalMacro($method);

            if (!$macro) {
                foreach ($this->getAllGenericMacros() as $callback) {
                    try {
                        return $this->executeCallable($callback, $method, ...$parameters);
                    } catch (BadMethodCallException) {
                        continue;
                    }
                }

                if ($this->isLocalStrictModeEnabled()) {
                    throw new UnknownMethodException($method);
                }

                return null;
            }

            return $this->executeCallable($macro, ...$parameters);
        });
    }

    private static function floorZeroPad(int|float $value, int $length): string
    {
        return str_pad((string) floor($value), $length, '0', STR_PAD_LEFT);
    }

    /**
     * @template T of CarbonInterface
     *
     * @param T $date
     *
     * @return T
     */
    private function mutateIfMutable(CarbonInterface $date): CarbonInterface
    {
        return $this instanceof DateTimeImmutable
            ? $date
            : $this->modify('@'.$date->rawFormat('U.u'))->setTimezone($date->getTimezone());
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use Carbon\Exceptions\InvalidTimeZoneException;
use Carbon\Exceptions\OutOfRangeException;
use Carbon\Exceptions\UnitException;
use Carbon\Month;
use Carbon\Translator;
use Carbon\WeekDay;
use Closure;
use DateMalformedStringException;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Exception;
use ReturnTypeWillChange;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Trait Creator.
 *
 * Static creators.
 *
 * Depends on the following methods:
 *
 * @method static Carbon|CarbonImmutable getTestNow()
 */
trait Creator
{
    use ObjectInitialisation;
    use LocalFactory;

    /**
     * The errors that can occur.
     */
    protected static array|bool $lastErrors = false;

    /**
     * Create a new Carbon instance.
     *
     * Please see the testing aids section (specifically static::setTestNow())
     * for more on the possibility of this constructor returning a test instance.
     *
     * @throws InvalidFormatException
     */
    public function __construct(
        DateTimeInterface|WeekDay|Month|string|int|float|null $time = null,
        DateTimeZone|string|int|null $timezone = null,
    ) {
        $this->initLocalFactory();

        if ($time instanceof Month) {
            $time = $time->name.' 1';
        } elseif ($time instanceof WeekDay) {
            $time = $time->name;
        } elseif ($time instanceof DateTimeInterface) {
            $time = $this->constructTimezoneFromDateTime($time, $timezone)->format('Y-m-d H:i:s.u');
        }

        if (\is_string($time) && str_starts_with($time, '@')) {
            $time = static::createFromTimestampUTC(substr($time, 1))->format('Y-m-d\TH:i:s.uP');
        } elseif (is_numeric($time) && (!\is_string($time) || !preg_match('/^\d{1,14}$/', $time))) {
            $time = static::createFromTimestampUTC($time)->format('Y-m-d\TH:i:s.uP');
        }

        // If the class has a test now set, and we are trying to create a now()
        // instance then override as required
        $isNow = \in_array($time, [null, '', 'now'], true);
        $timezone = static::safeCreateDateTimeZone($timezone) ?? null;

        if (
            ($this->clock || (
                method_exists(static::class, 'hasTestNow') &&
                method_exists(static::class, 'getTestNow') &&
                static::hasTestNow()
            )) &&
            ($isNow || static::hasRelativeKeywords($time))
        ) {
            $this->mockConstructorParameters($time, $timezone);
        }

        try {
            parent::__construct($time ?? 'now', $timezone);
        } catch (Exception $exception) {
            throw new InvalidFormatException($exception->getMessage(), 0, $exception);
        }

        $this->constructedObjectId = spl_object_hash($this);

        self::setLastErrors(parent::getLastErrors());
    }

    /**
     * Get timezone from a datetime instance.
     */
    private function constructTimezoneFromDateTime(
        DateTimeInterface $date,
        DateTimeZone|string|int|null &$timezone,
    ): DateTimeInterface {
        if ($timezone !== null) {
            $safeTz = static::safeCreateDateTimeZone($timezone);

            if ($safeTz) {
                $date = ($date instanceof DateTimeImmutable ? $date : clone $date)->setTimezone($safeTz);
            }

            return $date;
        }

        $timezone = $date->getTimezone();

        return $date;
    }

    /**
     * Update constructedObjectId on cloned.
     */
    public function __clone(): void
    {
        $this->constructedObjectId = spl_object_hash($this);
    }

    /**
     * Create a Carbon instance from a DateTime one.
     */
    public static function instance(DateTimeInterface $date): static
    {
        if ($date instanceof static) {
            return clone $date;
        }

        $instance = parent::createFromFormat('U.u', $date->format('U.u'))
            ->setTimezone($date->getTimezone());

        if ($date instanceof CarbonInterface) {
            $settings = $date->getSettings();

            if (!$date->hasLocalTranslator()) {
                unset($settings['locale']);
            }

            $instance->settings($settings);
        }

        return $instance;
    }

    /**
     * Create a carbon instance from a string.
     *
     * This is an alias for the constructor that allows better fluent syntax
     * as it allows you to do Carbon::parse('Monday next week')->fn() rather
     * than (new Carbon('Monday next week'))->fn().
     *
     * @throws InvalidFormatException
     */
    public static function rawParse(
        DateTimeInterface|WeekDay|Month|string|int|float|null $time,
        DateTimeZone|string|int|null $timezone = null,
    ): static {
        if ($time instanceof DateTimeInterface) {
            return static::instance($time);
        }

        try {
            return new static($time, $timezone);
        } catch (Exception $exception) {
            // @codeCoverageIgnoreStart
            try {
                $date = @static::now($timezone)->change($time);
            } catch (DateMalformedStringException|InvalidFormatException) {
                $date = null;
            }
            // @codeCoverageIgnoreEnd

            return $date
                ?? throw new InvalidFormatException("Could not parse '$time': ".$exception->getMessage(), 0, $exception);
        }
    }

    /**
     * Create a carbon instance from a string.
     *
     * This is an alias for the constructor that allows better fluent syntax
     * as it allows you to do Carbon::parse('Monday next week')->fn() rather
     * than (new Carbon('Monday next week'))->fn().
     *
     * @throws InvalidFormatException
     */
    public static function parse(
        DateTimeInterface|WeekDay|Month|string|int|float|null $time,
        DateTimeZone|string|int|null $timezone = null,
    ): static {
        $function = static::$parseFunction;

        if (!$function) {
            return static::rawParse($time, $timezone);
        }

        if (\is_string($function) && method_exists(static::class, $function)) {
            $function = [static::class, $function];
        }

        return $function(...\func_get_args());
    }

    /**
     * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
     *
     * @param string                       $time     date/time string in the given language (may also contain English).
     * @param string|null                  $locale   if locale is null or not specified, current global locale will be
     *                                               used instead.
     * @param DateTimeZone|string|int|null $timezone optional timezone for the new instance.
     *
     * @throws InvalidFormatException
     */
    public static function parseFromLocale(
        string $time,
        ?string $locale = null,
        DateTimeZone|string|int|null $timezone = null,
    ): static {
        return static::rawParse(static::translateTimeString($time, $locale, static::DEFAULT_LOCALE), $timezone);
    }

    /**
     * Get a Carbon instance for the current date and time.
     */
    public static function now(DateTimeZone|string|int|null $timezone = null): static
    {
        return new static(null, $timezone);
    }

    /**
     * Create a Carbon instance for today.
     */
    public static function today(DateTimeZone|string|int|null $timezone = null): static
    {
        return static::rawParse('today', $timezone);
    }

    /**
     * Create a Carbon instance for tomorrow.
     */
    public static function tomorrow(DateTimeZone|string|int|null $timezone = null): static
    {
        return static::rawParse('tomorrow', $timezone);
    }

    /**
     * Create a Carbon instance for yesterday.
     */
    public static function yesterday(DateTimeZone|string|int|null $timezone = null): static
    {
        return static::rawParse('yesterday', $timezone);
    }

    private static function assertBetween($unit, $value, $min, $max): void
    {
        if (static::isStrictModeEnabled() && ($value < $min || $value > $max)) {
            throw new OutOfRangeException($unit, $min, $max, $value);
        }
    }

    private static function createNowInstance($timezone)
    {
        if (!static::hasTestNow()) {
            return static::now($timezone);
        }

        $now = static::getTestNow();

        if ($now instanceof Closure) {
            return $now(static::now($timezone));
        }

        $now = $now->avoidMutation();

        return $timezone === null ? $now : $now->setTimezone($timezone);
    }

    /**
     * Create a new Carbon instance from a specific date and time.
     *
     * If any of $year, $month or $day are set to null their now() values will
     * be used.
     *
     * If $hour is null it will be set to its now() value and the default
     * values for $minute and $second will be their now() values.
     *
     * If $hour is not null then the default values for $minute and $second
     * will be 0.
     *
     * @param DateTimeInterface|string|int|null $year
     * @param int|null                          $month
     * @param int|null                          $day
     * @param int|null                          $hour
     * @param int|null                          $minute
     * @param int|null                          $second
     * @param DateTimeZone|string|int|null      $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null): ?static
    {
        $month = self::monthToInt($month);

        if ((\is_string($year) && !is_numeric($year)) || $year instanceof DateTimeInterface) {
            return static::parse($year, $timezone ?? (\is_string($month) || $month instanceof DateTimeZone ? $month : null));
        }

        $defaults = null;
        $getDefault = function ($unit) use ($timezone, &$defaults) {
            if ($defaults === null) {
                $now = self::createNowInstance($timezone);

                $defaults = array_combine([
                    'year',
                    'month',
                    'day',
                    'hour',
                    'minute',
                    'second',
                ], explode('-', $now->rawFormat('Y-n-j-G-i-s.u')));
            }

            return $defaults[$unit];
        };

        $year = $year ?? $getDefault('year');
        $month = $month ?? $getDefault('month');
        $day = $day ?? $getDefault('day');
        $hour = $hour ?? $getDefault('hour');
        $minute = $minute ?? $getDefault('minute');
        $second = (float) ($second ?? $getDefault('second'));

        self::assertBetween('month', $month, 0, 99);
        self::assertBetween('day', $day, 0, 99);
        self::assertBetween('hour', $hour, 0, 99);
        self::assertBetween('minute', $minute, 0, 99);
        self::assertBetween('second', $second, 0, 99);

        $fixYear = null;

        if ($year < 0) {
            $fixYear = $year;
            $year = 0;
        } elseif ($year > 9999) {
            $fixYear = $year - 9999;
            $year = 9999;
        }

        $second = ($second < 10 ? '0' : '').number_format($second, 6);
        $instance = static::rawCreateFromFormat('!Y-n-j G:i:s.u', \sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $timezone);

        if ($instance && $fixYear !== null) {
            $instance = $instance->addYears($fixYear);
        }

        return $instance ?? null;
    }

    /**
     * Create a new safe Carbon instance from a specific date and time.
     *
     * If any of $year, $month or $day are set to null their now() values will
     * be used.
     *
     * If $hour is null it will be set to its now() value and the default
     * values for $minute and $second will be their now() values.
     *
     * If $hour is not null then the default values for $minute and $second
     * will be 0.
     *
     * If one of the set values is not valid, an InvalidDateException
     * will be thrown.
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param int|null                     $hour
     * @param int|null                     $minute
     * @param int|null                     $second
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidDateException
     *
     * @return static|null
     */
    public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null): ?static
    {
        $month = self::monthToInt($month);
        $fields = static::getRangesByUnit();

        foreach ($fields as $field => $range) {
            if ($$field !== null && (!\is_int($$field) || $$field < $range[0] || $$field > $range[1])) {
                if (static::isStrictModeEnabled()) {
                    throw new InvalidDateException($field, $$field);
                }

                return null;
            }
        }

        $instance = static::create($year, $month, $day, $hour, $minute, $second, $timezone);

        foreach (array_reverse($fields) as $field => $range) {
            if ($$field !== null && (!\is_int($$field) || $$field !== $instance->$field)) {
                if (static::isStrictModeEnabled()) {
                    throw new InvalidDateException($field, $$field);
                }

                return null;
            }
        }

        return $instance;
    }

    /**
     * Create a new Carbon instance from a specific date and time using strict validation.
     *
     * @see create()
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param int|null                     $hour
     * @param int|null                     $minute
     * @param int|null                     $second
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null): static
    {
        $initialStrictMode = static::isStrictModeEnabled();
        static::useStrictMode(true);

        try {
            $date = static::create($year, $month, $day, $hour, $minute, $second, $timezone);
        } finally {
            static::useStrictMode($initialStrictMode);
        }

        return $date;
    }

    /**
     * Create a Carbon instance from just a date. The time portion is set to now.
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createFromDate($year = null, $month = null, $day = null, $timezone = null)
    {
        return static::create($year, $month, $day, null, null, null, $timezone);
    }

    /**
     * Create a Carbon instance from just a date. The time portion is set to midnight.
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createMidnightDate($year = null, $month = null, $day = null, $timezone = null)
    {
        return static::create($year, $month, $day, 0, 0, 0, $timezone);
    }

    /**
     * Create a Carbon instance from just a time. The date portion is set to today.
     *
     * @param int|null                     $hour
     * @param int|null                     $minute
     * @param int|null                     $second
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null): static
    {
        return static::create(null, null, null, $hour, $minute, $second, $timezone);
    }

    /**
     * Create a Carbon instance from a time string. The date portion is set to today.
     *
     * @throws InvalidFormatException
     */
    public static function createFromTimeString(string $time, DateTimeZone|string|int|null $timezone = null): static
    {
        return static::today($timezone)->setTimeFromTimeString($time);
    }

    private static function createFromFormatAndTimezone(
        string $format,
        string $time,
        DateTimeZone|string|int|null $originalTimezone,
    ): ?DateTimeInterface {
        if ($originalTimezone === null) {
            return parent::createFromFormat($format, $time) ?: null;
        }

        $timezone = \is_int($originalTimezone) ? self::getOffsetTimezone($originalTimezone) : $originalTimezone;

        $timezone = static::safeCreateDateTimeZone($timezone, $originalTimezone);

        return parent::createFromFormat($format, $time, $timezone) ?: null;
    }

    private static function getOffsetTimezone(int $offset): string
    {
        $minutes = (int) ($offset * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE);

        return @timezone_name_from_abbr('', $minutes, 1) ?: throw new InvalidTimeZoneException(
            "Invalid offset timezone $offset",
        );
    }

    /**
     * Create a Carbon instance from a specific format.
     *
     * @param string                       $format   Datetime format
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function rawCreateFromFormat(string $format, string $time, $timezone = null): ?static
    {
        // Work-around for https://bugs.php.net/bug.php?id=80141
        $format = preg_replace('/(?<!\\\\)((?:\\\\{2})*)c/', '$1Y-m-d\TH:i:sP', $format);

        if (preg_match('/(?<!\\\\)(?:\\\\{2})*(a|A)/', $format, $aMatches, PREG_OFFSET_CAPTURE) &&
            preg_match('/(?<!\\\\)(?:\\\\{2})*(h|g|H|G)/', $format, $hMatches, PREG_OFFSET_CAPTURE) &&
            $aMatches[1][1] < $hMatches[1][1] &&
            preg_match('/(am|pm|AM|PM)/', $time)
        ) {
            $format = preg_replace('/^(.*)(?<!\\\\)((?:\\\\{2})*)(a|A)(.*)$/U', '$1$2$4 $3', $format);
            $time = preg_replace('/^(.*)(am|pm|AM|PM)(.*)$/U', '$1$3 $2', $time);
        }

        if ($timezone === false) {
            $timezone = null;
        }

        // First attempt to create an instance, so that error messages are based on the unmodified format.
        $date = self::createFromFormatAndTimezone($format, $time, $timezone);
        $lastErrors = parent::getLastErrors();
        /** @var \Carbon\CarbonImmutable|\Carbon\Carbon|null $mock */
        $mock = static::getMockedTestNow($timezone);

        if ($mock && $date instanceof DateTimeInterface) {
            // Set timezone from mock if custom timezone was neither given directly nor as a part of format.
            // First let's skip the part that will be ignored by the parser.
            $nonEscaped = '(?<!\\\\)(\\\\{2})*';

            $nonIgnored = preg_replace("/^.*{$nonEscaped}!/s", '', $format);

            if ($timezone === null && !preg_match("/{$nonEscaped}[eOPT]/", $nonIgnored)) {
                $timezone = clone $mock->getTimezone();
            }

            $mock = $mock->copy();

            // Prepend mock datetime only if the format does not contain non escaped unix epoch reset flag.
            if (!preg_match("/{$nonEscaped}[!|]/", $format)) {
                if (preg_match('/[HhGgisvuB]/', $format)) {
                    $mock = $mock->setTime(0, 0);
                }

                $format = static::MOCK_DATETIME_FORMAT.' '.$format;
                $time = ($mock instanceof self ? $mock->rawFormat(static::MOCK_DATETIME_FORMAT) : $mock->format(static::MOCK_DATETIME_FORMAT)).' '.$time;
            }

            // Regenerate date from the modified format to base result on the mocked instance instead of now.
            $date = self::createFromFormatAndTimezone($format, $time, $timezone);
        }

        if ($date instanceof DateTimeInterface) {
            $instance = static::instance($date);
            $instance::setLastErrors($lastErrors);

            return $instance;
        }

        if (static::isStrictModeEnabled()) {
            throw new InvalidFormatException(implode(PHP_EOL, (array) $lastErrors['errors']));
        }

        return null;
    }

    /**
     * Create a Carbon instance from a specific format.
     *
     * @param string                       $format   Datetime format
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    #[ReturnTypeWillChange]
    public static function createFromFormat($format, $time, $timezone = null): ?static
    {
        $function = static::$createFromFormatFunction;

        // format is a single numeric unit
        if (\is_int($time) && \in_array(ltrim($format, '!'), ['U', 'Y', 'y', 'X', 'x', 'm', 'n', 'd', 'j', 'w', 'W', 'H', 'h', 'G', 'g', 'i', 's', 'u', 'z', 'v'], true)) {
            $time = (string) $time;
        }

        if (!\is_string($time)) {
            @trigger_error(
                'createFromFormat() $time parameter will only accept string or integer for 1-letter format representing a numeric unit in the next version',
                \E_USER_DEPRECATED,
            );
            $time = (string) $time;
        }

        if (!$function) {
            return static::rawCreateFromFormat($format, $time, $timezone);
        }

        if (\is_string($function) && method_exists(static::class, $function)) {
            $function = [static::class, $function];
        }

        return $function(...\func_get_args());
    }

    /**
     * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
     *
     * @param string                       $format     Datetime format
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone   optional timezone
     * @param string|null                  $locale     locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use)
     * @param TranslatorInterface|null     $translator optional custom translator to use for macro-formats
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function createFromIsoFormat(
        string $format,
        string $time,
        $timezone = null,
        ?string $locale = CarbonInterface::DEFAULT_LOCALE,
        ?TranslatorInterface $translator = null
    ): ?static {
        $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*(LTS|LT|[Ll]{1,4})/', function ($match) use ($locale, $translator) {
            [$code] = $match;

            static $formats = null;

            if ($formats === null) {
                $translator ??= Translator::get($locale);

                $formats = [
                    'LT' => static::getTranslationMessageWith($translator, 'formats.LT', $locale),
                    'LTS' => static::getTranslationMessageWith($translator, 'formats.LTS', $locale),
                    'L' => static::getTranslationMessageWith($translator, 'formats.L', $locale),
                    'LL' => static::getTranslationMessageWith($translator, 'formats.LL', $locale),
                    'LLL' => static::getTranslationMessageWith($translator, 'formats.LLL', $locale),
                    'LLLL' => static::getTranslationMessageWith($translator, 'formats.LLLL', $locale),
                ];
            }

            return $formats[$code] ?? preg_replace_callback(
                '/MMMM|MM|DD|dddd/',
                static fn (array $code) => mb_substr($code[0], 1),
                $formats[strtoupper($code)] ?? '',
            );
        }, $format);

        $format = preg_replace_callback('/(?<!\\\\)(\\\\{2})*('.CarbonInterface::ISO_FORMAT_REGEXP.'|[A-Za-z])/', function ($match) {
            [$code] = $match;

            static $replacements = null;

            if ($replacements === null) {
                $replacements = [
                    'OD' => 'd',
                    'OM' => 'M',
                    'OY' => 'Y',
                    'OH' => 'G',
                    'Oh' => 'g',
                    'Om' => 'i',
                    'Os' => 's',
                    'D' => 'd',
                    'DD' => 'd',
                    'Do' => 'd',
                    'd' => '!',
                    'dd' => '!',
                    'ddd' => 'D',
                    'dddd' => 'D',
                    'DDD' => 'z',
                    'DDDD' => 'z',
                    'DDDo' => 'z',
                    'e' => '!',
                    'E' => '!',
                    'H' => 'G',
                    'HH' => 'H',
                    'h' => 'g',
                    'hh' => 'h',
                    'k' => 'G',
                    'kk' => 'G',
                    'hmm' => 'gi',
                    'hmmss' => 'gis',
                    'Hmm' => 'Gi',
                    'Hmmss' => 'Gis',
                    'm' => 'i',
                    'mm' => 'i',
                    'a' => 'a',
                    'A' => 'a',
                    's' => 's',
                    'ss' => 's',
                    'S' => '*',
                    'SS' => '*',
                    'SSS' => '*',
                    'SSSS' => '*',
                    'SSSSS' => '*',
                    'SSSSSS' => 'u',
                    'SSSSSSS' => 'u*',
                    'SSSSSSSS' => 'u*',
                    'SSSSSSSSS' => 'u*',
                    'M' => 'm',
                    'MM' => 'm',
                    'MMM' => 'M',
                    'MMMM' => 'M',
                    'Mo' => 'm',
                    'Q' => '!',
                    'Qo' => '!',
                    'G' => '!',
                    'GG' => '!',
                    'GGG' => '!',
                    'GGGG' => '!',
                    'GGGGG' => '!',
                    'g' => '!',
                    'gg' => '!',
                    'ggg' => '!',
                    'gggg' => '!',
                    'ggggg' => '!',
                    'W' => '!',
                    'WW' => '!',
                    'Wo' => '!',
                    'w' => '!',
                    'ww' => '!',
                    'wo' => '!',
                    'x' => 'U???',
                    'X' => 'U',
                    'Y' => 'Y',
                    'YY' => 'y',
                    'YYYY' => 'Y',
                    'YYYYY' => 'Y',
                    'YYYYYY' => 'Y',
                    'z' => 'e',
                    'zz' => 'e',
                    'Z' => 'e',
                    'ZZ' => 'e',
                ];
            }

            $format = $replacements[$code] ?? '?';

            if ($format === '!') {
                throw new InvalidFormatException("Format $code not supported for creation.");
            }

            return $format;
        }, $format);

        return static::rawCreateFromFormat($format, $time, $timezone);
    }

    /**
     * Create a Carbon instance from a specific format and a string in a given language.
     *
     * @param string                       $format   Datetime format
     * @param string                       $locale
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null): ?static
    {
        $format = preg_replace_callback(
            '/(?:\\\\[a-zA-Z]|[bfkqCEJKQRV]){2,}/',
            static function (array $match) use ($locale): string {
                $word = str_replace('\\', '', $match[0]);
                $translatedWord = static::translateTimeString($word, $locale, static::DEFAULT_LOCALE);

                return $word === $translatedWord
                    ? $match[0]
                    : preg_replace('/[a-zA-Z]/', '\\\\$0', $translatedWord);
            },
            $format
        );

        return static::rawCreateFromFormat($format, static::translateTimeString($time, $locale, static::DEFAULT_LOCALE), $timezone);
    }

    /**
     * Create a Carbon instance from a specific ISO format and a string in a given language.
     *
     * @param string                       $format   Datetime ISO format
     * @param string                       $locale
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null): ?static
    {
        $time = static::translateTimeString($time, $locale, static::DEFAULT_LOCALE, CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS | CarbonInterface::TRANSLATE_MERIDIEM);

        return static::createFromIsoFormat($format, $time, $timezone, $locale);
    }

    /**
     * Make a Carbon instance from given variable if possible.
     *
     * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
     * and recurrences). Throw an exception for invalid format, but otherwise return null.
     *
     * @param mixed $var
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function make($var, DateTimeZone|string|null $timezone = null): ?static
    {
        if ($var instanceof DateTimeInterface) {
            return static::instance($var);
        }

        $date = null;

        if (\is_string($var)) {
            $var = trim($var);

            if (!preg_match('/^P[\dT]/', $var) &&
                !preg_match('/^R\d/', $var) &&
                preg_match('/[a-z\d]/i', $var)
            ) {
                $date = static::parse($var, $timezone);
            }
        }

        return $date;
    }

    /**
     * Set last errors.
     *
     * @param array|bool $lastErrors
     *
     * @return void
     */
    private static function setLastErrors($lastErrors): void
    {
        static::$lastErrors = $lastErrors;
    }

    /**
     * {@inheritdoc}
     */
    public static function getLastErrors(): array|false
    {
        return static::$lastErrors;
    }

    private static function monthToInt(mixed $value, string $unit = 'month'): mixed
    {
        if ($value instanceof Month) {
            if ($unit !== 'month') {
                throw new UnitException("Month enum cannot be used to set $unit");
            }

            return Month::int($value);
        }

        return $value;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonConverterInterface;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\Exceptions\InvalidFormatException;
use Carbon\Exceptions\InvalidIntervalException;
use Carbon\Exceptions\UnitException;
use Carbon\Exceptions\UnsupportedUnitException;
use Carbon\Unit;
use Closure;
use DateInterval;
use DateMalformedStringException;
use ReturnTypeWillChange;

/**
 * Trait Units.
 *
 * Add, subtract and set units.
 */
trait Units
{
    /**
     * @deprecated Prefer to use add addUTCUnit() which more accurately defines what it's doing.
     *
     * Add seconds to the instance using timestamp. Positive $value travels
     * forward while negative $value travels into the past.
     *
     * @param string         $unit
     * @param int|float|null $value
     *
     * @return static
     */
    public function addRealUnit(string $unit, $value = 1): static
    {
        return $this->addUTCUnit($unit, $value);
    }

    /**
     * Add seconds to the instance using timestamp. Positive $value travels
     * forward while negative $value travels into the past.
     *
     * @param string         $unit
     * @param int|float|null $value
     *
     * @return static
     */
    public function addUTCUnit(string $unit, $value = 1): static
    {
        $value ??= 0;

        switch ($unit) {
            // @call addUTCUnit
            case 'micro':

            // @call addUTCUnit
            case 'microsecond':
                /* @var CarbonInterface $this */
                $diff = $this->microsecond + $value;
                $time = $this->getTimestamp();
                $seconds = (int) floor($diff / static::MICROSECONDS_PER_SECOND);
                $time += $seconds;
                $diff -= $seconds * static::MICROSECONDS_PER_SECOND;
                $microtime = str_pad((string) $diff, 6, '0', STR_PAD_LEFT);
                $timezone = $this->tz;

                return $this->tz('UTC')->modify("@$time.$microtime")->setTimezone($timezone);

            // @call addUTCUnit
            case 'milli':
            // @call addUTCUnit
            case 'millisecond':
                return $this->addUTCUnit('microsecond', $value * static::MICROSECONDS_PER_MILLISECOND);

            // @call addUTCUnit
            case 'second':
                break;

            // @call addUTCUnit
            case 'minute':
                $value *= static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'hour':
                $value *= static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'day':
                $value *= static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'week':
                $value *= static::DAYS_PER_WEEK * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'month':
                $value *= 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'quarter':
                $value *= static::MONTHS_PER_QUARTER * 30 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'year':
                $value *= 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'decade':
                $value *= static::YEARS_PER_DECADE * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'century':
                $value *= static::YEARS_PER_CENTURY * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            // @call addUTCUnit
            case 'millennium':
                $value *= static::YEARS_PER_MILLENNIUM * 365 * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE;

                break;

            default:
                if ($this->isLocalStrictModeEnabled()) {
                    throw new UnitException("Invalid unit for real timestamp add/sub: '$unit'");
                }

                return $this;
        }

        $seconds = (int) $value;
        $microseconds = (int) round(
            (abs($value) - abs($seconds)) * ($value < 0 ? -1 : 1) * static::MICROSECONDS_PER_SECOND,
        );
        $date = $this->setTimestamp($this->getTimestamp() + $seconds);

        return $microseconds ? $date->addUTCUnit('microsecond', $microseconds) : $date;
    }

    /**
     * @deprecated Prefer to use add subUTCUnit() which more accurately defines what it's doing.
     *
     * Subtract seconds to the instance using timestamp. Positive $value travels
     * into the past while negative $value travels forward.
     *
     * @param string $unit
     * @param int    $value
     *
     * @return static
     */
    public function subRealUnit($unit, $value = 1): static
    {
        return $this->addUTCUnit($unit, -$value);
    }

    /**
     * Subtract seconds to the instance using timestamp. Positive $value travels
     * into the past while negative $value travels forward.
     *
     * @param string $unit
     * @param int    $value
     *
     * @return static
     */
    public function subUTCUnit($unit, $value = 1): static
    {
        return $this->addUTCUnit($unit, -$value);
    }

    /**
     * Returns true if a property can be changed via setter.
     *
     * @param string $unit
     *
     * @return bool
     */
    public static function isModifiableUnit($unit): bool
    {
        static $modifiableUnits = [
            // @call addUnit
            'millennium',
            // @call addUnit
            'century',
            // @call addUnit
            'decade',
            // @call addUnit
            'quarter',
            // @call addUnit
            'week',
            // @call addUnit
            'weekday',
        ];

        return \in_array($unit, $modifiableUnits, true) || \in_array($unit, static::$units, true);
    }

    /**
     * Call native PHP DateTime/DateTimeImmutable add() method.
     *
     * @param DateInterval $interval
     *
     * @return static
     */
    public function rawAdd(DateInterval $interval): static
    {
        return parent::add($interval);
    }

    /**
     * Add given units or interval to the current instance.
     *
     * @example $date->add('hour', 3)
     * @example $date->add(15, 'days')
     * @example $date->add(CarbonInterval::days(4))
     *
     * @param Unit|int|string|DateInterval|Closure|CarbonConverterInterface $unit
     * @param Unit|int|float|string                                         $value
     * @param bool|null                                                     $overflow
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public function add($unit, $value = 1, ?bool $overflow = null): static
    {
        $unit = Unit::toNameIfUnit($unit);
        $value = Unit::toNameIfUnit($value);

        if (\is_string($unit) && \func_num_args() === 1) {
            $unit = CarbonInterval::make($unit, [], true);
        }

        if ($unit instanceof CarbonConverterInterface) {
            $unit = Closure::fromCallable([$unit, 'convertDate']);
        }

        if ($unit instanceof Closure) {
            $result = $this->resolveCarbon($unit($this, false));

            if ($this !== $result && $this->isMutable()) {
                return $this->modify($result->rawFormat('Y-m-d H:i:s.u e O'));
            }

            return $result;
        }

        if ($unit instanceof DateInterval) {
            return parent::add($unit);
        }

        if (is_numeric($unit)) {
            [$value, $unit] = [$unit, $value];
        }

        return $this->addUnit((string) $unit, $value, $overflow);
    }

    /**
     * Add given units to the current instance.
     */
    public function addUnit(Unit|string $unit, $value = 1, ?bool $overflow = null): static
    {
        $unit = Unit::toName($unit);

        $originalArgs = \func_get_args();

        $date = $this;

        if (!is_numeric($value) || !(float) $value) {
            return $date->isMutable() ? $date : $date->copy();
        }

        $unit = self::singularUnit($unit);
        $metaUnits = [
            'millennium' => [static::YEARS_PER_MILLENNIUM, 'year'],
            'century' => [static::YEARS_PER_CENTURY, 'year'],
            'decade' => [static::YEARS_PER_DECADE, 'year'],
            'quarter' => [static::MONTHS_PER_QUARTER, 'month'],
        ];

        if (isset($metaUnits[$unit])) {
            [$factor, $unit] = $metaUnits[$unit];
            $value *= $factor;
        }

        if ($unit === 'weekday') {
            $weekendDays = $this->transmitFactory(static fn () => static::getWeekendDays());

            if ($weekendDays !== [static::SATURDAY, static::SUNDAY]) {
                $absoluteValue = abs($value);
                $sign = $value / max(1, $absoluteValue);
                $weekDaysCount = static::DAYS_PER_WEEK - min(static::DAYS_PER_WEEK - 1, \count(array_unique($weekendDays)));
                $weeks = floor($absoluteValue / $weekDaysCount);

                for ($diff = $absoluteValue % $weekDaysCount; $diff; $diff--) {
                    /** @var static $date */
                    $date = $date->addDays($sign);

                    while (\in_array($date->dayOfWeek, $weekendDays, true)) {
                        $date = $date->addDays($sign);
                    }
                }

                $value = $weeks * $sign;
                $unit = 'week';
            }

            $timeString = $date->toTimeString();
        } elseif ($canOverflow = (\in_array($unit, [
                'month',
                'year',
            ]) && ($overflow === false || (
                $overflow === null &&
                ($ucUnit = ucfirst($unit).'s') &&
                !($this->{'local'.$ucUnit.'Overflow'} ?? static::{'shouldOverflow'.$ucUnit}())
            )))) {
            $day = $date->day;
        }

        if ($unit === 'milli' || $unit === 'millisecond') {
            $unit = 'microsecond';
            $value *= static::MICROSECONDS_PER_MILLISECOND;
        }

        $previousException = null;

        try {
            $date = self::rawAddUnit($date, $unit, $value);

            if (isset($timeString)) {
                $date = $date?->setTimeFromTimeString($timeString);
            } elseif (isset($canOverflow, $day) && $canOverflow && $day !== $date?->day) {
                $date = $date?->modify('last day of previous month');
            }
        } catch (DateMalformedStringException|InvalidFormatException|UnsupportedUnitException $exception) {
            $date = null;
            $previousException = $exception;
        }

        return $date ?? throw new UnitException(
            'Unable to add unit '.var_export($originalArgs, true),
            previous: $previousException,
        );
    }

    /**
     * Subtract given units to the current instance.
     */
    public function subUnit(Unit|string $unit, $value = 1, ?bool $overflow = null): static
    {
        return $this->addUnit($unit, -$value, $overflow);
    }

    /**
     * Call native PHP DateTime/DateTimeImmutable sub() method.
     */
    public function rawSub(DateInterval $interval): static
    {
        return parent::sub($interval);
    }

    /**
     * Subtract given units or interval to the current instance.
     *
     * @example $date->sub('hour', 3)
     * @example $date->sub(15, 'days')
     * @example $date->sub(CarbonInterval::days(4))
     *
     * @param Unit|int|string|DateInterval|Closure|CarbonConverterInterface $unit
     * @param Unit|int|float|string                                         $value
     * @param bool|null                                                     $overflow
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public function sub($unit, $value = 1, ?bool $overflow = null): static
    {
        $unit = Unit::toNameIfUnit($unit);
        $value = Unit::toNameIfUnit($value);

        if (\is_string($unit) && \func_num_args() === 1) {
            $unit = CarbonInterval::make($unit, [], true);
        }

        if ($unit instanceof CarbonConverterInterface) {
            $unit = Closure::fromCallable([$unit, 'convertDate']);
        }

        if ($unit instanceof Closure) {
            $result = $this->resolveCarbon($unit($this, true));

            if ($this !== $result && $this->isMutable()) {
                return $this->modify($result->rawFormat('Y-m-d H:i:s.u e O'));
            }

            return $result;
        }

        if ($unit instanceof DateInterval) {
            return parent::sub($unit);
        }

        if (is_numeric($unit)) {
            [$value, $unit] = [$unit, $value];
        }

        return $this->addUnit((string) $unit, -(float) $value, $overflow);
    }

    /**
     * Subtract given units or interval to the current instance.
     *
     * @see sub()
     *
     * @param Unit|int|string|DateInterval $unit
     * @param Unit|int|float|string        $value
     * @param bool|null                    $overflow
     *
     * @return static
     */
    public function subtract($unit, $value = 1, ?bool $overflow = null): static
    {
        if (\is_string($unit) && \func_num_args() === 1) {
            $unit = CarbonInterval::make($unit, [], true);
        }

        return $this->sub($unit, $value, $overflow);
    }

    private static function rawAddUnit(self $date, string $unit, int|float $value): ?static
    {
        try {
            return $date->rawAdd(
                CarbonInterval::fromString(abs($value)." $unit")->invert($value < 0),
            );
        } catch (InvalidIntervalException $exception) {
            try {
                return $date->modify("$value $unit");
            } catch (InvalidFormatException) {
                throw new UnsupportedUnitException($unit, previous: $exception);
            }
        }
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Factory;
use Carbon\FactoryImmutable;
use Carbon\WrapperClock;
use Closure;

/**
 * Remember the factory that was the current at the creation of the object.
 */
trait LocalFactory
{
    /**
     * The clock that generated the current instance (or FactoryImmutable::getDefaultInstance() if none)
     */
    private ?WrapperClock $clock = null;

    public function getClock(): ?WrapperClock
    {
        return $this->clock;
    }

    private function initLocalFactory(): void
    {
        $this->clock = FactoryImmutable::getCurrentClock();
    }

    /**
     * Trigger the given action using the local factory of the object, so it will be transmitted
     * to any object also using this trait and calling initLocalFactory() in its constructor.
     *
     * @template T
     *
     * @param Closure(): T $action
     *
     * @return T
     */
    private function transmitFactory(Closure $action): mixed
    {
        $previousClock = FactoryImmutable::getCurrentClock();
        FactoryImmutable::setCurrentClock($this->clock);

        try {
            return $action();
        } finally {
            FactoryImmutable::setCurrentClock($previousClock);
        }
    }

    private function getFactory(): Factory
    {
        return $this->getClock()?->getFactory() ?? FactoryImmutable::getDefaultInstance();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\FactoryImmutable;

/**
 * Trait Macros.
 *
 * Allows users to register macros within the Carbon class.
 */
trait Macro
{
    use Mixin;

    /**
     * Register a custom macro.
     *
     * Pass null macro to remove it.
     *
     * @example
     * ```
     * $userSettings = [
     *   'locale' => 'pt',
     *   'timezone' => 'America/Sao_Paulo',
     * ];
     * Carbon::macro('userFormat', function () use ($userSettings) {
     *   return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
     * });
     * echo Carbon::yesterday()->hours(11)->userFormat();
     * ```
     *
     * @param-closure-this static $macro
     */
    public static function macro(string $name, ?callable $macro): void
    {
        FactoryImmutable::getDefaultInstance()->macro($name, $macro);
    }

    /**
     * Remove all macros and generic macros.
     */
    public static function resetMacros(): void
    {
        FactoryImmutable::getDefaultInstance()->resetMacros();
    }

    /**
     * Register a custom macro.
     *
     * @param callable $macro
     * @param int      $priority marco with higher priority is tried first
     *
     * @return void
     */
    public static function genericMacro(callable $macro, int $priority = 0): void
    {
        FactoryImmutable::getDefaultInstance()->genericMacro($macro, $priority);
    }

    /**
     * Checks if macro is registered globally.
     *
     * @param string $name
     *
     * @return bool
     */
    public static function hasMacro(string $name): bool
    {
        return FactoryImmutable::getInstance()->hasMacro($name);
    }

    /**
     * Get the raw callable macro registered globally for a given name.
     */
    public static function getMacro(string $name): ?callable
    {
        return FactoryImmutable::getInstance()->getMacro($name);
    }

    /**
     * Checks if macro is registered globally or locally.
     */
    public function hasLocalMacro(string $name): bool
    {
        return ($this->localMacros && isset($this->localMacros[$name])) || $this->transmitFactory(
            static fn () => static::hasMacro($name),
        );
    }

    /**
     * Get the raw callable macro registered globally or locally for a given name.
     */
    public function getLocalMacro(string $name): ?callable
    {
        return ($this->localMacros ?? [])[$name] ?? $this->transmitFactory(
            static fn () => static::getMacro($name),
        );
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use Carbon\CarbonInterval;

trait DeprecatedPeriodProperties
{
    /**
     * Period start in PHP < 8.2.
     *
     * @var CarbonInterface
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period start.
     */
    public $start;

    /**
     * Period end in PHP < 8.2.
     *
     * @var CarbonInterface|null
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period end.
     */
    public $end;

    /**
     * Period current iterated date in PHP < 8.2.
     *
     * @var CarbonInterface|null
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period current iterated date.
     */
    public $current;

    /**
     * Period interval in PHP < 8.2.
     *
     * @var CarbonInterval|null
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period interval.
     */
    public $interval;

    /**
     * Period recurrences in PHP < 8.2.
     *
     * @var int|float|null
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period recurrences.
     */
    public $recurrences;

    /**
     * Period start included option in PHP < 8.2.
     *
     * @var bool
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period start included option.
     */
    public $include_start_date;

    /**
     * Period end included option in PHP < 8.2.
     *
     * @var bool
     *
     * @deprecated PHP 8.2 this property is no longer in sync with the actual period end included option.
     */
    public $include_end_date;
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\FactoryImmutable;

/**
 * Options related to a static variable.
 */
trait StaticOptions
{
    ///////////////////////////////////////////////////////////////////
    ///////////// Behavior customization for sub-classes //////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * Function to call instead of format.
     *
     * @var string|callable|null
     */
    protected static $formatFunction;

    /**
     * Function to call instead of createFromFormat.
     *
     * @var string|callable|null
     */
    protected static $createFromFormatFunction;

    /**
     * Function to call instead of parse.
     *
     * @var string|callable|null
     */
    protected static $parseFunction;

    ///////////////////////////////////////////////////////////////////
    ///////////// Use default factory for static options //////////////
    ///////////////////////////////////////////////////////////////////

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     *
     * Enable the strict mode (or disable with passing false).
     *
     * @param bool $strictModeEnabled
     */
    public static function useStrictMode(bool $strictModeEnabled = true): void
    {
        FactoryImmutable::getDefaultInstance()->useStrictMode($strictModeEnabled);
    }

    /**
     * Returns true if the strict mode is globally in use, false else.
     * (It can be overridden in specific instances.)
     *
     * @return bool
     */
    public static function isStrictModeEnabled(): bool
    {
        return FactoryImmutable::getInstance()->isStrictModeEnabled();
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Indicates if months should be calculated with overflow.
     *
     * @param bool $monthsOverflow
     *
     * @return void
     */
    public static function useMonthsOverflow(bool $monthsOverflow = true): void
    {
        FactoryImmutable::getDefaultInstance()->useMonthsOverflow($monthsOverflow);
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Reset the month overflow behavior.
     *
     * @return void
     */
    public static function resetMonthsOverflow(): void
    {
        FactoryImmutable::getDefaultInstance()->resetMonthsOverflow();
    }

    /**
     * Get the month overflow global behavior (can be overridden in specific instances).
     *
     * @return bool
     */
    public static function shouldOverflowMonths(): bool
    {
        return FactoryImmutable::getInstance()->shouldOverflowMonths();
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Indicates if years should be calculated with overflow.
     *
     * @param bool $yearsOverflow
     *
     * @return void
     */
    public static function useYearsOverflow(bool $yearsOverflow = true): void
    {
        FactoryImmutable::getDefaultInstance()->useYearsOverflow($yearsOverflow);
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Reset the month overflow behavior.
     *
     * @return void
     */
    public static function resetYearsOverflow(): void
    {
        FactoryImmutable::getDefaultInstance()->resetYearsOverflow();
    }

    /**
     * Get the month overflow global behavior (can be overridden in specific instances).
     *
     * @return bool
     */
    public static function shouldOverflowYears(): bool
    {
        return FactoryImmutable::getInstance()->shouldOverflowYears();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

/**
 * Trait MagicParameter.
 *
 * Allows to retrieve parameter in magic calls by index or name.
 */
trait MagicParameter
{
    private function getMagicParameter(array $parameters, int $index, string $key, $default)
    {
        if (\array_key_exists($index, $parameters)) {
            return $parameters[$index];
        }

        if (\array_key_exists($key, $parameters)) {
            return $parameters[$key];
        }

        return $default;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Exceptions\UnknownUnitException;
use Carbon\Unit;
use Carbon\WeekDay;

/**
 * Trait Boundaries.
 *
 * startOf, endOf and derived method for each unit.
 *
 * Depends on the following properties:
 *
 * @property int $year
 * @property int $month
 * @property int $daysInMonth
 * @property int $quarter
 *
 * Depends on the following methods:
 *
 * @method $this setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0)
 * @method $this setDate(int $year, int $month, int $day)
 * @method $this addMonths(int $value = 1)
 */
trait Boundaries
{
    /**
     * Resets the time to 00:00:00 start of day
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay();
     * ```
     *
     * @return static
     */
    public function startOfDay()
    {
        return $this->setTime(0, 0, 0, 0);
    }

    /**
     * Resets the time to 23:59:59.999999 end of day
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay();
     * ```
     *
     * @return static
     */
    public function endOfDay()
    {
        return $this->setTime(static::HOURS_PER_DAY - 1, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
    }

    /**
     * Resets the date to the first day of the month and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth();
     * ```
     *
     * @return static
     */
    public function startOfMonth()
    {
        return $this->setDate($this->year, $this->month, 1)->startOfDay();
    }

    /**
     * Resets the date to end of the month and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth();
     * ```
     *
     * @return static
     */
    public function endOfMonth()
    {
        return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay();
    }

    /**
     * Resets the date to the first day of the quarter and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter();
     * ```
     *
     * @return static
     */
    public function startOfQuarter()
    {
        $month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1;

        return $this->setDate($this->year, $month, 1)->startOfDay();
    }

    /**
     * Resets the date to end of the quarter and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter();
     * ```
     *
     * @return static
     */
    public function endOfQuarter()
    {
        return $this->startOfQuarter()->addMonths(static::MONTHS_PER_QUARTER - 1)->endOfMonth();
    }

    /**
     * Resets the date to the first day of the year and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear();
     * ```
     *
     * @return static
     */
    public function startOfYear()
    {
        return $this->setDate($this->year, 1, 1)->startOfDay();
    }

    /**
     * Resets the date to end of the year and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear();
     * ```
     *
     * @return static
     */
    public function endOfYear()
    {
        return $this->setDate($this->year, 12, 31)->endOfDay();
    }

    /**
     * Resets the date to the first day of the decade and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade();
     * ```
     *
     * @return static
     */
    public function startOfDecade()
    {
        $year = $this->year - $this->year % static::YEARS_PER_DECADE;

        return $this->setDate($year, 1, 1)->startOfDay();
    }

    /**
     * Resets the date to end of the decade and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade();
     * ```
     *
     * @return static
     */
    public function endOfDecade()
    {
        $year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1;

        return $this->setDate($year, 12, 31)->endOfDay();
    }

    /**
     * Resets the date to the first day of the century and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury();
     * ```
     *
     * @return static
     */
    public function startOfCentury()
    {
        $year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY;

        return $this->setDate($year, 1, 1)->startOfDay();
    }

    /**
     * Resets the date to end of the century and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury();
     * ```
     *
     * @return static
     */
    public function endOfCentury()
    {
        $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY;

        return $this->setDate($year, 12, 31)->endOfDay();
    }

    /**
     * Resets the date to the first day of the millennium and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium();
     * ```
     *
     * @return static
     */
    public function startOfMillennium()
    {
        $year = $this->year - ($this->year - 1) % static::YEARS_PER_MILLENNIUM;

        return $this->setDate($year, 1, 1)->startOfDay();
    }

    /**
     * Resets the date to end of the millennium and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium();
     * ```
     *
     * @return static
     */
    public function endOfMillennium()
    {
        $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_MILLENNIUM + static::YEARS_PER_MILLENNIUM;

        return $this->setDate($year, 12, 31)->endOfDay();
    }

    /**
     * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n";
     * ```
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     *
     * @return static
     */
    public function startOfWeek(WeekDay|int|null $weekStartsAt = null): static
    {
        return $this
            ->subDays(
                (static::DAYS_PER_WEEK + $this->dayOfWeek - (WeekDay::int($weekStartsAt) ?? $this->firstWeekDay)) %
                static::DAYS_PER_WEEK,
            )
            ->startOfDay();
    }

    /**
     * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n";
     * ```
     *
     * @param WeekDay|int|null $weekEndsAt optional end allow you to specify the day of week to use to end the week
     *
     * @return static
     */
    public function endOfWeek(WeekDay|int|null $weekEndsAt = null): static
    {
        return $this
            ->addDays(
                (static::DAYS_PER_WEEK - $this->dayOfWeek + (WeekDay::int($weekEndsAt) ?? $this->lastWeekDay)) %
                static::DAYS_PER_WEEK,
            )
            ->endOfDay();
    }

    /**
     * Modify to start of current hour, minutes and seconds become 0
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour();
     * ```
     */
    public function startOfHour(): static
    {
        return $this->setTime($this->hour, 0, 0, 0);
    }

    /**
     * Modify to end of current hour, minutes and seconds become 59
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour();
     * ```
     */
    public function endOfHour(): static
    {
        return $this->setTime($this->hour, static::MINUTES_PER_HOUR - 1, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
    }

    /**
     * Modify to start of current minute, seconds become 0
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute();
     * ```
     */
    public function startOfMinute(): static
    {
        return $this->setTime($this->hour, $this->minute, 0, 0);
    }

    /**
     * Modify to end of current minute, seconds become 59
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute();
     * ```
     */
    public function endOfMinute(): static
    {
        return $this->setTime($this->hour, $this->minute, static::SECONDS_PER_MINUTE - 1, static::MICROSECONDS_PER_SECOND - 1);
    }

    /**
     * Modify to start of current second, microseconds become 0
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function startOfSecond(): static
    {
        return $this->setTime($this->hour, $this->minute, $this->second, 0);
    }

    /**
     * Modify to end of current second, microseconds become 999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->endOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function endOfSecond(): static
    {
        return $this->setTime($this->hour, $this->minute, $this->second, static::MICROSECONDS_PER_SECOND - 1);
    }

    /**
     * Modify to start of current millisecond, microseconds such as 12345 become 123000
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function startOfMillisecond(): static
    {
        $millisecond = (int) floor($this->micro / 1000);

        return $this->setTime($this->hour, $this->minute, $this->second, $millisecond * 1000);
    }

    /**
     * Modify to end of current millisecond, microseconds such as 12345 become 123999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->endOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function endOfMillisecond(): static
    {
        $millisecond = (int) floor($this->micro / 1000);

        return $this->setTime($this->hour, $this->minute, $this->second, $millisecond * 1000 + 999);
    }

    /**
     * Modify to start of current given unit.
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOf(Unit::Month)
     *   ->endOf(Unit::Week, Carbon::FRIDAY);
     * ```
     */
    public function startOf(Unit|string $unit, mixed ...$params): static
    {
        $ucfUnit = ucfirst($unit instanceof Unit ? $unit->value : static::singularUnit($unit));
        $method = "startOf$ucfUnit";
        if (!method_exists($this, $method)) {
            throw new UnknownUnitException($unit);
        }

        return $this->$method(...$params);
    }

    /**
     * Modify to end of current given unit.
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOf(Unit::Month)
     *   ->endOf(Unit::Week, Carbon::FRIDAY);
     * ```
     */
    public function endOf(Unit|string $unit, mixed ...$params): static
    {
        $ucfUnit = ucfirst($unit instanceof Unit ? $unit->value : static::singularUnit($unit));
        $method = "endOf$ucfUnit";
        if (!method_exists($this, $method)) {
            throw new UnknownUnitException($unit);
        }

        return $this->$method(...$params);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Carbon\CarbonPeriodImmutable;
use Carbon\Exceptions\UnitException;
use Closure;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;

/**
 * Trait Converter.
 *
 * Change date into different string formats and types and
 * handle the string cast.
 *
 * Depends on the following methods:
 *
 * @method static copy()
 */
trait Converter
{
    use ToStringFormat;

    /**
     * Returns the formatted date string on success or FALSE on failure.
     *
     * @see https://php.net/manual/en/datetime.format.php
     */
    public function format(string $format): string
    {
        $function = $this->localFormatFunction
            ?? $this->getFactory()->getSettings()['formatFunction']
            ?? static::$formatFunction;

        if (!$function) {
            return $this->rawFormat($format);
        }

        if (\is_string($function) && method_exists($this, $function)) {
            $function = [$this, $function];
        }

        return $function(...\func_get_args());
    }

    /**
     * @see https://php.net/manual/en/datetime.format.php
     */
    public function rawFormat(string $format): string
    {
        return parent::format($format);
    }

    /**
     * Format the instance as a string using the set format
     *
     * @example
     * ```
     * echo Carbon::now(); // Carbon instances can be cast to string
     * ```
     */
    public function __toString(): string
    {
        $format = $this->localToStringFormat
            ?? $this->getFactory()->getSettings()['toStringFormat']
            ?? null;

        return $format instanceof Closure
            ? $format($this)
            : $this->rawFormat($format ?: (
                \defined('static::DEFAULT_TO_STRING_FORMAT')
                    ? static::DEFAULT_TO_STRING_FORMAT
                    : CarbonInterface::DEFAULT_TO_STRING_FORMAT
            ));
    }

    /**
     * Format the instance as date
     *
     * @example
     * ```
     * echo Carbon::now()->toDateString();
     * ```
     */
    public function toDateString(): string
    {
        return $this->rawFormat('Y-m-d');
    }

    /**
     * Format the instance as a readable date
     *
     * @example
     * ```
     * echo Carbon::now()->toFormattedDateString();
     * ```
     */
    public function toFormattedDateString(): string
    {
        return $this->rawFormat('M j, Y');
    }

    /**
     * Format the instance with the day, and a readable date
     *
     * @example
     * ```
     * echo Carbon::now()->toFormattedDayDateString();
     * ```
     */
    public function toFormattedDayDateString(): string
    {
        return $this->rawFormat('D, M j, Y');
    }

    /**
     * Format the instance as time
     *
     * @example
     * ```
     * echo Carbon::now()->toTimeString();
     * ```
     */
    public function toTimeString(string $unitPrecision = 'second'): string
    {
        return $this->rawFormat(static::getTimeFormatByPrecision($unitPrecision));
    }

    /**
     * Format the instance as date and time
     *
     * @example
     * ```
     * echo Carbon::now()->toDateTimeString();
     * ```
     */
    public function toDateTimeString(string $unitPrecision = 'second'): string
    {
        return $this->rawFormat('Y-m-d '.static::getTimeFormatByPrecision($unitPrecision));
    }

    /**
     * Return a format from H:i to H:i:s.u according to given unit precision.
     *
     * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond"
     */
    public static function getTimeFormatByPrecision(string $unitPrecision): string
    {
        return match (static::singularUnit($unitPrecision)) {
            'minute' => 'H:i',
            'second' => 'H:i:s',
            'm', 'millisecond' => 'H:i:s.v',
            'µ', 'microsecond' => 'H:i:s.u',
            default => throw new UnitException('Precision unit expected among: minute, second, millisecond and microsecond.'),
        };
    }

    /**
     * Format the instance as date and time T-separated with no timezone
     *
     * @example
     * ```
     * echo Carbon::now()->toDateTimeLocalString();
     * echo "\n";
     * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond
     * ```
     */
    public function toDateTimeLocalString(string $unitPrecision = 'second'): string
    {
        return $this->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision));
    }

    /**
     * Format the instance with day, date and time
     *
     * @example
     * ```
     * echo Carbon::now()->toDayDateTimeString();
     * ```
     */
    public function toDayDateTimeString(): string
    {
        return $this->rawFormat('D, M j, Y g:i A');
    }

    /**
     * Format the instance as ATOM
     *
     * @example
     * ```
     * echo Carbon::now()->toAtomString();
     * ```
     */
    public function toAtomString(): string
    {
        return $this->rawFormat(DateTime::ATOM);
    }

    /**
     * Format the instance as COOKIE
     *
     * @example
     * ```
     * echo Carbon::now()->toCookieString();
     * ```
     */
    public function toCookieString(): string
    {
        return $this->rawFormat(DateTimeInterface::COOKIE);
    }

    /**
     * Format the instance as ISO8601
     *
     * @example
     * ```
     * echo Carbon::now()->toIso8601String();
     * ```
     */
    public function toIso8601String(): string
    {
        return $this->toAtomString();
    }

    /**
     * Format the instance as RFC822
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc822String();
     * ```
     */
    public function toRfc822String(): string
    {
        return $this->rawFormat(DateTimeInterface::RFC822);
    }

    /**
     * Convert the instance to UTC and return as Zulu ISO8601
     *
     * @example
     * ```
     * echo Carbon::now()->toIso8601ZuluString();
     * ```
     */
    public function toIso8601ZuluString(string $unitPrecision = 'second'): string
    {
        return $this->avoidMutation()
            ->utc()
            ->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
    }

    /**
     * Format the instance as RFC850
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc850String();
     * ```
     */
    public function toRfc850String(): string
    {
        return $this->rawFormat(DateTimeInterface::RFC850);
    }

    /**
     * Format the instance as RFC1036
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc1036String();
     * ```
     */
    public function toRfc1036String(): string
    {
        return $this->rawFormat(DateTimeInterface::RFC1036);
    }

    /**
     * Format the instance as RFC1123
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc1123String();
     * ```
     */
    public function toRfc1123String(): string
    {
        return $this->rawFormat(DateTimeInterface::RFC1123);
    }

    /**
     * Format the instance as RFC2822
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc2822String();
     * ```
     */
    public function toRfc2822String(): string
    {
        return $this->rawFormat(DateTimeInterface::RFC2822);
    }

    /**
     * Format the instance as RFC3339.
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc3339String() . "\n";
     * echo Carbon::now()->toRfc3339String(true) . "\n";
     * ```
     */
    public function toRfc3339String(bool $extended = false): string
    {
        return $this->rawFormat($extended ? DateTimeInterface::RFC3339_EXTENDED : DateTimeInterface::RFC3339);
    }

    /**
     * Format the instance as RSS
     *
     * @example
     * ```
     * echo Carbon::now()->toRssString();
     * ```
     */
    public function toRssString(): string
    {
        return $this->rawFormat(DateTimeInterface::RSS);
    }

    /**
     * Format the instance as W3C
     *
     * @example
     * ```
     * echo Carbon::now()->toW3cString();
     * ```
     */
    public function toW3cString(): string
    {
        return $this->rawFormat(DateTimeInterface::W3C);
    }

    /**
     * Format the instance as RFC7231
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc7231String();
     * ```
     */
    public function toRfc7231String(): string
    {
        return $this->avoidMutation()
            ->setTimezone('GMT')
            ->rawFormat(\defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT);
    }

    /**
     * Get default array representation.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toArray());
     * ```
     */
    public function toArray(): array
    {
        return [
            'year' => $this->year,
            'month' => $this->month,
            'day' => $this->day,
            'dayOfWeek' => $this->dayOfWeek,
            'dayOfYear' => $this->dayOfYear,
            'hour' => $this->hour,
            'minute' => $this->minute,
            'second' => $this->second,
            'micro' => $this->micro,
            'timestamp' => $this->timestamp,
            'formatted' => $this->rawFormat(\defined('static::DEFAULT_TO_STRING_FORMAT') ? static::DEFAULT_TO_STRING_FORMAT : CarbonInterface::DEFAULT_TO_STRING_FORMAT),
            'timezone' => $this->timezone,
        ];
    }

    /**
     * Get default object representation.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toObject());
     * ```
     */
    public function toObject(): object
    {
        return (object) $this->toArray();
    }

    /**
     * Returns english human-readable complete date string.
     *
     * @example
     * ```
     * echo Carbon::now()->toString();
     * ```
     */
    public function toString(): string
    {
        return $this->avoidMutation()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
    }

    /**
     * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
     * 1977-04-22T01:00:00-05:00).
     *
     * @example
     * ```
     * echo Carbon::now('America/Toronto')->toISOString() . "\n";
     * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
     * ```
     *
     * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
     */
    public function toISOString(bool $keepOffset = false): ?string
    {
        if (!$this->isValid()) {
            return null;
        }

        $yearFormat = $this->year < 0 || $this->year > 9999 ? 'YYYYYY' : 'YYYY';
        $timezoneFormat = $keepOffset ? 'Z' : '[Z]';
        $date = $keepOffset ? $this : $this->avoidMutation()->utc();

        return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$timezoneFormat");
    }

    /**
     * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
     *
     * @example
     * ```
     * echo Carbon::now('America/Toronto')->toJSON();
     * ```
     */
    public function toJSON(): ?string
    {
        return $this->toISOString();
    }

    /**
     * Return native DateTime PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDateTime());
     * ```
     */
    public function toDateTime(): DateTime
    {
        return DateTime::createFromFormat('U.u', $this->rawFormat('U.u'))
            ->setTimezone($this->getTimezone());
    }

    /**
     * Return native toDateTimeImmutable PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDateTimeImmutable());
     * ```
     */
    public function toDateTimeImmutable(): DateTimeImmutable
    {
        return DateTimeImmutable::createFromFormat('U.u', $this->rawFormat('U.u'))
            ->setTimezone($this->getTimezone());
    }

    /**
     * @alias toDateTime
     *
     * Return native DateTime PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDate());
     * ```
     */
    public function toDate(): DateTime
    {
        return $this->toDateTime();
    }

    /**
     * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
     *
     * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end      period end date or recurrences count if int
     * @param int|\DateInterval|string|null                      $interval period default interval or number of the given $unit
     * @param string|null                                        $unit     if specified, $interval must be an integer
     */
    public function toPeriod($end = null, $interval = null, $unit = null): CarbonPeriod
    {
        if ($unit) {
            $interval = CarbonInterval::make("$interval ".static::pluralUnit($unit));
        }

        $isDefaultInterval = !$interval;
        $interval ??= CarbonInterval::day();
        $class = $this->isMutable() ? CarbonPeriod::class : CarbonPeriodImmutable::class;

        if (\is_int($end) || (\is_string($end) && ctype_digit($end))) {
            $end = (int) $end;
        }

        $end ??= 1;

        if (!\is_int($end)) {
            $end = $this->resolveCarbon($end);
        }

        return new $class(
            raw: [$this, CarbonInterval::make($interval), $end],
            dateClass: static::class,
            isDefaultInterval: $isDefaultInterval,
        );
    }

    /**
     * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
     *
     * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end      period end date
     * @param int|\DateInterval|string|null                  $interval period default interval or number of the given $unit
     * @param string|null                                    $unit     if specified, $interval must be an integer
     */
    public function range($end = null, $interval = null, $unit = null): CarbonPeriod
    {
        return $this->toPeriod($end, $interval, $unit);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use Carbon\Exceptions\InvalidTypeException;
use Carbon\Exceptions\NotLocaleAwareException;
use Carbon\Language;
use Carbon\Translator;
use Carbon\TranslatorStrongTypeInterface;
use Closure;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Trait Localization.
 *
 * Embed default and locale translators and translation base methods.
 */
trait Localization
{
    use StaticLocalization;

    /**
     * Specific translator of the current instance.
     */
    protected ?TranslatorInterface $localTranslator = null;

    /**
     * Return true if the current instance has its own translator.
     */
    public function hasLocalTranslator(): bool
    {
        return isset($this->localTranslator);
    }

    /**
     * Get the translator of the current instance or the default if none set.
     */
    public function getLocalTranslator(): TranslatorInterface
    {
        return $this->localTranslator ?? $this->transmitFactory(static fn () => static::getTranslator());
    }

    /**
     * Set the translator for the current instance.
     */
    public function setLocalTranslator(TranslatorInterface $translator): self
    {
        $this->localTranslator = $translator;

        return $this;
    }

    /**
     * Returns raw translation message for a given key.
     *
     * @param TranslatorInterface|null $translator the translator to use
     * @param string                   $key        key to find
     * @param string|null              $locale     current locale used if null
     * @param string|null              $default    default value if translation returns the key
     *
     * @return string|Closure|null
     */
    public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)
    {
        if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) {
            throw new InvalidTypeException(
                'Translator does not implement '.TranslatorInterface::class.' and '.TranslatorBagInterface::class.'. '.
                (\is_object($translator) ? \get_class($translator) : \gettype($translator)).' has been given.',
            );
        }

        if (!$locale && $translator instanceof LocaleAwareInterface) {
            $locale = $translator->getLocale();
        }

        $result = self::getFromCatalogue($translator, $translator->getCatalogue($locale), $key);

        return $result === $key ? $default : $result;
    }

    /**
     * Returns raw translation message for a given key.
     *
     * @param string              $key        key to find
     * @param string|null         $locale     current locale used if null
     * @param string|null         $default    default value if translation returns the key
     * @param TranslatorInterface $translator an optional translator to use
     *
     * @return string
     */
    public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
    {
        return static::getTranslationMessageWith($translator ?? $this->getLocalTranslator(), $key, $locale, $default);
    }

    /**
     * Translate using translation string or callback available.
     *
     * @param TranslatorInterface $translator an optional translator to use
     * @param string              $key        key to find
     * @param array               $parameters replacement parameters
     * @param int|float|null      $number     number if plural
     *
     * @return string
     */
    public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string
    {
        $message = static::getTranslationMessageWith($translator, $key, null, $key);
        if ($message instanceof Closure) {
            return (string) $message(...array_values($parameters));
        }

        if ($number !== null) {
            $parameters['%count%'] = $number;
        }
        if (isset($parameters['%count%'])) {
            $parameters[':count'] = $parameters['%count%'];
        }

        return (string) $translator->trans($key, $parameters);
    }

    /**
     * Translate using translation string or callback available.
     *
     * @param string                   $key        key to find
     * @param array                    $parameters replacement parameters
     * @param string|int|float|null    $number     number if plural
     * @param TranslatorInterface|null $translator an optional translator to use
     * @param bool                     $altNumbers pass true to use alternative numbers
     *
     * @return string
     */
    public function translate(
        string $key,
        array $parameters = [],
        string|int|float|null $number = null,
        ?TranslatorInterface $translator = null,
        bool $altNumbers = false,
    ): string {
        $translation = static::translateWith($translator ?? $this->getLocalTranslator(), $key, $parameters, $number);

        if ($number !== null && $altNumbers) {
            return str_replace((string) $number, $this->translateNumber((int) $number), $translation);
        }

        return $translation;
    }

    /**
     * Returns the alternative number for a given integer if available in the current locale.
     *
     * @param int $number
     *
     * @return string
     */
    public function translateNumber(int $number): string
    {
        $translateKey = "alt_numbers.$number";
        $symbol = $this->translate($translateKey);

        if ($symbol !== $translateKey) {
            return $symbol;
        }

        if ($number > 99 && $this->translate('alt_numbers.99') !== 'alt_numbers.99') {
            $start = '';
            foreach ([10000, 1000, 100] as $exp) {
                $key = "alt_numbers_pow.$exp";
                if ($number >= $exp && $number < $exp * 10 && ($pow = $this->translate($key)) !== $key) {
                    $unit = floor($number / $exp);
                    $number -= $unit * $exp;
                    $start .= ($unit > 1 ? $this->translate("alt_numbers.$unit") : '').$pow;
                }
            }
            $result = '';
            while ($number) {
                $chunk = $number % 100;
                $result = $this->translate("alt_numbers.$chunk").$result;
                $number = floor($number / 100);
            }

            return "$start$result";
        }

        if ($number > 9 && $this->translate('alt_numbers.9') !== 'alt_numbers.9') {
            $result = '';
            while ($number) {
                $chunk = $number % 10;
                $result = $this->translate("alt_numbers.$chunk").$result;
                $number = floor($number / 10);
            }

            return $result;
        }

        return (string) $number;
    }

    /**
     * Translate a time string from a locale to an other.
     *
     * @param string      $timeString date/time/duration string to translate (may also contain English)
     * @param string|null $from       input locale of the $timeString parameter (`Carbon::getLocale()` by default)
     * @param string|null $to         output locale of the result returned (`"en"` by default)
     * @param int         $mode       specify what to translate with options:
     *                                - CarbonInterface::TRANSLATE_ALL (default)
     *                                - CarbonInterface::TRANSLATE_MONTHS
     *                                - CarbonInterface::TRANSLATE_DAYS
     *                                - CarbonInterface::TRANSLATE_UNITS
     *                                - CarbonInterface::TRANSLATE_MERIDIEM
     *                                You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS
     *
     * @return string
     */
    public static function translateTimeString(
        string $timeString,
        ?string $from = null,
        ?string $to = null,
        int $mode = CarbonInterface::TRANSLATE_ALL,
    ): string {
        // Fallback source and destination locales
        $from = $from ?: static::getLocale();
        $to = $to ?: CarbonInterface::DEFAULT_LOCALE;

        if ($from === $to) {
            return $timeString;
        }

        // Standardize apostrophe
        $timeString = strtr($timeString, ['’' => "'"]);

        $fromTranslations = [];
        $toTranslations = [];

        foreach (['from', 'to'] as $key) {
            $language = $$key;
            $translator = Translator::get($language);
            $translations = $translator->getMessages();

            if (!isset($translations[$language])) {
                return $timeString;
            }

            $translationKey = $key.'Translations';
            $messages = $translations[$language];
            $months = $messages['months'] ?? [];
            $weekdays = $messages['weekdays'] ?? [];
            $meridiem = $messages['meridiem'] ?? ['AM', 'PM'];

            if (isset($messages['ordinal_words'])) {
                $timeString = self::replaceOrdinalWords(
                    $timeString,
                    $key === 'from' ? array_flip($messages['ordinal_words']) : $messages['ordinal_words']
                );
            }

            if ($key === 'from') {
                foreach (['months', 'weekdays'] as $variable) {
                    $list = $messages[$variable.'_standalone'] ?? null;

                    if ($list) {
                        foreach ($$variable as $index => &$name) {
                            $name .= '|'.$list[$index];
                        }
                    }
                }
            }

            $$translationKey = array_merge(
                $mode & CarbonInterface::TRANSLATE_MONTHS ? self::getTranslationArray($months, static::MONTHS_PER_YEAR, $timeString) : [],
                $mode & CarbonInterface::TRANSLATE_MONTHS ? self::getTranslationArray($messages['months_short'] ?? [], static::MONTHS_PER_YEAR, $timeString) : [],
                $mode & CarbonInterface::TRANSLATE_DAYS ? self::getTranslationArray($weekdays, static::DAYS_PER_WEEK, $timeString) : [],
                $mode & CarbonInterface::TRANSLATE_DAYS ? self::getTranslationArray($messages['weekdays_short'] ?? [], static::DAYS_PER_WEEK, $timeString) : [],
                $mode & CarbonInterface::TRANSLATE_DIFF ? self::translateWordsByKeys([
                    'diff_now',
                    'diff_today',
                    'diff_yesterday',
                    'diff_tomorrow',
                    'diff_before_yesterday',
                    'diff_after_tomorrow',
                ], $messages, $key) : [],
                $mode & CarbonInterface::TRANSLATE_UNITS ? self::translateWordsByKeys([
                    'year',
                    'month',
                    'week',
                    'day',
                    'hour',
                    'minute',
                    'second',
                ], $messages, $key) : [],
                $mode & CarbonInterface::TRANSLATE_MERIDIEM ? array_map(function ($hour) use ($meridiem) {
                    if (\is_array($meridiem)) {
                        return $meridiem[$hour < static::HOURS_PER_DAY / 2 ? 0 : 1];
                    }

                    return $meridiem($hour, 0, false);
                }, range(0, 23)) : [],
            );
        }

        return substr(preg_replace_callback('/(?<=[\d\s+.\/,_-])('.implode('|', $fromTranslations).')(?=[\d\s+.\/,_-])/iu', function ($match) use ($fromTranslations, $toTranslations) {
            [$chunk] = $match;

            foreach ($fromTranslations as $index => $word) {
                if (preg_match("/^$word\$/iu", $chunk)) {
                    return $toTranslations[$index] ?? '';
                }
            }

            return $chunk; // @codeCoverageIgnore
        }, " $timeString "), 1, -1);
    }

    /**
     * Translate a time string from the current locale (`$date->locale()`) to another one.
     *
     * @param string      $timeString time string to translate
     * @param string|null $to         output locale of the result returned ("en" by default)
     *
     * @return string
     */
    public function translateTimeStringTo(string $timeString, ?string $to = null): string
    {
        return static::translateTimeString($timeString, $this->getTranslatorLocale(), $to);
    }

    /**
     * Get/set the locale for the current instance.
     *
     * @param string|null $locale
     * @param string      ...$fallbackLocales
     *
     * @return $this|string
     */
    public function locale(?string $locale = null, string ...$fallbackLocales): static|string
    {
        if ($locale === null) {
            return $this->getTranslatorLocale();
        }

        if (!$this->localTranslator || $this->getTranslatorLocale($this->localTranslator) !== $locale) {
            $translator = Translator::get($locale);

            if (!empty($fallbackLocales)) {
                $translator->setFallbackLocales($fallbackLocales);

                foreach ($fallbackLocales as $fallbackLocale) {
                    $messages = Translator::get($fallbackLocale)->getMessages();

                    if (isset($messages[$fallbackLocale])) {
                        $translator->setMessages($fallbackLocale, $messages[$fallbackLocale]);
                    }
                }
            }

            $this->localTranslator = $translator;
        }

        return $this;
    }

    /**
     * Get the current translator locale.
     *
     * @return string
     */
    public static function getLocale(): string
    {
        return static::getLocaleAwareTranslator()->getLocale();
    }

    /**
     * Set the current translator locale and indicate if the source locale file exists.
     * Pass 'auto' as locale to use the closest language to the current LC_TIME locale.
     *
     * @param string $locale locale ex. en
     */
    public static function setLocale(string $locale): void
    {
        static::getLocaleAwareTranslator()->setLocale($locale);
    }

    /**
     * Set the fallback locale.
     *
     * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
     *
     * @param string $locale
     */
    public static function setFallbackLocale(string $locale): void
    {
        $translator = static::getTranslator();

        if (method_exists($translator, 'setFallbackLocales')) {
            $translator->setFallbackLocales([$locale]);

            if ($translator instanceof Translator) {
                $preferredLocale = $translator->getLocale();
                $fallbackMessages = [];
                $preferredMessages = $translator->getMessages($preferredLocale);

                foreach (Translator::get($locale)->getMessages()[$locale] ?? [] as $key => $value) {
                    if (
                        preg_match('/^(?:a_)?(.+)_(?:standalone|ago|from_now|before|after|short|min)$/', $key, $match)
                        && isset($preferredMessages[$match[1]])
                    ) {
                        continue;
                    }

                    $fallbackMessages[$key] = $value;
                }

                $translator->setMessages($preferredLocale, array_replace_recursive(
                    $translator->getMessages()[$locale] ?? [],
                    $fallbackMessages,
                    $preferredMessages,
                ));
            }
        }
    }

    /**
     * Get the fallback locale.
     *
     * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
     */
    public static function getFallbackLocale(): ?string
    {
        $translator = static::getTranslator();

        if (method_exists($translator, 'getFallbackLocales')) {
            return $translator->getFallbackLocales()[0] ?? null;
        }

        return null;
    }

    /**
     * Set the current locale to the given, execute the passed function, reset the locale to previous one,
     * then return the result of the closure (or null if the closure was void).
     *
     * @param string   $locale locale ex. en
     * @param callable $func
     *
     * @return mixed
     */
    public static function executeWithLocale(string $locale, callable $func): mixed
    {
        $currentLocale = static::getLocale();
        static::setLocale($locale);
        $newLocale = static::getLocale();
        $result = $func(
            $newLocale === 'en' && strtolower(substr((string) $locale, 0, 2)) !== 'en'
                ? false
                : $newLocale,
            static::getTranslator(),
        );
        static::setLocale($currentLocale);

        return $result;
    }

    /**
     * Returns true if the given locale is internally supported and has short-units support.
     * Support is considered enabled if either year, day or hour has a short variant translated.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasShortUnits(string $locale): bool
    {
        return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
            return ($newLocale && (($y = static::translateWith($translator, 'y')) !== 'y' && $y !== static::translateWith($translator, 'year'))) || (
                ($y = static::translateWith($translator, 'd')) !== 'd' &&
                    $y !== static::translateWith($translator, 'day')
            ) || (
                ($y = static::translateWith($translator, 'h')) !== 'h' &&
                    $y !== static::translateWith($translator, 'hour')
            );
        });
    }

    /**
     * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
     * Support is considered enabled if the 4 sentences are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasDiffSyntax(string $locale): bool
    {
        return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
            if (!$newLocale) {
                return false;
            }

            foreach (['ago', 'from_now', 'before', 'after'] as $key) {
                if ($translator instanceof TranslatorBagInterface &&
                    self::getFromCatalogue($translator, $translator->getCatalogue($newLocale), $key) instanceof Closure
                ) {
                    continue;
                }

                if ($translator->trans($key) === $key) {
                    return false;
                }
            }

            return true;
        });
    }

    /**
     * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
     * Support is considered enabled if the 3 words are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasDiffOneDayWords(string $locale): bool
    {
        return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
            return $newLocale &&
                $translator->trans('diff_now') !== 'diff_now' &&
                $translator->trans('diff_yesterday') !== 'diff_yesterday' &&
                $translator->trans('diff_tomorrow') !== 'diff_tomorrow';
        });
    }

    /**
     * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
     * Support is considered enabled if the 2 words are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasDiffTwoDayWords(string $locale): bool
    {
        return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
            return $newLocale &&
                $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' &&
                $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow';
        });
    }

    /**
     * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
     * Support is considered enabled if the 4 sentences are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasPeriodSyntax($locale)
    {
        return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
            return $newLocale &&
                $translator->trans('period_recurrences') !== 'period_recurrences' &&
                $translator->trans('period_interval') !== 'period_interval' &&
                $translator->trans('period_start_date') !== 'period_start_date' &&
                $translator->trans('period_end_date') !== 'period_end_date';
        });
    }

    /**
     * Returns the list of internally available locales and already loaded custom locales.
     * (It will ignore custom translator dynamic loading.)
     *
     * @return array
     */
    public static function getAvailableLocales(): array
    {
        $translator = static::getLocaleAwareTranslator();

        return $translator instanceof Translator
            ? $translator->getAvailableLocales()
            : [$translator->getLocale()];
    }

    /**
     * Returns list of Language object for each available locale. This object allow you to get the ISO name, native
     * name, region and variant of the locale.
     *
     * @return Language[]
     */
    public static function getAvailableLocalesInfo(): array
    {
        $languages = [];

        foreach (static::getAvailableLocales() as $id) {
            $languages[$id] = new Language($id);
        }

        return $languages;
    }

    /**
     * Get the locale of a given translator.
     *
     * If null or omitted, current local translator is used.
     * If no local translator is in use, current global translator is used.
     */
    protected function getTranslatorLocale($translator = null): ?string
    {
        if (\func_num_args() === 0) {
            $translator = $this->getLocalTranslator();
        }

        $translator = static::getLocaleAwareTranslator($translator);

        return $translator?->getLocale();
    }

    /**
     * Throw an error if passed object is not LocaleAwareInterface.
     *
     * @param LocaleAwareInterface|null $translator
     *
     * @return LocaleAwareInterface|null
     */
    protected static function getLocaleAwareTranslator($translator = null)
    {
        if (\func_num_args() === 0) {
            $translator = static::getTranslator();
        }

        if ($translator && !($translator instanceof LocaleAwareInterface || method_exists($translator, 'getLocale'))) {
            throw new NotLocaleAwareException($translator); // @codeCoverageIgnore
        }

        return $translator;
    }

    /**
     * @param mixed                                                    $translator
     * @param \Symfony\Component\Translation\MessageCatalogueInterface $catalogue
     *
     * @return mixed
     */
    private static function getFromCatalogue($translator, $catalogue, string $id, string $domain = 'messages')
    {
        return $translator instanceof TranslatorStrongTypeInterface
            ? $translator->getFromCatalogue($catalogue, $id, $domain)
            : $catalogue->get($id, $domain); // @codeCoverageIgnore
    }

    /**
     * Return the word cleaned from its translation codes.
     *
     * @param string $word
     *
     * @return string
     */
    private static function cleanWordFromTranslationString($word)
    {
        $word = str_replace([':count', '%count', ':time'], '', $word);
        $word = strtr($word, ['’' => "'"]);
        $word = preg_replace(
            '/\{(?:-?\d+(?:\.\d+)?|-?Inf)(?:,(?:-?\d+|-?Inf))?}|[\[\]](?:-?\d+(?:\.\d+)?|-?Inf)(?:,(?:-?\d+|-?Inf))?[\[\]]/',
            '',
            $word,
        );

        return trim($word);
    }

    /**
     * Translate a list of words.
     *
     * @param string[] $keys     keys to translate.
     * @param string[] $messages messages bag handling translations.
     * @param string   $key      'to' (to get the translation) or 'from' (to get the detection RegExp pattern).
     *
     * @return string[]
     */
    private static function translateWordsByKeys($keys, $messages, $key): array
    {
        return array_map(function ($wordKey) use ($messages, $key) {
            $message = $key === 'from' && isset($messages[$wordKey.'_regexp'])
                ? $messages[$wordKey.'_regexp']
                : ($messages[$wordKey] ?? null);

            if (!$message) {
                return '>>DO NOT REPLACE<<';
            }

            $parts = explode('|', $message);

            return $key === 'to'
                ? self::cleanWordFromTranslationString(end($parts))
                : '(?:'.implode('|', array_map(static::cleanWordFromTranslationString(...), $parts)).')';
        }, $keys);
    }

    /**
     * Get an array of translations based on the current date.
     *
     * @param callable $translation
     * @param int      $length
     * @param string   $timeString
     *
     * @return string[]
     */
    private static function getTranslationArray($translation, $length, $timeString): array
    {
        $filler = '>>DO NOT REPLACE<<';

        if (\is_array($translation)) {
            return array_pad($translation, $length, $filler);
        }

        $list = [];
        $date = static::now();

        for ($i = 0; $i < $length; $i++) {
            $list[] = $translation($date, $timeString, $i) ?? $filler;
        }

        return $list;
    }

    private static function replaceOrdinalWords(string $timeString, array $ordinalWords): string
    {
        return preg_replace_callback('/(?<![a-z])[a-z]+(?![a-z])/i', function (array $match) use ($ordinalWords) {
            return $ordinalWords[mb_strtolower($match[0])] ?? $match[0];
        }, $timeString);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\Callback;
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Closure;
use DateTimeImmutable;
use DateTimeInterface;

trait IntervalStep
{
    /**
     * Step to apply instead of a fixed interval to get the new date.
     *
     * @var Closure|null
     */
    protected $step;

    /**
     * Get the dynamic step in use.
     *
     * @return Closure
     */
    public function getStep(): ?Closure
    {
        return $this->step;
    }

    /**
     * Set a step to apply instead of a fixed interval to get the new date.
     *
     * Or pass null to switch to fixed interval.
     *
     * @param Closure|null $step
     */
    public function setStep(?Closure $step): void
    {
        $this->step = $step;
    }

    /**
     * Take a date and apply either the step if set, or the current interval else.
     *
     * The interval/step is applied negatively (typically subtraction instead of addition) if $negated is true.
     *
     * @param DateTimeInterface $dateTime
     * @param bool              $negated
     *
     * @return CarbonInterface
     */
    public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface
    {
        /** @var CarbonInterface $carbonDate */
        $carbonDate = $dateTime instanceof CarbonInterface ? $dateTime : $this->resolveCarbon($dateTime);

        if ($this->step) {
            $carbonDate = Callback::parameter($this->step, $carbonDate->avoidMutation());

            return $carbonDate->modify(($this->step)($carbonDate, $negated)->format('Y-m-d H:i:s.u e O'));
        }

        if ($negated) {
            return $carbonDate->rawSub($this);
        }

        return $carbonDate->rawAdd($this);
    }

    /**
     * Convert DateTimeImmutable instance to CarbonImmutable instance and DateTime instance to Carbon instance.
     */
    private function resolveCarbon(DateTimeInterface $dateTime): Carbon|CarbonImmutable
    {
        if ($dateTime instanceof DateTimeImmutable) {
            return CarbonImmutable::instance($dateTime);
        }

        return Carbon::instance($dateTime);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use Carbon\Exceptions\InvalidFormatException;
use ReturnTypeWillChange;

/**
 * Trait Modifiers.
 *
 * Returns dates relative to current date using modifier short-hand.
 */
trait Modifiers
{
    /**
     * Midday/noon hour.
     *
     * @var int
     */
    protected static $midDayAt = 12;

    /**
     * get midday/noon hour
     *
     * @return int
     */
    public static function getMidDayAt()
    {
        return static::$midDayAt;
    }

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather consider mid-day is always 12pm, then if you need to test if it's an other
     *             hour, test it explicitly:
     *                 $date->format('G') == 13
     *             or to set explicitly to a given hour:
     *                 $date->setTime(13, 0, 0, 0)
     *
     * Set midday/noon hour
     *
     * @param int $hour midday hour
     *
     * @return void
     */
    public static function setMidDayAt($hour)
    {
        static::$midDayAt = $hour;
    }

    /**
     * Modify to midday, default to self::$midDayAt
     *
     * @return static
     */
    public function midDay()
    {
        return $this->setTime(static::$midDayAt, 0, 0, 0);
    }

    /**
     * Modify to the next occurrence of a given modifier such as a day of
     * the week. If no modifier is provided, modify to the next occurrence
     * of the current day of the week. Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param string|int|null $modifier
     *
     * @return static
     */
    public function next($modifier = null)
    {
        if ($modifier === null) {
            $modifier = $this->dayOfWeek;
        }

        return $this->change(
            'next '.(\is_string($modifier) ? $modifier : static::$days[$modifier]),
        );
    }

    /**
     * Go forward or backward to the next week- or weekend-day.
     *
     * @param bool $weekday
     * @param bool $forward
     *
     * @return static
     */
    private function nextOrPreviousDay($weekday = true, $forward = true)
    {
        /** @var CarbonInterface $date */
        $date = $this;
        $step = $forward ? 1 : -1;

        do {
            $date = $date->addDays($step);
        } while ($weekday ? $date->isWeekend() : $date->isWeekday());

        return $date;
    }

    /**
     * Go forward to the next weekday.
     *
     * @return static
     */
    public function nextWeekday()
    {
        return $this->nextOrPreviousDay();
    }

    /**
     * Go backward to the previous weekday.
     *
     * @return static
     */
    public function previousWeekday()
    {
        return $this->nextOrPreviousDay(true, false);
    }

    /**
     * Go forward to the next weekend day.
     *
     * @return static
     */
    public function nextWeekendDay()
    {
        return $this->nextOrPreviousDay(false);
    }

    /**
     * Go backward to the previous weekend day.
     *
     * @return static
     */
    public function previousWeekendDay()
    {
        return $this->nextOrPreviousDay(false, false);
    }

    /**
     * Modify to the previous occurrence of a given modifier such as a day of
     * the week. If no dayOfWeek is provided, modify to the previous occurrence
     * of the current day of the week. Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param string|int|null $modifier
     *
     * @return static
     */
    public function previous($modifier = null)
    {
        if ($modifier === null) {
            $modifier = $this->dayOfWeek;
        }

        return $this->change(
            'last '.(\is_string($modifier) ? $modifier : static::$days[$modifier]),
        );
    }

    /**
     * Modify to the first occurrence of a given day of the week
     * in the current month. If no dayOfWeek is provided, modify to the
     * first day of the current month.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek
     *
     * @return static
     */
    public function firstOfMonth($dayOfWeek = null)
    {
        $date = $this->startOfDay();

        if ($dayOfWeek === null) {
            return $date->day(1);
        }

        return $date->modify('first '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year);
    }

    /**
     * Modify to the last occurrence of a given day of the week
     * in the current month. If no dayOfWeek is provided, modify to the
     * last day of the current month.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek
     *
     * @return static
     */
    public function lastOfMonth($dayOfWeek = null)
    {
        $date = $this->startOfDay();

        if ($dayOfWeek === null) {
            return $date->day($date->daysInMonth);
        }

        return $date->modify('last '.static::$days[$dayOfWeek].' of '.$date->rawFormat('F').' '.$date->year);
    }

    /**
     * Modify to the given occurrence of a given day of the week
     * in the current month. If the calculated occurrence is outside the scope
     * of the current month, then return false and no modifications are made.
     * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int $nth
     * @param int $dayOfWeek
     *
     * @return mixed
     */
    public function nthOfMonth($nth, $dayOfWeek)
    {
        $date = $this->avoidMutation()->firstOfMonth();
        $check = $date->rawFormat('Y-m');
        $date = $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);

        return $date->rawFormat('Y-m') === $check ? $this->modify((string) $date) : false;
    }

    /**
     * Modify to the first occurrence of a given day of the week
     * in the current quarter. If no dayOfWeek is provided, modify to the
     * first day of the current quarter.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function firstOfQuarter($dayOfWeek = null)
    {
        return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER - 2, 1)->firstOfMonth($dayOfWeek);
    }

    /**
     * Modify to the last occurrence of a given day of the week
     * in the current quarter. If no dayOfWeek is provided, modify to the
     * last day of the current quarter.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function lastOfQuarter($dayOfWeek = null)
    {
        return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER, 1)->lastOfMonth($dayOfWeek);
    }

    /**
     * Modify to the given occurrence of a given day of the week
     * in the current quarter. If the calculated occurrence is outside the scope
     * of the current quarter, then return false and no modifications are made.
     * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int $nth
     * @param int $dayOfWeek
     *
     * @return mixed
     */
    public function nthOfQuarter($nth, $dayOfWeek)
    {
        $date = $this->avoidMutation()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
        $lastMonth = $date->month;
        $year = $date->year;
        $date = $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);

        return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify((string) $date);
    }

    /**
     * Modify to the first occurrence of a given day of the week
     * in the current year. If no dayOfWeek is provided, modify to the
     * first day of the current year.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function firstOfYear($dayOfWeek = null)
    {
        return $this->month(1)->firstOfMonth($dayOfWeek);
    }

    /**
     * Modify to the last occurrence of a given day of the week
     * in the current year. If no dayOfWeek is provided, modify to the
     * last day of the current year.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function lastOfYear($dayOfWeek = null)
    {
        return $this->month(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek);
    }

    /**
     * Modify to the given occurrence of a given day of the week
     * in the current year. If the calculated occurrence is outside the scope
     * of the current year, then return false and no modifications are made.
     * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int $nth
     * @param int $dayOfWeek
     *
     * @return mixed
     */
    public function nthOfYear($nth, $dayOfWeek)
    {
        $date = $this->avoidMutation()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);

        return $this->year === $date->year ? $this->modify((string) $date) : false;
    }

    /**
     * Modify the current instance to the average of a given instance (default now) and the current instance
     * (second-precision).
     *
     * @param \Carbon\Carbon|\DateTimeInterface|null $date
     *
     * @return static
     */
    public function average($date = null)
    {
        return $this->addRealMicroseconds((int) ($this->diffInMicroseconds($this->resolveCarbon($date), false) / 2));
    }

    /**
     * Get the closest date from the instance (second-precision).
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
     *
     * @return static
     */
    public function closest($date1, $date2)
    {
        return $this->diffInMicroseconds($date1, true) < $this->diffInMicroseconds($date2, true) ? $date1 : $date2;
    }

    /**
     * Get the farthest date from the instance (second-precision).
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
     *
     * @return static
     */
    public function farthest($date1, $date2)
    {
        return $this->diffInMicroseconds($date1, true) > $this->diffInMicroseconds($date2, true) ? $date1 : $date2;
    }

    /**
     * Get the minimum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @return static
     */
    public function min($date = null)
    {
        $date = $this->resolveCarbon($date);

        return $this->lt($date) ? $this : $date;
    }

    /**
     * Get the minimum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @see min()
     *
     * @return static
     */
    public function minimum($date = null)
    {
        return $this->min($date);
    }

    /**
     * Get the maximum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @return static
     */
    public function max($date = null)
    {
        $date = $this->resolveCarbon($date);

        return $this->gt($date) ? $this : $date;
    }

    /**
     * Get the maximum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @see max()
     *
     * @return static
     */
    public function maximum($date = null)
    {
        return $this->max($date);
    }

    /**
     * Calls \DateTime::modify if mutable or \DateTimeImmutable::modify else.
     *
     * @see https://php.net/manual/en/datetime.modify.php
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public function modify($modify)
    {
        return parent::modify((string) $modify)
            ?: throw new InvalidFormatException('Could not modify with: '.var_export($modify, true));
    }

    /**
     * Similar to native modify() method of DateTime but can handle more grammars.
     *
     * @example
     * ```
     * echo Carbon::now()->change('next 2pm');
     * ```
     *
     * @link https://php.net/manual/en/datetime.modify.php
     *
     * @param string $modifier
     *
     * @return static
     */
    public function change($modifier)
    {
        return $this->modify(preg_replace_callback('/^(next|previous|last)\s+(\d{1,2}(h|am|pm|:\d{1,2}(:\d{1,2})?))$/i', function ($match) {
            $match[2] = str_replace('h', ':00', $match[2]);
            $test = $this->avoidMutation()->modify($match[2]);
            $method = $match[1] === 'next' ? 'lt' : 'gt';
            $match[1] = $test->$method($this) ? $match[1].' day' : 'today';

            return $match[1].' '.$match[2];
        }, strtr(trim($modifier), [
            ' at ' => ' ',
            'just now' => 'now',
            'after tomorrow' => 'tomorrow +1 day',
            'before yesterday' => 'yesterday -1 day',
        ])));
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Traits;

use Carbon\CarbonInterface;
use DateTimeInterface;
use Throwable;

/**
 * Trait Options.
 *
 * Embed base methods to change settings of Carbon classes.
 *
 * Depends on the following methods:
 *
 * @method static shiftTimezone($timezone) Set the timezone
 */
trait Options
{
    use StaticOptions;
    use Localization;

    /**
     * Indicates if months should be calculated with overflow.
     * Specific setting.
     */
    protected ?bool $localMonthsOverflow = null;

    /**
     * Indicates if years should be calculated with overflow.
     * Specific setting.
     */
    protected ?bool $localYearsOverflow = null;

    /**
     * Indicates if the strict mode is in use.
     * Specific setting.
     */
    protected ?bool $localStrictModeEnabled = null;

    /**
     * Options for diffForHumans and forHumans methods.
     */
    protected ?int $localHumanDiffOptions = null;

    /**
     * Format to use on string cast.
     *
     * @var string|callable|null
     */
    protected $localToStringFormat = null;

    /**
     * Format to use on JSON serialization.
     *
     * @var string|callable|null
     */
    protected $localSerializer = null;

    /**
     * Instance-specific macros.
     */
    protected ?array $localMacros = null;

    /**
     * Instance-specific generic macros.
     */
    protected ?array $localGenericMacros = null;

    /**
     * Function to call instead of format.
     *
     * @var string|callable|null
     */
    protected $localFormatFunction = null;

    /**
     * Set specific options.
     *  - strictMode: true|false|null
     *  - monthOverflow: true|false|null
     *  - yearOverflow: true|false|null
     *  - humanDiffOptions: int|null
     *  - toStringFormat: string|Closure|null
     *  - toJsonFormat: string|Closure|null
     *  - locale: string|null
     *  - timezone: \DateTimeZone|string|int|null
     *  - macros: array|null
     *  - genericMacros: array|null
     *
     * @param array $settings
     *
     * @return $this|static
     */
    public function settings(array $settings): static
    {
        $this->localStrictModeEnabled = $settings['strictMode'] ?? null;
        $this->localMonthsOverflow = $settings['monthOverflow'] ?? null;
        $this->localYearsOverflow = $settings['yearOverflow'] ?? null;
        $this->localHumanDiffOptions = $settings['humanDiffOptions'] ?? null;
        $this->localToStringFormat = $settings['toStringFormat'] ?? null;
        $this->localSerializer = $settings['toJsonFormat'] ?? null;
        $this->localMacros = $settings['macros'] ?? null;
        $this->localGenericMacros = $settings['genericMacros'] ?? null;
        $this->localFormatFunction = $settings['formatFunction'] ?? null;

        if (isset($settings['locale'])) {
            $locales = $settings['locale'];

            if (!\is_array($locales)) {
                $locales = [$locales];
            }

            $this->locale(...$locales);
        } elseif (isset($settings['translator']) && property_exists($this, 'localTranslator')) {
            $this->localTranslator = $settings['translator'];
        }

        if (isset($settings['innerTimezone'])) {
            return $this->setTimezone($settings['innerTimezone']);
        }

        if (isset($settings['timezone'])) {
            return $this->shiftTimezone($settings['timezone']);
        }

        return $this;
    }

    /**
     * Returns current local settings.
     */
    public function getSettings(): array
    {
        $settings = [];
        $map = [
            'localStrictModeEnabled' => 'strictMode',
            'localMonthsOverflow' => 'monthOverflow',
            'localYearsOverflow' => 'yearOverflow',
            'localHumanDiffOptions' => 'humanDiffOptions',
            'localToStringFormat' => 'toStringFormat',
            'localSerializer' => 'toJsonFormat',
            'localMacros' => 'macros',
            'localGenericMacros' => 'genericMacros',
            'locale' => 'locale',
            'tzName' => 'timezone',
            'localFormatFunction' => 'formatFunction',
        ];

        foreach ($map as $property => $key) {
            $value = $this->$property ?? null;

            if ($value !== null && ($key !== 'locale' || $value !== 'en' || $this->localTranslator)) {
                $settings[$key] = $value;
            }
        }

        return $settings;
    }

    /**
     * Show truthy properties on var_dump().
     */
    public function __debugInfo(): array
    {
        $infos = array_filter(get_object_vars($this), static function ($var) {
            return $var;
        });

        foreach (['dumpProperties', 'constructedObjectId', 'constructed', 'originalInput'] as $property) {
            if (isset($infos[$property])) {
                unset($infos[$property]);
            }
        }

        $this->addExtraDebugInfos($infos);

        foreach (["\0*\0", ''] as $prefix) {
            $key = $prefix.'carbonRecurrences';

            if (\array_key_exists($key, $infos)) {
                $infos['recurrences'] = $infos[$key];
                unset($infos[$key]);
            }
        }

        return $infos;
    }

    protected function isLocalStrictModeEnabled(): bool
    {
        return $this->localStrictModeEnabled
            ?? $this->transmitFactory(static fn () => static::isStrictModeEnabled());
    }

    protected function addExtraDebugInfos(array &$infos): void
    {
        if ($this instanceof DateTimeInterface) {
            try {
                $infos['date'] ??= $this->format(CarbonInterface::MOCK_DATETIME_FORMAT);
                $infos['timezone'] ??= $this->tzName ?? $this->timezoneSetting ?? $this->timezone ?? null;
            } catch (Throwable) {
                // noop
            }
        }
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Mark translator using strong type from symfony/translation >= 6.
 */
interface TranslatorStrongTypeInterface
{
    public function getFromCatalogue(MessageCatalogueInterface $catalogue, string $id, string $domain = 'messages');
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use JsonSerializable;

class Language implements JsonSerializable
{
    protected static ?array $languagesNames = null;

    protected static ?array $regionsNames = null;

    protected string $id;

    protected string $code;

    protected ?string $variant = null;

    protected ?string $region = null;

    protected ?array $names = null;

    protected ?string $isoName = null;

    protected ?string $nativeName = null;

    public function __construct(string $id)
    {
        $this->id = str_replace('-', '_', $id);
        $parts = explode('_', $this->id);
        $this->code = $parts[0];

        if (isset($parts[1])) {
            if (!preg_match('/^[A-Z]+$/', $parts[1])) {
                $this->variant = $parts[1];
                $parts[1] = $parts[2] ?? null;
            }
            if ($parts[1]) {
                $this->region = $parts[1];
            }
        }
    }

    /**
     * Get the list of the known languages.
     *
     * @return array
     */
    public static function all(): array
    {
        static::$languagesNames ??= require __DIR__.'/List/languages.php';

        return static::$languagesNames;
    }

    /**
     * Get the list of the known regions.
     *
     * ⚠ ISO 3166-2 short name provided with no warranty, should not
     * be used for any purpose to show official state names.
     */
    public static function regions(): array
    {
        static::$regionsNames ??= require __DIR__.'/List/regions.php';

        return static::$regionsNames;
    }

    /**
     * Get both isoName and nativeName as an array.
     */
    public function getNames(): array
    {
        $this->names ??= static::all()[$this->code] ?? [
            'isoName' => $this->code,
            'nativeName' => $this->code,
        ];

        return $this->names;
    }

    /**
     * Returns the original locale ID.
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * Returns the code of the locale "en"/"fr".
     */
    public function getCode(): string
    {
        return $this->code;
    }

    /**
     * Returns the variant code such as cyrl/latn.
     */
    public function getVariant(): ?string
    {
        return $this->variant;
    }

    /**
     * Returns the variant such as Cyrillic/Latin.
     */
    public function getVariantName(): ?string
    {
        if ($this->variant === 'Latn') {
            return 'Latin';
        }

        if ($this->variant === 'Cyrl') {
            return 'Cyrillic';
        }

        return $this->variant;
    }

    /**
     * Returns the region part of the locale.
     */
    public function getRegion(): ?string
    {
        return $this->region;
    }

    /**
     * Returns the region name for the current language.
     *
     * ⚠ ISO 3166-2 short name provided with no warranty, should not
     * be used for any purpose to show official state names.
     */
    public function getRegionName(): ?string
    {
        return $this->region ? (static::regions()[$this->region] ?? $this->region) : null;
    }

    /**
     * Returns the long ISO language name.
     */
    public function getFullIsoName(): string
    {
        $this->isoName ??= $this->getNames()['isoName'];

        return $this->isoName;
    }

    /**
     * Set the ISO language name.
     */
    public function setIsoName(string $isoName): static
    {
        $this->isoName = $isoName;

        return $this;
    }

    /**
     * Return the full name of the language in this language.
     */
    public function getFullNativeName(): string
    {
        $this->nativeName ??= $this->getNames()['nativeName'];

        return $this->nativeName;
    }

    /**
     * Set the name of the language in this language.
     */
    public function setNativeName(string $nativeName): static
    {
        $this->nativeName = $nativeName;

        return $this;
    }

    /**
     * Returns the short ISO language name.
     */
    public function getIsoName(): string
    {
        $name = $this->getFullIsoName();

        return trim(strstr($name, ',', true) ?: $name);
    }

    /**
     * Get the short name of the language in this language.
     */
    public function getNativeName(): string
    {
        $name = $this->getFullNativeName();

        return trim(strstr($name, ',', true) ?: $name);
    }

    /**
     * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
     */
    public function getIsoDescription(): string
    {
        $region = $this->getRegionName();
        $variant = $this->getVariantName();

        return $this->getIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
    }

    /**
     * Get a string with short native name, region in parentheses if applicable, variant in parentheses if applicable.
     */
    public function getNativeDescription(): string
    {
        $region = $this->getRegionName();
        $variant = $this->getVariantName();

        return $this->getNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
    }

    /**
     * Get a string with long ISO name, region in parentheses if applicable, variant in parentheses if applicable.
     */
    public function getFullIsoDescription(): string
    {
        $region = $this->getRegionName();
        $variant = $this->getVariantName();

        return $this->getFullIsoName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
    }

    /**
     * Get a string with long native name, region in parentheses if applicable, variant in parentheses if applicable.
     */
    public function getFullNativeDescription(): string
    {
        $region = $this->getRegionName();
        $variant = $this->getVariantName();

        return $this->getFullNativeName().($region ? ' ('.$region.')' : '').($variant ? ' ('.$variant.')' : '');
    }

    /**
     * Returns the original locale ID.
     */
    public function __toString(): string
    {
        return $this->getId();
    }

    /**
     * Get a string with short ISO name, region in parentheses if applicable, variant in parentheses if applicable.
     */
    public function jsonSerialize(): string
    {
        return $this->getIsoDescription();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Traits\Date;
use DateTime;
use DateTimeInterface;

/**
 * A simple API extension for DateTime.
 *
 * <autodoc generated by `composer phpdoc`>
 *
 * @property      string           $localeDayOfWeek                                                                   the day of week in current locale
 * @property      string           $shortLocaleDayOfWeek                                                              the abbreviated day of week in current locale
 * @property      string           $localeMonth                                                                       the month in current locale
 * @property      string           $shortLocaleMonth                                                                  the abbreviated month in current locale
 * @property      int              $year
 * @property      int              $yearIso
 * @property      int              $month
 * @property      int              $day
 * @property      int              $hour
 * @property      int              $minute
 * @property      int              $second
 * @property      int              $micro
 * @property      int              $microsecond
 * @property      int              $dayOfWeekIso                                                                      1 (for Monday) through 7 (for Sunday)
 * @property      int|float|string $timestamp                                                                         seconds since the Unix Epoch
 * @property      string           $englishDayOfWeek                                                                  the day of week in English
 * @property      string           $shortEnglishDayOfWeek                                                             the abbreviated day of week in English
 * @property      string           $englishMonth                                                                      the month in English
 * @property      string           $shortEnglishMonth                                                                 the abbreviated month in English
 * @property      int              $milliseconds
 * @property      int              $millisecond
 * @property      int              $milli
 * @property      int              $week                                                                              1 through 53
 * @property      int              $isoWeek                                                                           1 through 53
 * @property      int              $weekYear                                                                          year according to week format
 * @property      int              $isoWeekYear                                                                       year according to ISO week format
 * @property      int              $age                                                                               does a diffInYears() with default parameters
 * @property      int              $offset                                                                            the timezone offset in seconds from UTC
 * @property      int              $offsetMinutes                                                                     the timezone offset in minutes from UTC
 * @property      int              $offsetHours                                                                       the timezone offset in hours from UTC
 * @property      CarbonTimeZone   $timezone                                                                          the current timezone
 * @property      CarbonTimeZone   $tz                                                                                alias of $timezone
 * @property      int              $centuryOfMillennium                                                               The value of the century starting from the beginning of the current millennium
 * @property      int              $dayOfCentury                                                                      The value of the day starting from the beginning of the current century
 * @property      int              $dayOfDecade                                                                       The value of the day starting from the beginning of the current decade
 * @property      int              $dayOfMillennium                                                                   The value of the day starting from the beginning of the current millennium
 * @property      int              $dayOfMonth                                                                        The value of the day starting from the beginning of the current month
 * @property      int              $dayOfQuarter                                                                      The value of the day starting from the beginning of the current quarter
 * @property      int              $dayOfWeek                                                                         0 (for Sunday) through 6 (for Saturday)
 * @property      int              $dayOfYear                                                                         1 through 366
 * @property      int              $decadeOfCentury                                                                   The value of the decade starting from the beginning of the current century
 * @property      int              $decadeOfMillennium                                                                The value of the decade starting from the beginning of the current millennium
 * @property      int              $hourOfCentury                                                                     The value of the hour starting from the beginning of the current century
 * @property      int              $hourOfDay                                                                         The value of the hour starting from the beginning of the current day
 * @property      int              $hourOfDecade                                                                      The value of the hour starting from the beginning of the current decade
 * @property      int              $hourOfMillennium                                                                  The value of the hour starting from the beginning of the current millennium
 * @property      int              $hourOfMonth                                                                       The value of the hour starting from the beginning of the current month
 * @property      int              $hourOfQuarter                                                                     The value of the hour starting from the beginning of the current quarter
 * @property      int              $hourOfWeek                                                                        The value of the hour starting from the beginning of the current week
 * @property      int              $hourOfYear                                                                        The value of the hour starting from the beginning of the current year
 * @property      int              $microsecondOfCentury                                                              The value of the microsecond starting from the beginning of the current century
 * @property      int              $microsecondOfDay                                                                  The value of the microsecond starting from the beginning of the current day
 * @property      int              $microsecondOfDecade                                                               The value of the microsecond starting from the beginning of the current decade
 * @property      int              $microsecondOfHour                                                                 The value of the microsecond starting from the beginning of the current hour
 * @property      int              $microsecondOfMillennium                                                           The value of the microsecond starting from the beginning of the current millennium
 * @property      int              $microsecondOfMillisecond                                                          The value of the microsecond starting from the beginning of the current millisecond
 * @property      int              $microsecondOfMinute                                                               The value of the microsecond starting from the beginning of the current minute
 * @property      int              $microsecondOfMonth                                                                The value of the microsecond starting from the beginning of the current month
 * @property      int              $microsecondOfQuarter                                                              The value of the microsecond starting from the beginning of the current quarter
 * @property      int              $microsecondOfSecond                                                               The value of the microsecond starting from the beginning of the current second
 * @property      int              $microsecondOfWeek                                                                 The value of the microsecond starting from the beginning of the current week
 * @property      int              $microsecondOfYear                                                                 The value of the microsecond starting from the beginning of the current year
 * @property      int              $millisecondOfCentury                                                              The value of the millisecond starting from the beginning of the current century
 * @property      int              $millisecondOfDay                                                                  The value of the millisecond starting from the beginning of the current day
 * @property      int              $millisecondOfDecade                                                               The value of the millisecond starting from the beginning of the current decade
 * @property      int              $millisecondOfHour                                                                 The value of the millisecond starting from the beginning of the current hour
 * @property      int              $millisecondOfMillennium                                                           The value of the millisecond starting from the beginning of the current millennium
 * @property      int              $millisecondOfMinute                                                               The value of the millisecond starting from the beginning of the current minute
 * @property      int              $millisecondOfMonth                                                                The value of the millisecond starting from the beginning of the current month
 * @property      int              $millisecondOfQuarter                                                              The value of the millisecond starting from the beginning of the current quarter
 * @property      int              $millisecondOfSecond                                                               The value of the millisecond starting from the beginning of the current second
 * @property      int              $millisecondOfWeek                                                                 The value of the millisecond starting from the beginning of the current week
 * @property      int              $millisecondOfYear                                                                 The value of the millisecond starting from the beginning of the current year
 * @property      int              $minuteOfCentury                                                                   The value of the minute starting from the beginning of the current century
 * @property      int              $minuteOfDay                                                                       The value of the minute starting from the beginning of the current day
 * @property      int              $minuteOfDecade                                                                    The value of the minute starting from the beginning of the current decade
 * @property      int              $minuteOfHour                                                                      The value of the minute starting from the beginning of the current hour
 * @property      int              $minuteOfMillennium                                                                The value of the minute starting from the beginning of the current millennium
 * @property      int              $minuteOfMonth                                                                     The value of the minute starting from the beginning of the current month
 * @property      int              $minuteOfQuarter                                                                   The value of the minute starting from the beginning of the current quarter
 * @property      int              $minuteOfWeek                                                                      The value of the minute starting from the beginning of the current week
 * @property      int              $minuteOfYear                                                                      The value of the minute starting from the beginning of the current year
 * @property      int              $monthOfCentury                                                                    The value of the month starting from the beginning of the current century
 * @property      int              $monthOfDecade                                                                     The value of the month starting from the beginning of the current decade
 * @property      int              $monthOfMillennium                                                                 The value of the month starting from the beginning of the current millennium
 * @property      int              $monthOfQuarter                                                                    The value of the month starting from the beginning of the current quarter
 * @property      int              $monthOfYear                                                                       The value of the month starting from the beginning of the current year
 * @property      int              $quarterOfCentury                                                                  The value of the quarter starting from the beginning of the current century
 * @property      int              $quarterOfDecade                                                                   The value of the quarter starting from the beginning of the current decade
 * @property      int              $quarterOfMillennium                                                               The value of the quarter starting from the beginning of the current millennium
 * @property      int              $quarterOfYear                                                                     The value of the quarter starting from the beginning of the current year
 * @property      int              $secondOfCentury                                                                   The value of the second starting from the beginning of the current century
 * @property      int              $secondOfDay                                                                       The value of the second starting from the beginning of the current day
 * @property      int              $secondOfDecade                                                                    The value of the second starting from the beginning of the current decade
 * @property      int              $secondOfHour                                                                      The value of the second starting from the beginning of the current hour
 * @property      int              $secondOfMillennium                                                                The value of the second starting from the beginning of the current millennium
 * @property      int              $secondOfMinute                                                                    The value of the second starting from the beginning of the current minute
 * @property      int              $secondOfMonth                                                                     The value of the second starting from the beginning of the current month
 * @property      int              $secondOfQuarter                                                                   The value of the second starting from the beginning of the current quarter
 * @property      int              $secondOfWeek                                                                      The value of the second starting from the beginning of the current week
 * @property      int              $secondOfYear                                                                      The value of the second starting from the beginning of the current year
 * @property      int              $weekOfCentury                                                                     The value of the week starting from the beginning of the current century
 * @property      int              $weekOfDecade                                                                      The value of the week starting from the beginning of the current decade
 * @property      int              $weekOfMillennium                                                                  The value of the week starting from the beginning of the current millennium
 * @property      int              $weekOfMonth                                                                       1 through 5
 * @property      int              $weekOfQuarter                                                                     The value of the week starting from the beginning of the current quarter
 * @property      int              $weekOfYear                                                                        ISO-8601 week number of year, weeks starting on Monday
 * @property      int              $yearOfCentury                                                                     The value of the year starting from the beginning of the current century
 * @property      int              $yearOfDecade                                                                      The value of the year starting from the beginning of the current decade
 * @property      int              $yearOfMillennium                                                                  The value of the year starting from the beginning of the current millennium
 * @property-read string           $latinMeridiem                                                                     "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
 * @property-read string           $latinUpperMeridiem                                                                "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
 * @property-read string           $timezoneAbbreviatedName                                                           the current timezone abbreviated name
 * @property-read string           $tzAbbrName                                                                        alias of $timezoneAbbreviatedName
 * @property-read string           $dayName                                                                           long name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortDayName                                                                      short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $minDayName                                                                        very short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $monthName                                                                         long name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortMonthName                                                                    short name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $meridiem                                                                          lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read string           $upperMeridiem                                                                     uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read int              $noZeroHour                                                                        current hour from 1 to 24
 * @property-read int              $isoWeeksInYear                                                                    51 through 53
 * @property-read int              $weekNumberInMonth                                                                 1 through 5
 * @property-read int              $firstWeekDay                                                                      0 through 6
 * @property-read int              $lastWeekDay                                                                       0 through 6
 * @property-read int              $quarter                                                                           the quarter of this instance, 1 - 4
 * @property-read int              $decade                                                                            the decade of this instance
 * @property-read int              $century                                                                           the century of this instance
 * @property-read int              $millennium                                                                        the millennium of this instance
 * @property-read bool             $dst                                                                               daylight savings time indicator, true if DST, false otherwise
 * @property-read bool             $local                                                                             checks if the timezone is local, true if local, false otherwise
 * @property-read bool             $utc                                                                               checks if the timezone is UTC, true if UTC, false otherwise
 * @property-read string           $timezoneName                                                                      the current timezone name
 * @property-read string           $tzName                                                                            alias of $timezoneName
 * @property-read string           $locale                                                                            locale of the current instance
 * @property-read int              $centuriesInMillennium                                                             The number of centuries contained in the current millennium
 * @property-read int              $daysInCentury                                                                     The number of days contained in the current century
 * @property-read int              $daysInDecade                                                                      The number of days contained in the current decade
 * @property-read int              $daysInMillennium                                                                  The number of days contained in the current millennium
 * @property-read int              $daysInMonth                                                                       number of days in the given month
 * @property-read int              $daysInQuarter                                                                     The number of days contained in the current quarter
 * @property-read int              $daysInWeek                                                                        The number of days contained in the current week
 * @property-read int              $daysInYear                                                                        365 or 366
 * @property-read int              $decadesInCentury                                                                  The number of decades contained in the current century
 * @property-read int              $decadesInMillennium                                                               The number of decades contained in the current millennium
 * @property-read int              $hoursInCentury                                                                    The number of hours contained in the current century
 * @property-read int              $hoursInDay                                                                        The number of hours contained in the current day
 * @property-read int              $hoursInDecade                                                                     The number of hours contained in the current decade
 * @property-read int              $hoursInMillennium                                                                 The number of hours contained in the current millennium
 * @property-read int              $hoursInMonth                                                                      The number of hours contained in the current month
 * @property-read int              $hoursInQuarter                                                                    The number of hours contained in the current quarter
 * @property-read int              $hoursInWeek                                                                       The number of hours contained in the current week
 * @property-read int              $hoursInYear                                                                       The number of hours contained in the current year
 * @property-read int              $microsecondsInCentury                                                             The number of microseconds contained in the current century
 * @property-read int              $microsecondsInDay                                                                 The number of microseconds contained in the current day
 * @property-read int              $microsecondsInDecade                                                              The number of microseconds contained in the current decade
 * @property-read int              $microsecondsInHour                                                                The number of microseconds contained in the current hour
 * @property-read int              $microsecondsInMillennium                                                          The number of microseconds contained in the current millennium
 * @property-read int              $microsecondsInMillisecond                                                         The number of microseconds contained in the current millisecond
 * @property-read int              $microsecondsInMinute                                                              The number of microseconds contained in the current minute
 * @property-read int              $microsecondsInMonth                                                               The number of microseconds contained in the current month
 * @property-read int              $microsecondsInQuarter                                                             The number of microseconds contained in the current quarter
 * @property-read int              $microsecondsInSecond                                                              The number of microseconds contained in the current second
 * @property-read int              $microsecondsInWeek                                                                The number of microseconds contained in the current week
 * @property-read int              $microsecondsInYear                                                                The number of microseconds contained in the current year
 * @property-read int              $millisecondsInCentury                                                             The number of milliseconds contained in the current century
 * @property-read int              $millisecondsInDay                                                                 The number of milliseconds contained in the current day
 * @property-read int              $millisecondsInDecade                                                              The number of milliseconds contained in the current decade
 * @property-read int              $millisecondsInHour                                                                The number of milliseconds contained in the current hour
 * @property-read int              $millisecondsInMillennium                                                          The number of milliseconds contained in the current millennium
 * @property-read int              $millisecondsInMinute                                                              The number of milliseconds contained in the current minute
 * @property-read int              $millisecondsInMonth                                                               The number of milliseconds contained in the current month
 * @property-read int              $millisecondsInQuarter                                                             The number of milliseconds contained in the current quarter
 * @property-read int              $millisecondsInSecond                                                              The number of milliseconds contained in the current second
 * @property-read int              $millisecondsInWeek                                                                The number of milliseconds contained in the current week
 * @property-read int              $millisecondsInYear                                                                The number of milliseconds contained in the current year
 * @property-read int              $minutesInCentury                                                                  The number of minutes contained in the current century
 * @property-read int              $minutesInDay                                                                      The number of minutes contained in the current day
 * @property-read int              $minutesInDecade                                                                   The number of minutes contained in the current decade
 * @property-read int              $minutesInHour                                                                     The number of minutes contained in the current hour
 * @property-read int              $minutesInMillennium                                                               The number of minutes contained in the current millennium
 * @property-read int              $minutesInMonth                                                                    The number of minutes contained in the current month
 * @property-read int              $minutesInQuarter                                                                  The number of minutes contained in the current quarter
 * @property-read int              $minutesInWeek                                                                     The number of minutes contained in the current week
 * @property-read int              $minutesInYear                                                                     The number of minutes contained in the current year
 * @property-read int              $monthsInCentury                                                                   The number of months contained in the current century
 * @property-read int              $monthsInDecade                                                                    The number of months contained in the current decade
 * @property-read int              $monthsInMillennium                                                                The number of months contained in the current millennium
 * @property-read int              $monthsInQuarter                                                                   The number of months contained in the current quarter
 * @property-read int              $monthsInYear                                                                      The number of months contained in the current year
 * @property-read int              $quartersInCentury                                                                 The number of quarters contained in the current century
 * @property-read int              $quartersInDecade                                                                  The number of quarters contained in the current decade
 * @property-read int              $quartersInMillennium                                                              The number of quarters contained in the current millennium
 * @property-read int              $quartersInYear                                                                    The number of quarters contained in the current year
 * @property-read int              $secondsInCentury                                                                  The number of seconds contained in the current century
 * @property-read int              $secondsInDay                                                                      The number of seconds contained in the current day
 * @property-read int              $secondsInDecade                                                                   The number of seconds contained in the current decade
 * @property-read int              $secondsInHour                                                                     The number of seconds contained in the current hour
 * @property-read int              $secondsInMillennium                                                               The number of seconds contained in the current millennium
 * @property-read int              $secondsInMinute                                                                   The number of seconds contained in the current minute
 * @property-read int              $secondsInMonth                                                                    The number of seconds contained in the current month
 * @property-read int              $secondsInQuarter                                                                  The number of seconds contained in the current quarter
 * @property-read int              $secondsInWeek                                                                     The number of seconds contained in the current week
 * @property-read int              $secondsInYear                                                                     The number of seconds contained in the current year
 * @property-read int              $weeksInCentury                                                                    The number of weeks contained in the current century
 * @property-read int              $weeksInDecade                                                                     The number of weeks contained in the current decade
 * @property-read int              $weeksInMillennium                                                                 The number of weeks contained in the current millennium
 * @property-read int              $weeksInMonth                                                                      The number of weeks contained in the current month
 * @property-read int              $weeksInQuarter                                                                    The number of weeks contained in the current quarter
 * @property-read int              $weeksInYear                                                                       51 through 53
 * @property-read int              $yearsInCentury                                                                    The number of years contained in the current century
 * @property-read int              $yearsInDecade                                                                     The number of years contained in the current decade
 * @property-read int              $yearsInMillennium                                                                 The number of years contained in the current millennium
 *
 * @method        bool             isUtc()                                                                            Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
 * @method        bool             isLocal()                                                                          Check if the current instance has non-UTC timezone.
 * @method        bool             isValid()                                                                          Check if the current instance is a valid date.
 * @method        bool             isDST()                                                                            Check if the current instance is in a daylight saving time.
 * @method        bool             isSunday()                                                                         Checks if the instance day is sunday.
 * @method        bool             isMonday()                                                                         Checks if the instance day is monday.
 * @method        bool             isTuesday()                                                                        Checks if the instance day is tuesday.
 * @method        bool             isWednesday()                                                                      Checks if the instance day is wednesday.
 * @method        bool             isThursday()                                                                       Checks if the instance day is thursday.
 * @method        bool             isFriday()                                                                         Checks if the instance day is friday.
 * @method        bool             isSaturday()                                                                       Checks if the instance day is saturday.
 * @method        bool             isSameYear(DateTimeInterface|string $date)                                         Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentYear()                                                                    Checks if the instance is in the same year as the current moment.
 * @method        bool             isNextYear()                                                                       Checks if the instance is in the same year as the current moment next year.
 * @method        bool             isLastYear()                                                                       Checks if the instance is in the same year as the current moment last year.
 * @method        bool             isCurrentMonth()                                                                   Checks if the instance is in the same month as the current moment.
 * @method        bool             isNextMonth()                                                                      Checks if the instance is in the same month as the current moment next month.
 * @method        bool             isLastMonth()                                                                      Checks if the instance is in the same month as the current moment last month.
 * @method        bool             isSameWeek(DateTimeInterface|string $date)                                         Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentWeek()                                                                    Checks if the instance is in the same week as the current moment.
 * @method        bool             isNextWeek()                                                                       Checks if the instance is in the same week as the current moment next week.
 * @method        bool             isLastWeek()                                                                       Checks if the instance is in the same week as the current moment last week.
 * @method        bool             isSameDay(DateTimeInterface|string $date)                                          Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDay()                                                                     Checks if the instance is in the same day as the current moment.
 * @method        bool             isNextDay()                                                                        Checks if the instance is in the same day as the current moment next day.
 * @method        bool             isLastDay()                                                                        Checks if the instance is in the same day as the current moment last day.
 * @method        bool             isSameHour(DateTimeInterface|string $date)                                         Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentHour()                                                                    Checks if the instance is in the same hour as the current moment.
 * @method        bool             isNextHour()                                                                       Checks if the instance is in the same hour as the current moment next hour.
 * @method        bool             isLastHour()                                                                       Checks if the instance is in the same hour as the current moment last hour.
 * @method        bool             isSameMinute(DateTimeInterface|string $date)                                       Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMinute()                                                                  Checks if the instance is in the same minute as the current moment.
 * @method        bool             isNextMinute()                                                                     Checks if the instance is in the same minute as the current moment next minute.
 * @method        bool             isLastMinute()                                                                     Checks if the instance is in the same minute as the current moment last minute.
 * @method        bool             isSameSecond(DateTimeInterface|string $date)                                       Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentSecond()                                                                  Checks if the instance is in the same second as the current moment.
 * @method        bool             isNextSecond()                                                                     Checks if the instance is in the same second as the current moment next second.
 * @method        bool             isLastSecond()                                                                     Checks if the instance is in the same second as the current moment last second.
 * @method        bool             isSameMilli(DateTimeInterface|string $date)                                        Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMilli()                                                                   Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMilli()                                                                      Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMilli()                                                                      Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMillisecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillisecond()                                                             Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMicro(DateTimeInterface|string $date)                                        Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicro()                                                                   Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicro()                                                                      Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicro()                                                                      Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameMicrosecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicrosecond()                                                             Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameDecade(DateTimeInterface|string $date)                                       Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDecade()                                                                  Checks if the instance is in the same decade as the current moment.
 * @method        bool             isNextDecade()                                                                     Checks if the instance is in the same decade as the current moment next decade.
 * @method        bool             isLastDecade()                                                                     Checks if the instance is in the same decade as the current moment last decade.
 * @method        bool             isSameCentury(DateTimeInterface|string $date)                                      Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentCentury()                                                                 Checks if the instance is in the same century as the current moment.
 * @method        bool             isNextCentury()                                                                    Checks if the instance is in the same century as the current moment next century.
 * @method        bool             isLastCentury()                                                                    Checks if the instance is in the same century as the current moment last century.
 * @method        bool             isSameMillennium(DateTimeInterface|string $date)                                   Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillennium()                                                              Checks if the instance is in the same millennium as the current moment.
 * @method        bool             isNextMillennium()                                                                 Checks if the instance is in the same millennium as the current moment next millennium.
 * @method        bool             isLastMillennium()                                                                 Checks if the instance is in the same millennium as the current moment last millennium.
 * @method        bool             isCurrentQuarter()                                                                 Checks if the instance is in the same quarter as the current moment.
 * @method        bool             isNextQuarter()                                                                    Checks if the instance is in the same quarter as the current moment next quarter.
 * @method        bool             isLastQuarter()                                                                    Checks if the instance is in the same quarter as the current moment last quarter.
 * @method        $this            years(int $value)                                                                  Set current instance year to the given value.
 * @method        $this            year(int $value)                                                                   Set current instance year to the given value.
 * @method        $this            setYears(int $value)                                                               Set current instance year to the given value.
 * @method        $this            setYear(int $value)                                                                Set current instance year to the given value.
 * @method        $this            months(Month|int $value)                                                           Set current instance month to the given value.
 * @method        $this            month(Month|int $value)                                                            Set current instance month to the given value.
 * @method        $this            setMonths(Month|int $value)                                                        Set current instance month to the given value.
 * @method        $this            setMonth(Month|int $value)                                                         Set current instance month to the given value.
 * @method        $this            days(int $value)                                                                   Set current instance day to the given value.
 * @method        $this            day(int $value)                                                                    Set current instance day to the given value.
 * @method        $this            setDays(int $value)                                                                Set current instance day to the given value.
 * @method        $this            setDay(int $value)                                                                 Set current instance day to the given value.
 * @method        $this            hours(int $value)                                                                  Set current instance hour to the given value.
 * @method        $this            hour(int $value)                                                                   Set current instance hour to the given value.
 * @method        $this            setHours(int $value)                                                               Set current instance hour to the given value.
 * @method        $this            setHour(int $value)                                                                Set current instance hour to the given value.
 * @method        $this            minutes(int $value)                                                                Set current instance minute to the given value.
 * @method        $this            minute(int $value)                                                                 Set current instance minute to the given value.
 * @method        $this            setMinutes(int $value)                                                             Set current instance minute to the given value.
 * @method        $this            setMinute(int $value)                                                              Set current instance minute to the given value.
 * @method        $this            seconds(int $value)                                                                Set current instance second to the given value.
 * @method        $this            second(int $value)                                                                 Set current instance second to the given value.
 * @method        $this            setSeconds(int $value)                                                             Set current instance second to the given value.
 * @method        $this            setSecond(int $value)                                                              Set current instance second to the given value.
 * @method        $this            millis(int $value)                                                                 Set current instance millisecond to the given value.
 * @method        $this            milli(int $value)                                                                  Set current instance millisecond to the given value.
 * @method        $this            setMillis(int $value)                                                              Set current instance millisecond to the given value.
 * @method        $this            setMilli(int $value)                                                               Set current instance millisecond to the given value.
 * @method        $this            milliseconds(int $value)                                                           Set current instance millisecond to the given value.
 * @method        $this            millisecond(int $value)                                                            Set current instance millisecond to the given value.
 * @method        $this            setMilliseconds(int $value)                                                        Set current instance millisecond to the given value.
 * @method        $this            setMillisecond(int $value)                                                         Set current instance millisecond to the given value.
 * @method        $this            micros(int $value)                                                                 Set current instance microsecond to the given value.
 * @method        $this            micro(int $value)                                                                  Set current instance microsecond to the given value.
 * @method        $this            setMicros(int $value)                                                              Set current instance microsecond to the given value.
 * @method        $this            setMicro(int $value)                                                               Set current instance microsecond to the given value.
 * @method        $this            microseconds(int $value)                                                           Set current instance microsecond to the given value.
 * @method        $this            microsecond(int $value)                                                            Set current instance microsecond to the given value.
 * @method        $this            setMicroseconds(int $value)                                                        Set current instance microsecond to the given value.
 * @method        self             setMicrosecond(int $value)                                                         Set current instance microsecond to the given value.
 * @method        $this            addYears(int|float $value = 1)                                                     Add years (the $value count passed in) to the instance (using date interval).
 * @method        $this            addYear()                                                                          Add one year to the instance (using date interval).
 * @method        $this            subYears(int|float $value = 1)                                                     Sub years (the $value count passed in) to the instance (using date interval).
 * @method        $this            subYear()                                                                          Sub one year to the instance (using date interval).
 * @method        $this            addYearsWithOverflow(int|float $value = 1)                                         Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addYearWithOverflow()                                                              Add one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subYearsWithOverflow(int|float $value = 1)                                         Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subYearWithOverflow()                                                              Sub one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addYearsWithoutOverflow(int|float $value = 1)                                      Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addYearWithoutOverflow()                                                           Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subYearsWithoutOverflow(int|float $value = 1)                                      Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subYearWithoutOverflow()                                                           Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addYearsWithNoOverflow(int|float $value = 1)                                       Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addYearWithNoOverflow()                                                            Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subYearsWithNoOverflow(int|float $value = 1)                                       Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subYearWithNoOverflow()                                                            Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addYearsNoOverflow(int|float $value = 1)                                           Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addYearNoOverflow()                                                                Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subYearsNoOverflow(int|float $value = 1)                                           Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subYearNoOverflow()                                                                Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMonths(int|float $value = 1)                                                    Add months (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMonth()                                                                         Add one month to the instance (using date interval).
 * @method        $this            subMonths(int|float $value = 1)                                                    Sub months (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMonth()                                                                         Sub one month to the instance (using date interval).
 * @method        $this            addMonthsWithOverflow(int|float $value = 1)                                        Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addMonthWithOverflow()                                                             Add one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subMonthsWithOverflow(int|float $value = 1)                                        Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subMonthWithOverflow()                                                             Sub one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addMonthsWithoutOverflow(int|float $value = 1)                                     Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMonthWithoutOverflow()                                                          Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMonthsWithoutOverflow(int|float $value = 1)                                     Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMonthWithoutOverflow()                                                          Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMonthsWithNoOverflow(int|float $value = 1)                                      Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMonthWithNoOverflow()                                                           Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMonthsWithNoOverflow(int|float $value = 1)                                      Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMonthWithNoOverflow()                                                           Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMonthsNoOverflow(int|float $value = 1)                                          Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMonthNoOverflow()                                                               Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMonthsNoOverflow(int|float $value = 1)                                          Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMonthNoOverflow()                                                               Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDays(int|float $value = 1)                                                      Add days (the $value count passed in) to the instance (using date interval).
 * @method        $this            addDay()                                                                           Add one day to the instance (using date interval).
 * @method        $this            subDays(int|float $value = 1)                                                      Sub days (the $value count passed in) to the instance (using date interval).
 * @method        $this            subDay()                                                                           Sub one day to the instance (using date interval).
 * @method        $this            addHours(int|float $value = 1)                                                     Add hours (the $value count passed in) to the instance (using date interval).
 * @method        $this            addHour()                                                                          Add one hour to the instance (using date interval).
 * @method        $this            subHours(int|float $value = 1)                                                     Sub hours (the $value count passed in) to the instance (using date interval).
 * @method        $this            subHour()                                                                          Sub one hour to the instance (using date interval).
 * @method        $this            addMinutes(int|float $value = 1)                                                   Add minutes (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMinute()                                                                        Add one minute to the instance (using date interval).
 * @method        $this            subMinutes(int|float $value = 1)                                                   Sub minutes (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMinute()                                                                        Sub one minute to the instance (using date interval).
 * @method        $this            addSeconds(int|float $value = 1)                                                   Add seconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            addSecond()                                                                        Add one second to the instance (using date interval).
 * @method        $this            subSeconds(int|float $value = 1)                                                   Sub seconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            subSecond()                                                                        Sub one second to the instance (using date interval).
 * @method        $this            addMillis(int|float $value = 1)                                                    Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMilli()                                                                         Add one millisecond to the instance (using date interval).
 * @method        $this            subMillis(int|float $value = 1)                                                    Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMilli()                                                                         Sub one millisecond to the instance (using date interval).
 * @method        $this            addMilliseconds(int|float $value = 1)                                              Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMillisecond()                                                                   Add one millisecond to the instance (using date interval).
 * @method        $this            subMilliseconds(int|float $value = 1)                                              Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMillisecond()                                                                   Sub one millisecond to the instance (using date interval).
 * @method        $this            addMicros(int|float $value = 1)                                                    Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMicro()                                                                         Add one microsecond to the instance (using date interval).
 * @method        $this            subMicros(int|float $value = 1)                                                    Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMicro()                                                                         Sub one microsecond to the instance (using date interval).
 * @method        $this            addMicroseconds(int|float $value = 1)                                              Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMicrosecond()                                                                   Add one microsecond to the instance (using date interval).
 * @method        $this            subMicroseconds(int|float $value = 1)                                              Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMicrosecond()                                                                   Sub one microsecond to the instance (using date interval).
 * @method        $this            addMillennia(int|float $value = 1)                                                 Add millennia (the $value count passed in) to the instance (using date interval).
 * @method        $this            addMillennium()                                                                    Add one millennium to the instance (using date interval).
 * @method        $this            subMillennia(int|float $value = 1)                                                 Sub millennia (the $value count passed in) to the instance (using date interval).
 * @method        $this            subMillennium()                                                                    Sub one millennium to the instance (using date interval).
 * @method        $this            addMillenniaWithOverflow(int|float $value = 1)                                     Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addMillenniumWithOverflow()                                                        Add one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subMillenniaWithOverflow(int|float $value = 1)                                     Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subMillenniumWithOverflow()                                                        Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addMillenniaWithoutOverflow(int|float $value = 1)                                  Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMillenniumWithoutOverflow()                                                     Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMillenniaWithoutOverflow(int|float $value = 1)                                  Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMillenniumWithoutOverflow()                                                     Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMillenniaWithNoOverflow(int|float $value = 1)                                   Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMillenniumWithNoOverflow()                                                      Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMillenniaWithNoOverflow(int|float $value = 1)                                   Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMillenniumWithNoOverflow()                                                      Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMillenniaNoOverflow(int|float $value = 1)                                       Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addMillenniumNoOverflow()                                                          Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMillenniaNoOverflow(int|float $value = 1)                                       Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subMillenniumNoOverflow()                                                          Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addCenturies(int|float $value = 1)                                                 Add centuries (the $value count passed in) to the instance (using date interval).
 * @method        $this            addCentury()                                                                       Add one century to the instance (using date interval).
 * @method        $this            subCenturies(int|float $value = 1)                                                 Sub centuries (the $value count passed in) to the instance (using date interval).
 * @method        $this            subCentury()                                                                       Sub one century to the instance (using date interval).
 * @method        $this            addCenturiesWithOverflow(int|float $value = 1)                                     Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addCenturyWithOverflow()                                                           Add one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subCenturiesWithOverflow(int|float $value = 1)                                     Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subCenturyWithOverflow()                                                           Sub one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addCenturiesWithoutOverflow(int|float $value = 1)                                  Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addCenturyWithoutOverflow()                                                        Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subCenturiesWithoutOverflow(int|float $value = 1)                                  Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subCenturyWithoutOverflow()                                                        Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addCenturiesWithNoOverflow(int|float $value = 1)                                   Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addCenturyWithNoOverflow()                                                         Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subCenturiesWithNoOverflow(int|float $value = 1)                                   Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subCenturyWithNoOverflow()                                                         Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addCenturiesNoOverflow(int|float $value = 1)                                       Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addCenturyNoOverflow()                                                             Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subCenturiesNoOverflow(int|float $value = 1)                                       Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subCenturyNoOverflow()                                                             Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDecades(int|float $value = 1)                                                   Add decades (the $value count passed in) to the instance (using date interval).
 * @method        $this            addDecade()                                                                        Add one decade to the instance (using date interval).
 * @method        $this            subDecades(int|float $value = 1)                                                   Sub decades (the $value count passed in) to the instance (using date interval).
 * @method        $this            subDecade()                                                                        Sub one decade to the instance (using date interval).
 * @method        $this            addDecadesWithOverflow(int|float $value = 1)                                       Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addDecadeWithOverflow()                                                            Add one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subDecadesWithOverflow(int|float $value = 1)                                       Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subDecadeWithOverflow()                                                            Sub one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addDecadesWithoutOverflow(int|float $value = 1)                                    Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDecadeWithoutOverflow()                                                         Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subDecadesWithoutOverflow(int|float $value = 1)                                    Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subDecadeWithoutOverflow()                                                         Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDecadesWithNoOverflow(int|float $value = 1)                                     Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDecadeWithNoOverflow()                                                          Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subDecadesWithNoOverflow(int|float $value = 1)                                     Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subDecadeWithNoOverflow()                                                          Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDecadesNoOverflow(int|float $value = 1)                                         Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addDecadeNoOverflow()                                                              Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subDecadesNoOverflow(int|float $value = 1)                                         Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subDecadeNoOverflow()                                                              Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addQuarters(int|float $value = 1)                                                  Add quarters (the $value count passed in) to the instance (using date interval).
 * @method        $this            addQuarter()                                                                       Add one quarter to the instance (using date interval).
 * @method        $this            subQuarters(int|float $value = 1)                                                  Sub quarters (the $value count passed in) to the instance (using date interval).
 * @method        $this            subQuarter()                                                                       Sub one quarter to the instance (using date interval).
 * @method        $this            addQuartersWithOverflow(int|float $value = 1)                                      Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addQuarterWithOverflow()                                                           Add one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subQuartersWithOverflow(int|float $value = 1)                                      Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            subQuarterWithOverflow()                                                           Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        $this            addQuartersWithoutOverflow(int|float $value = 1)                                   Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addQuarterWithoutOverflow()                                                        Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subQuartersWithoutOverflow(int|float $value = 1)                                   Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subQuarterWithoutOverflow()                                                        Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addQuartersWithNoOverflow(int|float $value = 1)                                    Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addQuarterWithNoOverflow()                                                         Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subQuartersWithNoOverflow(int|float $value = 1)                                    Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subQuarterWithNoOverflow()                                                         Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addQuartersNoOverflow(int|float $value = 1)                                        Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addQuarterNoOverflow()                                                             Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subQuartersNoOverflow(int|float $value = 1)                                        Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            subQuarterNoOverflow()                                                             Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        $this            addWeeks(int|float $value = 1)                                                     Add weeks (the $value count passed in) to the instance (using date interval).
 * @method        $this            addWeek()                                                                          Add one week to the instance (using date interval).
 * @method        $this            subWeeks(int|float $value = 1)                                                     Sub weeks (the $value count passed in) to the instance (using date interval).
 * @method        $this            subWeek()                                                                          Sub one week to the instance (using date interval).
 * @method        $this            addWeekdays(int|float $value = 1)                                                  Add weekdays (the $value count passed in) to the instance (using date interval).
 * @method        $this            addWeekday()                                                                       Add one weekday to the instance (using date interval).
 * @method        $this            subWeekdays(int|float $value = 1)                                                  Sub weekdays (the $value count passed in) to the instance (using date interval).
 * @method        $this            subWeekday()                                                                       Sub one weekday to the instance (using date interval).
 * @method        $this            addUTCMicros(int|float $value = 1)                                                 Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMicro()                                                                      Add one microsecond to the instance (using timestamp).
 * @method        $this            subUTCMicros(int|float $value = 1)                                                 Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMicro()                                                                      Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicros(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        $this            addUTCMicroseconds(int|float $value = 1)                                           Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMicrosecond()                                                                Add one microsecond to the instance (using timestamp).
 * @method        $this            subUTCMicroseconds(int|float $value = 1)                                           Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMicrosecond()                                                                Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicroseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        $this            addUTCMillis(int|float $value = 1)                                                 Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMilli()                                                                      Add one millisecond to the instance (using timestamp).
 * @method        $this            subUTCMillis(int|float $value = 1)                                                 Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMilli()                                                                      Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMillis(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        $this            addUTCMilliseconds(int|float $value = 1)                                           Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMillisecond()                                                                Add one millisecond to the instance (using timestamp).
 * @method        $this            subUTCMilliseconds(int|float $value = 1)                                           Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMillisecond()                                                                Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMilliseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        $this            addUTCSeconds(int|float $value = 1)                                                Add seconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCSecond()                                                                     Add one second to the instance (using timestamp).
 * @method        $this            subUTCSeconds(int|float $value = 1)                                                Sub seconds (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCSecond()                                                                     Sub one second to the instance (using timestamp).
 * @method        CarbonPeriod     secondsUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
 * @method        float            diffInUTCSeconds(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of seconds.
 * @method        $this            addUTCMinutes(int|float $value = 1)                                                Add minutes (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMinute()                                                                     Add one minute to the instance (using timestamp).
 * @method        $this            subUTCMinutes(int|float $value = 1)                                                Sub minutes (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMinute()                                                                     Sub one minute to the instance (using timestamp).
 * @method        CarbonPeriod     minutesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
 * @method        float            diffInUTCMinutes(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of minutes.
 * @method        $this            addUTCHours(int|float $value = 1)                                                  Add hours (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCHour()                                                                       Add one hour to the instance (using timestamp).
 * @method        $this            subUTCHours(int|float $value = 1)                                                  Sub hours (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCHour()                                                                       Sub one hour to the instance (using timestamp).
 * @method        CarbonPeriod     hoursUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
 * @method        float            diffInUTCHours(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of hours.
 * @method        $this            addUTCDays(int|float $value = 1)                                                   Add days (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCDay()                                                                        Add one day to the instance (using timestamp).
 * @method        $this            subUTCDays(int|float $value = 1)                                                   Sub days (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCDay()                                                                        Sub one day to the instance (using timestamp).
 * @method        CarbonPeriod     daysUntil($endDate = null, int|float $factor = 1)                                  Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
 * @method        float            diffInUTCDays(DateTimeInterface|string|null $date, bool $absolute = false)         Convert current and given date in UTC timezone and return a floating number of days.
 * @method        $this            addUTCWeeks(int|float $value = 1)                                                  Add weeks (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCWeek()                                                                       Add one week to the instance (using timestamp).
 * @method        $this            subUTCWeeks(int|float $value = 1)                                                  Sub weeks (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCWeek()                                                                       Sub one week to the instance (using timestamp).
 * @method        CarbonPeriod     weeksUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
 * @method        float            diffInUTCWeeks(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of weeks.
 * @method        $this            addUTCMonths(int|float $value = 1)                                                 Add months (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMonth()                                                                      Add one month to the instance (using timestamp).
 * @method        $this            subUTCMonths(int|float $value = 1)                                                 Sub months (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMonth()                                                                      Sub one month to the instance (using timestamp).
 * @method        CarbonPeriod     monthsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
 * @method        float            diffInUTCMonths(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of months.
 * @method        $this            addUTCQuarters(int|float $value = 1)                                               Add quarters (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCQuarter()                                                                    Add one quarter to the instance (using timestamp).
 * @method        $this            subUTCQuarters(int|float $value = 1)                                               Sub quarters (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCQuarter()                                                                    Sub one quarter to the instance (using timestamp).
 * @method        CarbonPeriod     quartersUntil($endDate = null, int|float $factor = 1)                              Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
 * @method        float            diffInUTCQuarters(DateTimeInterface|string|null $date, bool $absolute = false)     Convert current and given date in UTC timezone and return a floating number of quarters.
 * @method        $this            addUTCYears(int|float $value = 1)                                                  Add years (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCYear()                                                                       Add one year to the instance (using timestamp).
 * @method        $this            subUTCYears(int|float $value = 1)                                                  Sub years (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCYear()                                                                       Sub one year to the instance (using timestamp).
 * @method        CarbonPeriod     yearsUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
 * @method        float            diffInUTCYears(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of years.
 * @method        $this            addUTCDecades(int|float $value = 1)                                                Add decades (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCDecade()                                                                     Add one decade to the instance (using timestamp).
 * @method        $this            subUTCDecades(int|float $value = 1)                                                Sub decades (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCDecade()                                                                     Sub one decade to the instance (using timestamp).
 * @method        CarbonPeriod     decadesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
 * @method        float            diffInUTCDecades(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of decades.
 * @method        $this            addUTCCenturies(int|float $value = 1)                                              Add centuries (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCCentury()                                                                    Add one century to the instance (using timestamp).
 * @method        $this            subUTCCenturies(int|float $value = 1)                                              Sub centuries (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCCentury()                                                                    Sub one century to the instance (using timestamp).
 * @method        CarbonPeriod     centuriesUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
 * @method        float            diffInUTCCenturies(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of centuries.
 * @method        $this            addUTCMillennia(int|float $value = 1)                                              Add millennia (the $value count passed in) to the instance (using timestamp).
 * @method        $this            addUTCMillennium()                                                                 Add one millennium to the instance (using timestamp).
 * @method        $this            subUTCMillennia(int|float $value = 1)                                              Sub millennia (the $value count passed in) to the instance (using timestamp).
 * @method        $this            subUTCMillennium()                                                                 Sub one millennium to the instance (using timestamp).
 * @method        CarbonPeriod     millenniaUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
 * @method        float            diffInUTCMillennia(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of millennia.
 * @method        $this            roundYear(float $precision = 1, string $function = "round")                        Round the current instance year with given precision using the given function.
 * @method        $this            roundYears(float $precision = 1, string $function = "round")                       Round the current instance year with given precision using the given function.
 * @method        $this            floorYear(float $precision = 1)                                                    Truncate the current instance year with given precision.
 * @method        $this            floorYears(float $precision = 1)                                                   Truncate the current instance year with given precision.
 * @method        $this            ceilYear(float $precision = 1)                                                     Ceil the current instance year with given precision.
 * @method        $this            ceilYears(float $precision = 1)                                                    Ceil the current instance year with given precision.
 * @method        $this            roundMonth(float $precision = 1, string $function = "round")                       Round the current instance month with given precision using the given function.
 * @method        $this            roundMonths(float $precision = 1, string $function = "round")                      Round the current instance month with given precision using the given function.
 * @method        $this            floorMonth(float $precision = 1)                                                   Truncate the current instance month with given precision.
 * @method        $this            floorMonths(float $precision = 1)                                                  Truncate the current instance month with given precision.
 * @method        $this            ceilMonth(float $precision = 1)                                                    Ceil the current instance month with given precision.
 * @method        $this            ceilMonths(float $precision = 1)                                                   Ceil the current instance month with given precision.
 * @method        $this            roundDay(float $precision = 1, string $function = "round")                         Round the current instance day with given precision using the given function.
 * @method        $this            roundDays(float $precision = 1, string $function = "round")                        Round the current instance day with given precision using the given function.
 * @method        $this            floorDay(float $precision = 1)                                                     Truncate the current instance day with given precision.
 * @method        $this            floorDays(float $precision = 1)                                                    Truncate the current instance day with given precision.
 * @method        $this            ceilDay(float $precision = 1)                                                      Ceil the current instance day with given precision.
 * @method        $this            ceilDays(float $precision = 1)                                                     Ceil the current instance day with given precision.
 * @method        $this            roundHour(float $precision = 1, string $function = "round")                        Round the current instance hour with given precision using the given function.
 * @method        $this            roundHours(float $precision = 1, string $function = "round")                       Round the current instance hour with given precision using the given function.
 * @method        $this            floorHour(float $precision = 1)                                                    Truncate the current instance hour with given precision.
 * @method        $this            floorHours(float $precision = 1)                                                   Truncate the current instance hour with given precision.
 * @method        $this            ceilHour(float $precision = 1)                                                     Ceil the current instance hour with given precision.
 * @method        $this            ceilHours(float $precision = 1)                                                    Ceil the current instance hour with given precision.
 * @method        $this            roundMinute(float $precision = 1, string $function = "round")                      Round the current instance minute with given precision using the given function.
 * @method        $this            roundMinutes(float $precision = 1, string $function = "round")                     Round the current instance minute with given precision using the given function.
 * @method        $this            floorMinute(float $precision = 1)                                                  Truncate the current instance minute with given precision.
 * @method        $this            floorMinutes(float $precision = 1)                                                 Truncate the current instance minute with given precision.
 * @method        $this            ceilMinute(float $precision = 1)                                                   Ceil the current instance minute with given precision.
 * @method        $this            ceilMinutes(float $precision = 1)                                                  Ceil the current instance minute with given precision.
 * @method        $this            roundSecond(float $precision = 1, string $function = "round")                      Round the current instance second with given precision using the given function.
 * @method        $this            roundSeconds(float $precision = 1, string $function = "round")                     Round the current instance second with given precision using the given function.
 * @method        $this            floorSecond(float $precision = 1)                                                  Truncate the current instance second with given precision.
 * @method        $this            floorSeconds(float $precision = 1)                                                 Truncate the current instance second with given precision.
 * @method        $this            ceilSecond(float $precision = 1)                                                   Ceil the current instance second with given precision.
 * @method        $this            ceilSeconds(float $precision = 1)                                                  Ceil the current instance second with given precision.
 * @method        $this            roundMillennium(float $precision = 1, string $function = "round")                  Round the current instance millennium with given precision using the given function.
 * @method        $this            roundMillennia(float $precision = 1, string $function = "round")                   Round the current instance millennium with given precision using the given function.
 * @method        $this            floorMillennium(float $precision = 1)                                              Truncate the current instance millennium with given precision.
 * @method        $this            floorMillennia(float $precision = 1)                                               Truncate the current instance millennium with given precision.
 * @method        $this            ceilMillennium(float $precision = 1)                                               Ceil the current instance millennium with given precision.
 * @method        $this            ceilMillennia(float $precision = 1)                                                Ceil the current instance millennium with given precision.
 * @method        $this            roundCentury(float $precision = 1, string $function = "round")                     Round the current instance century with given precision using the given function.
 * @method        $this            roundCenturies(float $precision = 1, string $function = "round")                   Round the current instance century with given precision using the given function.
 * @method        $this            floorCentury(float $precision = 1)                                                 Truncate the current instance century with given precision.
 * @method        $this            floorCenturies(float $precision = 1)                                               Truncate the current instance century with given precision.
 * @method        $this            ceilCentury(float $precision = 1)                                                  Ceil the current instance century with given precision.
 * @method        $this            ceilCenturies(float $precision = 1)                                                Ceil the current instance century with given precision.
 * @method        $this            roundDecade(float $precision = 1, string $function = "round")                      Round the current instance decade with given precision using the given function.
 * @method        $this            roundDecades(float $precision = 1, string $function = "round")                     Round the current instance decade with given precision using the given function.
 * @method        $this            floorDecade(float $precision = 1)                                                  Truncate the current instance decade with given precision.
 * @method        $this            floorDecades(float $precision = 1)                                                 Truncate the current instance decade with given precision.
 * @method        $this            ceilDecade(float $precision = 1)                                                   Ceil the current instance decade with given precision.
 * @method        $this            ceilDecades(float $precision = 1)                                                  Ceil the current instance decade with given precision.
 * @method        $this            roundQuarter(float $precision = 1, string $function = "round")                     Round the current instance quarter with given precision using the given function.
 * @method        $this            roundQuarters(float $precision = 1, string $function = "round")                    Round the current instance quarter with given precision using the given function.
 * @method        $this            floorQuarter(float $precision = 1)                                                 Truncate the current instance quarter with given precision.
 * @method        $this            floorQuarters(float $precision = 1)                                                Truncate the current instance quarter with given precision.
 * @method        $this            ceilQuarter(float $precision = 1)                                                  Ceil the current instance quarter with given precision.
 * @method        $this            ceilQuarters(float $precision = 1)                                                 Ceil the current instance quarter with given precision.
 * @method        $this            roundMillisecond(float $precision = 1, string $function = "round")                 Round the current instance millisecond with given precision using the given function.
 * @method        $this            roundMilliseconds(float $precision = 1, string $function = "round")                Round the current instance millisecond with given precision using the given function.
 * @method        $this            floorMillisecond(float $precision = 1)                                             Truncate the current instance millisecond with given precision.
 * @method        $this            floorMilliseconds(float $precision = 1)                                            Truncate the current instance millisecond with given precision.
 * @method        $this            ceilMillisecond(float $precision = 1)                                              Ceil the current instance millisecond with given precision.
 * @method        $this            ceilMilliseconds(float $precision = 1)                                             Ceil the current instance millisecond with given precision.
 * @method        $this            roundMicrosecond(float $precision = 1, string $function = "round")                 Round the current instance microsecond with given precision using the given function.
 * @method        $this            roundMicroseconds(float $precision = 1, string $function = "round")                Round the current instance microsecond with given precision using the given function.
 * @method        $this            floorMicrosecond(float $precision = 1)                                             Truncate the current instance microsecond with given precision.
 * @method        $this            floorMicroseconds(float $precision = 1)                                            Truncate the current instance microsecond with given precision.
 * @method        $this            ceilMicrosecond(float $precision = 1)                                              Ceil the current instance microsecond with given precision.
 * @method        $this            ceilMicroseconds(float $precision = 1)                                             Ceil the current instance microsecond with given precision.
 * @method        string           shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)   Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)    Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1)  Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        int              centuriesInMillennium()                                                            Return the number of centuries contained in the current millennium
 * @method        int|static       centuryOfMillennium(?int $century = null)                                          Return the value of the century starting from the beginning of the current millennium when called with no parameters, change the current century when called with an integer value
 * @method        int|static       dayOfCentury(?int $day = null)                                                     Return the value of the day starting from the beginning of the current century when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfDecade(?int $day = null)                                                      Return the value of the day starting from the beginning of the current decade when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMillennium(?int $day = null)                                                  Return the value of the day starting from the beginning of the current millennium when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMonth(?int $day = null)                                                       Return the value of the day starting from the beginning of the current month when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfQuarter(?int $day = null)                                                     Return the value of the day starting from the beginning of the current quarter when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfWeek(?int $day = null)                                                        Return the value of the day starting from the beginning of the current week when called with no parameters, change the current day when called with an integer value
 * @method        int              daysInCentury()                                                                    Return the number of days contained in the current century
 * @method        int              daysInDecade()                                                                     Return the number of days contained in the current decade
 * @method        int              daysInMillennium()                                                                 Return the number of days contained in the current millennium
 * @method        int              daysInMonth()                                                                      Return the number of days contained in the current month
 * @method        int              daysInQuarter()                                                                    Return the number of days contained in the current quarter
 * @method        int              daysInWeek()                                                                       Return the number of days contained in the current week
 * @method        int              daysInYear()                                                                       Return the number of days contained in the current year
 * @method        int|static       decadeOfCentury(?int $decade = null)                                               Return the value of the decade starting from the beginning of the current century when called with no parameters, change the current decade when called with an integer value
 * @method        int|static       decadeOfMillennium(?int $decade = null)                                            Return the value of the decade starting from the beginning of the current millennium when called with no parameters, change the current decade when called with an integer value
 * @method        int              decadesInCentury()                                                                 Return the number of decades contained in the current century
 * @method        int              decadesInMillennium()                                                              Return the number of decades contained in the current millennium
 * @method        int|static       hourOfCentury(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current century when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDay(?int $hour = null)                                                       Return the value of the hour starting from the beginning of the current day when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDecade(?int $hour = null)                                                    Return the value of the hour starting from the beginning of the current decade when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMillennium(?int $hour = null)                                                Return the value of the hour starting from the beginning of the current millennium when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMonth(?int $hour = null)                                                     Return the value of the hour starting from the beginning of the current month when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfQuarter(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current quarter when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfWeek(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current week when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfYear(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current year when called with no parameters, change the current hour when called with an integer value
 * @method        int              hoursInCentury()                                                                   Return the number of hours contained in the current century
 * @method        int              hoursInDay()                                                                       Return the number of hours contained in the current day
 * @method        int              hoursInDecade()                                                                    Return the number of hours contained in the current decade
 * @method        int              hoursInMillennium()                                                                Return the number of hours contained in the current millennium
 * @method        int              hoursInMonth()                                                                     Return the number of hours contained in the current month
 * @method        int              hoursInQuarter()                                                                   Return the number of hours contained in the current quarter
 * @method        int              hoursInWeek()                                                                      Return the number of hours contained in the current week
 * @method        int              hoursInYear()                                                                      Return the number of hours contained in the current year
 * @method        int|static       microsecondOfCentury(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current century when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDay(?int $microsecond = null)                                         Return the value of the microsecond starting from the beginning of the current day when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDecade(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current decade when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfHour(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current hour when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillennium(?int $microsecond = null)                                  Return the value of the microsecond starting from the beginning of the current millennium when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillisecond(?int $microsecond = null)                                 Return the value of the microsecond starting from the beginning of the current millisecond when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMinute(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current minute when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMonth(?int $microsecond = null)                                       Return the value of the microsecond starting from the beginning of the current month when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfQuarter(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current quarter when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfSecond(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current second when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfWeek(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current week when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfYear(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current year when called with no parameters, change the current microsecond when called with an integer value
 * @method        int              microsecondsInCentury()                                                            Return the number of microseconds contained in the current century
 * @method        int              microsecondsInDay()                                                                Return the number of microseconds contained in the current day
 * @method        int              microsecondsInDecade()                                                             Return the number of microseconds contained in the current decade
 * @method        int              microsecondsInHour()                                                               Return the number of microseconds contained in the current hour
 * @method        int              microsecondsInMillennium()                                                         Return the number of microseconds contained in the current millennium
 * @method        int              microsecondsInMillisecond()                                                        Return the number of microseconds contained in the current millisecond
 * @method        int              microsecondsInMinute()                                                             Return the number of microseconds contained in the current minute
 * @method        int              microsecondsInMonth()                                                              Return the number of microseconds contained in the current month
 * @method        int              microsecondsInQuarter()                                                            Return the number of microseconds contained in the current quarter
 * @method        int              microsecondsInSecond()                                                             Return the number of microseconds contained in the current second
 * @method        int              microsecondsInWeek()                                                               Return the number of microseconds contained in the current week
 * @method        int              microsecondsInYear()                                                               Return the number of microseconds contained in the current year
 * @method        int|static       millisecondOfCentury(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current century when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDay(?int $millisecond = null)                                         Return the value of the millisecond starting from the beginning of the current day when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDecade(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current decade when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfHour(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current hour when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMillennium(?int $millisecond = null)                                  Return the value of the millisecond starting from the beginning of the current millennium when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMinute(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current minute when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMonth(?int $millisecond = null)                                       Return the value of the millisecond starting from the beginning of the current month when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfQuarter(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current quarter when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfSecond(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current second when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfWeek(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current week when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfYear(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current year when called with no parameters, change the current millisecond when called with an integer value
 * @method        int              millisecondsInCentury()                                                            Return the number of milliseconds contained in the current century
 * @method        int              millisecondsInDay()                                                                Return the number of milliseconds contained in the current day
 * @method        int              millisecondsInDecade()                                                             Return the number of milliseconds contained in the current decade
 * @method        int              millisecondsInHour()                                                               Return the number of milliseconds contained in the current hour
 * @method        int              millisecondsInMillennium()                                                         Return the number of milliseconds contained in the current millennium
 * @method        int              millisecondsInMinute()                                                             Return the number of milliseconds contained in the current minute
 * @method        int              millisecondsInMonth()                                                              Return the number of milliseconds contained in the current month
 * @method        int              millisecondsInQuarter()                                                            Return the number of milliseconds contained in the current quarter
 * @method        int              millisecondsInSecond()                                                             Return the number of milliseconds contained in the current second
 * @method        int              millisecondsInWeek()                                                               Return the number of milliseconds contained in the current week
 * @method        int              millisecondsInYear()                                                               Return the number of milliseconds contained in the current year
 * @method        int|static       minuteOfCentury(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current century when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDay(?int $minute = null)                                                   Return the value of the minute starting from the beginning of the current day when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDecade(?int $minute = null)                                                Return the value of the minute starting from the beginning of the current decade when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfHour(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current hour when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMillennium(?int $minute = null)                                            Return the value of the minute starting from the beginning of the current millennium when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMonth(?int $minute = null)                                                 Return the value of the minute starting from the beginning of the current month when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfQuarter(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current quarter when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfWeek(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current week when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfYear(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current year when called with no parameters, change the current minute when called with an integer value
 * @method        int              minutesInCentury()                                                                 Return the number of minutes contained in the current century
 * @method        int              minutesInDay()                                                                     Return the number of minutes contained in the current day
 * @method        int              minutesInDecade()                                                                  Return the number of minutes contained in the current decade
 * @method        int              minutesInHour()                                                                    Return the number of minutes contained in the current hour
 * @method        int              minutesInMillennium()                                                              Return the number of minutes contained in the current millennium
 * @method        int              minutesInMonth()                                                                   Return the number of minutes contained in the current month
 * @method        int              minutesInQuarter()                                                                 Return the number of minutes contained in the current quarter
 * @method        int              minutesInWeek()                                                                    Return the number of minutes contained in the current week
 * @method        int              minutesInYear()                                                                    Return the number of minutes contained in the current year
 * @method        int|static       monthOfCentury(?int $month = null)                                                 Return the value of the month starting from the beginning of the current century when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfDecade(?int $month = null)                                                  Return the value of the month starting from the beginning of the current decade when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfMillennium(?int $month = null)                                              Return the value of the month starting from the beginning of the current millennium when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfQuarter(?int $month = null)                                                 Return the value of the month starting from the beginning of the current quarter when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfYear(?int $month = null)                                                    Return the value of the month starting from the beginning of the current year when called with no parameters, change the current month when called with an integer value
 * @method        int              monthsInCentury()                                                                  Return the number of months contained in the current century
 * @method        int              monthsInDecade()                                                                   Return the number of months contained in the current decade
 * @method        int              monthsInMillennium()                                                               Return the number of months contained in the current millennium
 * @method        int              monthsInQuarter()                                                                  Return the number of months contained in the current quarter
 * @method        int              monthsInYear()                                                                     Return the number of months contained in the current year
 * @method        int|static       quarterOfCentury(?int $quarter = null)                                             Return the value of the quarter starting from the beginning of the current century when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfDecade(?int $quarter = null)                                              Return the value of the quarter starting from the beginning of the current decade when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfMillennium(?int $quarter = null)                                          Return the value of the quarter starting from the beginning of the current millennium when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfYear(?int $quarter = null)                                                Return the value of the quarter starting from the beginning of the current year when called with no parameters, change the current quarter when called with an integer value
 * @method        int              quartersInCentury()                                                                Return the number of quarters contained in the current century
 * @method        int              quartersInDecade()                                                                 Return the number of quarters contained in the current decade
 * @method        int              quartersInMillennium()                                                             Return the number of quarters contained in the current millennium
 * @method        int              quartersInYear()                                                                   Return the number of quarters contained in the current year
 * @method        int|static       secondOfCentury(?int $second = null)                                               Return the value of the second starting from the beginning of the current century when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDay(?int $second = null)                                                   Return the value of the second starting from the beginning of the current day when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDecade(?int $second = null)                                                Return the value of the second starting from the beginning of the current decade when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfHour(?int $second = null)                                                  Return the value of the second starting from the beginning of the current hour when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMillennium(?int $second = null)                                            Return the value of the second starting from the beginning of the current millennium when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMinute(?int $second = null)                                                Return the value of the second starting from the beginning of the current minute when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMonth(?int $second = null)                                                 Return the value of the second starting from the beginning of the current month when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfQuarter(?int $second = null)                                               Return the value of the second starting from the beginning of the current quarter when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfWeek(?int $second = null)                                                  Return the value of the second starting from the beginning of the current week when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfYear(?int $second = null)                                                  Return the value of the second starting from the beginning of the current year when called with no parameters, change the current second when called with an integer value
 * @method        int              secondsInCentury()                                                                 Return the number of seconds contained in the current century
 * @method        int              secondsInDay()                                                                     Return the number of seconds contained in the current day
 * @method        int              secondsInDecade()                                                                  Return the number of seconds contained in the current decade
 * @method        int              secondsInHour()                                                                    Return the number of seconds contained in the current hour
 * @method        int              secondsInMillennium()                                                              Return the number of seconds contained in the current millennium
 * @method        int              secondsInMinute()                                                                  Return the number of seconds contained in the current minute
 * @method        int              secondsInMonth()                                                                   Return the number of seconds contained in the current month
 * @method        int              secondsInQuarter()                                                                 Return the number of seconds contained in the current quarter
 * @method        int              secondsInWeek()                                                                    Return the number of seconds contained in the current week
 * @method        int              secondsInYear()                                                                    Return the number of seconds contained in the current year
 * @method        int|static       weekOfCentury(?int $week = null)                                                   Return the value of the week starting from the beginning of the current century when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfDecade(?int $week = null)                                                    Return the value of the week starting from the beginning of the current decade when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMillennium(?int $week = null)                                                Return the value of the week starting from the beginning of the current millennium when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMonth(?int $week = null)                                                     Return the value of the week starting from the beginning of the current month when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfQuarter(?int $week = null)                                                   Return the value of the week starting from the beginning of the current quarter when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfYear(?int $week = null)                                                      Return the value of the week starting from the beginning of the current year when called with no parameters, change the current week when called with an integer value
 * @method        int              weeksInCentury()                                                                   Return the number of weeks contained in the current century
 * @method        int              weeksInDecade()                                                                    Return the number of weeks contained in the current decade
 * @method        int              weeksInMillennium()                                                                Return the number of weeks contained in the current millennium
 * @method        int              weeksInMonth()                                                                     Return the number of weeks contained in the current month
 * @method        int              weeksInQuarter()                                                                   Return the number of weeks contained in the current quarter
 * @method        int|static       yearOfCentury(?int $year = null)                                                   Return the value of the year starting from the beginning of the current century when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfDecade(?int $year = null)                                                    Return the value of the year starting from the beginning of the current decade when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfMillennium(?int $year = null)                                                Return the value of the year starting from the beginning of the current millennium when called with no parameters, change the current year when called with an integer value
 * @method        int              yearsInCentury()                                                                   Return the number of years contained in the current century
 * @method        int              yearsInDecade()                                                                    Return the number of years contained in the current decade
 * @method        int              yearsInMillennium()                                                                Return the number of years contained in the current millennium
 *
 * </autodoc>
 */
class Carbon extends DateTime implements CarbonInterface
{
    use Date;

    /**
     * Returns true if the current class/instance is mutable.
     */
    public static function isMutable(): bool
    {
        return true;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\Exceptions\ImmutableException;
use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;

class TranslatorImmutable extends Translator
{
    private bool $constructed = false;

    public function __construct($locale, ?MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
    {
        parent::__construct($locale, $formatter, $cacheDir, $debug);
        $this->constructed = true;
    }

    /**
     * @codeCoverageIgnore
     */
    public function setDirectories(array $directories): static
    {
        $this->disallowMutation(__METHOD__);

        return parent::setDirectories($directories);
    }

    public function setLocale($locale): void
    {
        $this->disallowMutation(__METHOD__);

        parent::setLocale($locale);
    }

    /**
     * @codeCoverageIgnore
     */
    public function setMessages(string $locale, array $messages): static
    {
        $this->disallowMutation(__METHOD__);

        return parent::setMessages($locale, $messages);
    }

    /**
     * @codeCoverageIgnore
     */
    public function setTranslations(array $messages): static
    {
        $this->disallowMutation(__METHOD__);

        return parent::setTranslations($messages);
    }

    /**
     * @codeCoverageIgnore
     */
    public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory): void
    {
        $this->disallowMutation(__METHOD__);

        parent::setConfigCacheFactory($configCacheFactory);
    }

    public function resetMessages(?string $locale = null): bool
    {
        $this->disallowMutation(__METHOD__);

        return parent::resetMessages($locale);
    }

    /**
     * @codeCoverageIgnore
     */
    public function setFallbackLocales(array $locales): void
    {
        $this->disallowMutation(__METHOD__);

        parent::setFallbackLocales($locales);
    }

    private function disallowMutation($method)
    {
        if ($this->constructed) {
            throw new ImmutableException($method.' not allowed on '.static::class);
        }
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Closure;
use DateInterval;
use DatePeriod;
use DateTime;
use DateTimeInterface;
use DateTimeZone;
use ReflectionFunction;
use ReflectionNamedType;
use ReflectionType;

final class Callback
{
    private ?ReflectionFunction $function;

    private function __construct(private readonly Closure $closure)
    {
    }

    public static function fromClosure(Closure $closure): self
    {
        return new self($closure);
    }

    public static function parameter(mixed $closure, mixed $value, string|int $index = 0): mixed
    {
        if ($closure instanceof Closure) {
            return self::fromClosure($closure)->prepareParameter($value, $index);
        }

        return $value;
    }

    public function getReflectionFunction(): ReflectionFunction
    {
        return $this->function ??= new ReflectionFunction($this->closure);
    }

    public function prepareParameter(mixed $value, string|int $index = 0): mixed
    {
        $type = $this->getParameterType($index);

        if (!($type instanceof ReflectionNamedType)) {
            return $value;
        }

        $name = $type->getName();

        if ($name === CarbonInterface::class) {
            $name = $value instanceof DateTime ? Carbon::class : CarbonImmutable::class;
        }

        if (!class_exists($name) || is_a($value, $name)) {
            return $value;
        }

        $class = $this->getPromotedClass($value);

        if ($class && is_a($name, $class, true)) {
            return $name::instance($value);
        }

        return $value;
    }

    public function call(mixed ...$arguments): mixed
    {
        foreach ($arguments as $index => &$value) {
            if ($this->getPromotedClass($value)) {
                $value = $this->prepareParameter($value, $index);
            }
        }

        return ($this->closure)(...$arguments);
    }

    private function getParameterType(string|int $index): ?ReflectionType
    {
        $parameters = $this->getReflectionFunction()->getParameters();

        if (\is_int($index)) {
            return ($parameters[$index] ?? null)?->getType();
        }

        foreach ($parameters as $parameter) {
            if ($parameter->getName() === $index) {
                return $parameter->getType();
            }
        }

        return null;
    }

    /** @return class-string|null */
    private function getPromotedClass(mixed $value): ?string
    {
        if ($value instanceof DateTimeInterface) {
            return CarbonInterface::class;
        }

        if ($value instanceof DateInterval) {
            return CarbonInterval::class;
        }

        if ($value instanceof DatePeriod) {
            return CarbonPeriod::class;
        }

        if ($value instanceof DateTimeZone) {
            return CarbonTimeZone::class;
        }

        return null;
    }
}
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Rune Mønnike
 * - François B
 * - codenhagen
 * - JD Isaacks
 * - Jens Herlevsen
 * - Ulrik McArdle (mcardle)
 * - Frederik Sauer (FrittenKeeZ)
 * - Janus Bahs Jacquet (kokoshneta)
 */
return [
    'year' => ':count år|:count år',
    'a_year' => 'et år|:count år',
    'y' => ':count år|:count år',
    'month' => ':count måned|:count måneder',
    'a_month' => 'en måned|:count måneder',
    'm' => ':count mdr.',
    'week' => ':count uge|:count uger',
    'a_week' => 'en uge|:count uger',
    'w' => ':count u.',
    'day' => ':count dag|:count dage',
    'a_day' => ':count dag|:count dage',
    'd' => ':count d.',
    'hour' => ':count time|:count timer',
    'a_hour' => 'en time|:count timer',
    'h' => ':count t.',
    'minute' => ':count minut|:count minutter',
    'a_minute' => 'et minut|:count minutter',
    'min' => ':count min.',
    'second' => ':count sekund|:count sekunder',
    'a_second' => 'få sekunder|:count sekunder',
    's' => ':count s.',
    'ago' => 'for :time siden',
    'from_now' => 'om :time',
    'after' => ':time efter',
    'before' => ':time før',
    'diff_now' => 'nu',
    'diff_today' => 'i dag',
    'diff_today_regexp' => 'i dag(?:\\s+kl.)?',
    'diff_yesterday' => 'i går',
    'diff_yesterday_regexp' => 'i går(?:\\s+kl.)?',
    'diff_tomorrow' => 'i morgen',
    'diff_tomorrow_regexp' => 'i morgen(?:\\s+kl.)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[i dag kl.] LT',
        'nextDay' => '[i morgen kl.] LT',
        'nextWeek' => 'på dddd [kl.] LT',
        'lastDay' => '[i går kl.] LT',
        'lastWeek' => '[i] dddd[s kl.] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['januar', 'februar', 'marts', 'april', 'maj', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'december'],
    'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'],
    'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
    'weekdays_short' => ['søn.', 'man.', 'tir.', 'ons.', 'tor.', 'fre.', 'lør.'],
    'weekdays_min' => ['sø.', 'ma.', 'ti.', 'on.', 'to.', 'fr.', 'lø.'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' og '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kamusi Project Martin Benjamin locales@kamusi.org
 */
return array_replace_recursive(require __DIR__.'/sw.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
    'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['asubuhi', 'alasiri'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/hne_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - yasinn
 */
return [
    'year' => '{1}'.'بىر يىل'.'|:count '.'يىل',
    'month' => '{1}'.'بىر ئاي'.'|:count '.'ئاي',
    'week' => '{1}'.'بىر ھەپتە'.'|:count '.'ھەپتە',
    'day' => '{1}'.'بىر كۈن'.'|:count '.'كۈن',
    'hour' => '{1}'.'بىر سائەت'.'|:count '.'سائەت',
    'minute' => '{1}'.'بىر مىنۇت'.'|:count '.'مىنۇت',
    'second' => '{1}'.'نەچچە سېكونت'.'|:count '.'سېكونت',
    'ago' => ':time بۇرۇن',
    'from_now' => ':time كېيىن',
    'diff_today' => 'بۈگۈن',
    'diff_yesterday' => 'تۆنۈگۈن',
    'diff_tomorrow' => 'ئەتە',
    'diff_tomorrow_regexp' => 'ئەتە(?:\\s+سائەت)?',
    'diff_today_regexp' => 'بۈگۈن(?:\\s+سائەت)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى',
        'LLL' => 'YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
        'LLLL' => 'dddd، YYYY-يىلىM-ئاينىڭD-كۈنى، HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[بۈگۈن سائەت] LT',
        'nextDay' => '[ئەتە سائەت] LT',
        'nextWeek' => '[كېلەركى] dddd [سائەت] LT',
        'lastDay' => '[تۆنۈگۈن] LT',
        'lastWeek' => '[ئالدىنقى] dddd [سائەت] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'd', 'D', 'DDD' => $number.'-كۈنى',
            'w', 'W' => $number.'-ھەپتە',
            default => $number,
        };
    },
    'meridiem' => static function ($hour, $minute) {
        $time = $hour * 100 + $minute;
        if ($time < 600) {
            return 'يېرىم كېچە';
        }
        if ($time < 900) {
            return 'سەھەر';
        }
        if ($time < 1130) {
            return 'چۈشتىن بۇرۇن';
        }
        if ($time < 1230) {
            return 'چۈش';
        }
        if ($time < 1800) {
            return 'چۈشتىن كېيىن';
        }

        return 'كەچ';
    },
    'months' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
    'months_short' => ['يانۋار', 'فېۋرال', 'مارت', 'ئاپرېل', 'ماي', 'ئىيۇن', 'ئىيۇل', 'ئاۋغۇست', 'سېنتەبىر', 'ئۆكتەبىر', 'نويابىر', 'دېكابىر'],
    'weekdays' => ['يەكشەنبە', 'دۈشەنبە', 'سەيشەنبە', 'چارشەنبە', 'پەيشەنبە', 'جۈمە', 'شەنبە'],
    'weekdays_short' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],
    'weekdays_min' => ['يە', 'دۈ', 'سە', 'چا', 'پە', 'جۈ', 'شە'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' ۋە '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/nso_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Daniel S. Billing
 * - Paul
 * - Jimmie Johansson
 * - Jens Herlevsen
 */
return array_replace_recursive(require __DIR__.'/nb.php', [
    'formats' => [
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D. MMMM YYYY [kl.] HH:mm',
    ],
    'calendar' => [
        'nextWeek' => 'på dddd [kl.] LT',
        'lastWeek' => '[i] dddd[s kl.] LT',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ms.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/MM/yy',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY, h:mm a',
        'LLLL' => 'dd MMMM YYYY, h:mm a',
    ],
    'meridiem' => ['a', 'p'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mjw_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ur.php', [
    'weekdays' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
    'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
    'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بُدھ', 'جمعرات', 'جمعہ', 'ہفتہ'],
    'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئ', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd, DD MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sah_RU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sr_Latn_ME.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
    'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵕⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
    'weekdays_short' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
    'weekdays_min' => ['ⴰⵙⴰ', 'ⴰⵢⵏ', 'ⴰⵙⵉ', 'ⴰⴽⵕ', 'ⴰⴽⵡ', 'ⴰⵙⵉⵎ', 'ⴰⵙⵉⴹ'],
    'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵜⵓⴱⵔ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
    'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵜⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
    'first_day_of_week' => 6,
    'weekend' => [5, 6],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'year' => ':count aseggwas',
    'y' => ':count aseggwas',
    'a_year' => ':count aseggwas',

    'month' => ':count ayyur',
    'm' => ':count ayyur',
    'a_month' => ':count ayyur',

    'week' => ':count imalass',
    'w' => ':count imalass',
    'a_week' => ':count imalass',

    'day' => ':count ass',
    'd' => ':count ass',
    'a_day' => ':count ass',

    'hour' => ':count urɣ', // less reliable
    'h' => ':count urɣ', // less reliable
    'a_hour' => ':count urɣ', // less reliable

    'minute' => ':count ⴰⵎⵥⵉ', // less reliable
    'min' => ':count ⴰⵎⵥⵉ', // less reliable
    'a_minute' => ':count ⴰⵎⵥⵉ', // less reliable

    'second' => ':count sin', // less reliable
    's' => ':count sin', // less reliable
    'a_second' => ':count sin', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Cassiano Montanari
 * - Eduardo Dalla Vecchia
 * - David Rodrigues
 * - Matt Pope
 * - François B
 * - Prodis
 * - Marlon Maxwel
 * - JD Isaacks
 * - Raphael Amorim
 * - Rafael Raupp
 * - felipeleite1
 * - swalker
 * - Lucas Macedo
 * - Paulo Freitas
 * - Sebastian Thierer
 */
return array_replace_recursive(require __DIR__.'/pt.php', [
    'period_recurrences' => 'uma|:count vez',
    'period_interval' => 'toda :interval',
    'formats' => [
        'LLL' => 'D [de] MMMM [de] YYYY [às] HH:mm',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY [às] HH:mm',
    ],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Adam Brunner
 * - Brett Johnson
 * - balping
 */

use Carbon\CarbonInterface;

$huWeekEndings = ['vasárnap', 'hétfőn', 'kedden', 'szerdán', 'csütörtökön', 'pénteken', 'szombaton'];

return [
    'year' => ':count év',
    'y' => ':count év',
    'month' => ':count hónap',
    'm' => ':count hónap',
    'week' => ':count hét',
    'w' => ':count hét',
    'day' => ':count nap',
    'd' => ':count nap',
    'hour' => ':count óra',
    'h' => ':count óra',
    'minute' => ':count perc',
    'min' => ':count perc',
    'second' => ':count másodperc',
    's' => ':count másodperc',
    'ago' => ':time',
    'from_now' => ':time múlva',
    'after' => ':time később',
    'before' => ':time korábban',
    'year_ago' => ':count éve',
    'y_ago' => ':count éve',
    'month_ago' => ':count hónapja',
    'm_ago' => ':count hónapja',
    'week_ago' => ':count hete',
    'w_ago' => ':count hete',
    'day_ago' => ':count napja',
    'd_ago' => ':count napja',
    'hour_ago' => ':count órája',
    'h_ago' => ':count órája',
    'minute_ago' => ':count perce',
    'min_ago' => ':count perce',
    'second_ago' => ':count másodperce',
    's_ago' => ':count másodperce',
    'year_after' => ':count évvel',
    'y_after' => ':count évvel',
    'month_after' => ':count hónappal',
    'm_after' => ':count hónappal',
    'week_after' => ':count héttel',
    'w_after' => ':count héttel',
    'day_after' => ':count nappal',
    'd_after' => ':count nappal',
    'hour_after' => ':count órával',
    'h_after' => ':count órával',
    'minute_after' => ':count perccel',
    'min_after' => ':count perccel',
    'second_after' => ':count másodperccel',
    's_after' => ':count másodperccel',
    'year_before' => ':count évvel',
    'y_before' => ':count évvel',
    'month_before' => ':count hónappal',
    'm_before' => ':count hónappal',
    'week_before' => ':count héttel',
    'w_before' => ':count héttel',
    'day_before' => ':count nappal',
    'd_before' => ':count nappal',
    'hour_before' => ':count órával',
    'h_before' => ':count órával',
    'minute_before' => ':count perccel',
    'min_before' => ':count perccel',
    'second_before' => ':count másodperccel',
    's_before' => ':count másodperccel',
    'months' => ['január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december'],
    'months_short' => ['jan.', 'febr.', 'márc.', 'ápr.', 'máj.', 'jún.', 'júl.', 'aug.', 'szept.', 'okt.', 'nov.', 'dec.'],
    'weekdays' => ['vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'],
    'weekdays_short' => ['vas', 'hét', 'kedd', 'sze', 'csüt', 'pén', 'szo'],
    'weekdays_min' => ['v', 'h', 'k', 'sze', 'cs', 'p', 'sz'],
    'ordinal' => ':number.',
    'diff_now' => 'most',
    'diff_today' => 'ma',
    'diff_yesterday' => 'tegnap',
    'diff_tomorrow' => 'holnap',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'YYYY.MM.DD.',
        'LL' => 'YYYY. MMMM D.',
        'LLL' => 'YYYY. MMMM D. H:mm',
        'LLLL' => 'YYYY. MMMM D., dddd H:mm',
    ],
    'calendar' => [
        'sameDay' => '[ma] LT[-kor]',
        'nextDay' => '[holnap] LT[-kor]',
        'nextWeek' => static function (CarbonInterface $date) use ($huWeekEndings) {
            return '['.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]';
        },
        'lastDay' => '[tegnap] LT[-kor]',
        'lastWeek' => static function (CarbonInterface $date) use ($huWeekEndings) {
            return '[múlt '.$huWeekEndings[$date->dayOfWeek].'] LT[-kor]';
        },
        'sameElse' => 'L',
    ],
    'meridiem' => ['DE', 'DU'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' és '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Mousa Moradi mousamk@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'OY/OM/OD',
    ],
    'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
    'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
    'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
    'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
    'weekdays_min' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
    'first_day_of_week' => 6,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - Mia Nordentoft
 * - JD Isaacks
 */
return [
    'year' => ':count jaro|:count jaroj',
    'a_year' => 'jaro|:count jaroj',
    'y' => ':count j.',
    'month' => ':count monato|:count monatoj',
    'a_month' => 'monato|:count monatoj',
    'm' => ':count mo.',
    'week' => ':count semajno|:count semajnoj',
    'a_week' => 'semajno|:count semajnoj',
    'w' => ':count sem.',
    'day' => ':count tago|:count tagoj',
    'a_day' => 'tago|:count tagoj',
    'd' => ':count t.',
    'hour' => ':count horo|:count horoj',
    'a_hour' => 'horo|:count horoj',
    'h' => ':count h.',
    'minute' => ':count minuto|:count minutoj',
    'a_minute' => 'minuto|:count minutoj',
    'min' => ':count min.',
    'second' => ':count sekundo|:count sekundoj',
    'a_second' => 'sekundoj|:count sekundoj',
    's' => ':count sek.',
    'ago' => 'antaŭ :time',
    'from_now' => 'post :time',
    'after' => ':time poste',
    'before' => ':time antaŭe',
    'diff_yesterday' => 'Hieraŭ',
    'diff_yesterday_regexp' => 'Hieraŭ(?:\\s+je)?',
    'diff_today' => 'Hodiaŭ',
    'diff_today_regexp' => 'Hodiaŭ(?:\\s+je)?',
    'diff_tomorrow' => 'Morgaŭ',
    'diff_tomorrow_regexp' => 'Morgaŭ(?:\\s+je)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'D[-a de] MMMM, YYYY',
        'LLL' => 'D[-a de] MMMM, YYYY HH:mm',
        'LLLL' => 'dddd, [la] D[-a de] MMMM, YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Hodiaŭ je] LT',
        'nextDay' => '[Morgaŭ je] LT',
        'nextWeek' => 'dddd [je] LT',
        'lastDay' => '[Hieraŭ je] LT',
        'lastWeek' => '[pasinta] dddd [je] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numbera',
    'meridiem' => ['a.t.m.', 'p.t.m.'],
    'months' => ['januaro', 'februaro', 'marto', 'aprilo', 'majo', 'junio', 'julio', 'aŭgusto', 'septembro', 'oktobro', 'novembro', 'decembro'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aŭg', 'sep', 'okt', 'nov', 'dec'],
    'weekdays' => ['dimanĉo', 'lundo', 'mardo', 'merkredo', 'ĵaŭdo', 'vendredo', 'sabato'],
    'weekdays_short' => ['dim', 'lun', 'mard', 'merk', 'ĵaŭ', 'ven', 'sab'],
    'weekdays_min' => ['di', 'lu', 'ma', 'me', 'ĵa', 've', 'sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' kaj '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/the_NP.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat Pune    libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['জানুৱারি', 'ফেব্রুৱারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'সেপ্তেম্বর', 'ওক্তোবর', 'নবেম্বর', 'ডিসেম্বর'],
    'months_short' => ['জান', 'ফেব', 'মার', 'এপ্রি', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ', 'ওক্ত', 'নবে', 'ডিস'],
    'weekdays' => ['নোংমাইজিং', 'নিংথৌকাবা', 'লৈবাকপোকপা', 'য়ুমশকৈশা', 'শগোলশেন', 'ইরাই', 'থাংজ'],
    'weekdays_short' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'],
    'weekdays_min' => ['নোং', 'নিং', 'লৈবাক', 'য়ুম', 'শগোল', 'ইরা', 'থাং'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['এ.ম.', 'প.ম.'],

    'year' => ':count ইসিং', // less reliable
    'y' => ':count ইসিং', // less reliable
    'a_year' => ':count ইসিং', // less reliable

    'second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
    's' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
    'a_second' => ':count ꯅꯤꯡꯊꯧꯀꯥꯕ', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ta.php', [
    'meridiem' => ['Taparachu', 'Ebongi'],
    'weekdays' => ['Nakaejuma', 'Nakaebarasa', 'Nakaare', 'Nakauni', 'Nakaung’on', 'Nakakany', 'Nakasabiti'],
    'weekdays_short' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
    'weekdays_min' => ['Jum', 'Bar', 'Aar', 'Uni', 'Ung', 'Kan', 'Sab'],
    'months' => ['Orara', 'Omuk', 'Okwamg’', 'Odung’el', 'Omaruk', 'Omodok’king’ol', 'Ojola', 'Opedel', 'Osokosokoma', 'Otibar', 'Olabor', 'Opoo'],
    'months_short' => ['Rar', 'Muk', 'Kwa', 'Dun', 'Mar', 'Mod', 'Jol', 'Ped', 'Sok', 'Tib', 'Lab', 'Poo'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['mbaʼámbaʼ', 'ncwònzém'],
    'weekdays' => null,
    'weekdays_short' => ['lyɛʼɛ́ sẅíŋtè', 'mvfò lyɛ̌ʼ', 'mbɔ́ɔntè mvfò lyɛ̌ʼ', 'tsètsɛ̀ɛ lyɛ̌ʼ', 'mbɔ́ɔntè tsetsɛ̀ɛ lyɛ̌ʼ', 'mvfò màga lyɛ̌ʼ', 'màga lyɛ̌ʼ'],
    'weekdays_min' => null,
    'months' => null,
    'months_short' => ['saŋ tsetsɛ̀ɛ lùm', 'saŋ kàg ngwóŋ', 'saŋ lepyè shúm', 'saŋ cÿó', 'saŋ tsɛ̀ɛ cÿó', 'saŋ njÿoláʼ', 'saŋ tyɛ̀b tyɛ̀b mbʉ̀ŋ', 'saŋ mbʉ̀ŋ', 'saŋ ngwɔ̀ʼ mbÿɛ', 'saŋ tàŋa tsetsáʼ', 'saŋ mejwoŋó', 'saŋ lùm'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/yy',
        'LL' => 'D MMM, YYYY',
        'LLL' => '[lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm',
        'LLLL' => 'dddd , [lyɛ]̌ʼ d [na] MMMM, YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
    'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
    'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
    'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['saaku', 'carra'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/km.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ia_FR.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Sashko Todorov
 * - Josh Soref
 * - François B
 * - Serhan Apaydın
 * - Borislav Mickov
 * - JD Isaacks
 * - Tomi Atanasoski
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count година|:count години',
    'a_year' => 'година|:count години',
    'y' => ':count год.',
    'month' => ':count месец|:count месеци',
    'a_month' => 'месец|:count месеци',
    'm' => ':count месец|:count месеци',
    'week' => ':count седмица|:count седмици',
    'a_week' => 'седмица|:count седмици',
    'w' => ':count седмица|:count седмици',
    'day' => ':count ден|:count дена',
    'a_day' => 'ден|:count дена',
    'd' => ':count ден|:count дена',
    'hour' => ':count час|:count часа',
    'a_hour' => 'час|:count часа',
    'h' => ':count час|:count часа',
    'minute' => ':count минута|:count минути',
    'a_minute' => 'минута|:count минути',
    'min' => ':count мин.',
    'second' => ':count секунда|:count секунди',
    'a_second' => 'неколку секунди|:count секунди',
    's' => ':count сек.',
    'ago' => 'пред :time',
    'from_now' => 'после :time',
    'after' => 'по :time',
    'before' => 'пред :time',
    'diff_now' => 'сега',
    'diff_today' => 'Денес',
    'diff_today_regexp' => 'Денес(?:\\s+во)?',
    'diff_yesterday' => 'вчера',
    'diff_yesterday_regexp' => 'Вчера(?:\\s+во)?',
    'diff_tomorrow' => 'утре',
    'diff_tomorrow_regexp' => 'Утре(?:\\s+во)?',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'D.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY H:mm',
        'LLLL' => 'dddd, D MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[Денес во] LT',
        'nextDay' => '[Утре во] LT',
        'nextWeek' => '[Во] dddd [во] LT',
        'lastDay' => '[Вчера во] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0, 3, 6 => '[Изминатата] dddd [во] LT',
            default => '[Изминатиот] dddd [во] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        $lastDigit = $number % 10;
        $last2Digits = $number % 100;
        if ($number === 0) {
            return $number.'-ев';
        }
        if ($last2Digits === 0) {
            return $number.'-ен';
        }
        if ($last2Digits > 10 && $last2Digits < 20) {
            return $number.'-ти';
        }
        if ($lastDigit === 1) {
            return $number.'-ви';
        }
        if ($lastDigit === 2) {
            return $number.'-ри';
        }
        if ($lastDigit === 7 || $lastDigit === 8) {
            return $number.'-ми';
        }

        return $number.'-ти';
    },
    'months' => ['јануари', 'февруари', 'март', 'април', 'мај', 'јуни', 'јули', 'август', 'септември', 'октомври', 'ноември', 'декември'],
    'months_short' => ['јан', 'фев', 'мар', 'апр', 'мај', 'јун', 'јул', 'авг', 'сеп', 'окт', 'ное', 'дек'],
    'weekdays' => ['недела', 'понеделник', 'вторник', 'среда', 'четврток', 'петок', 'сабота'],
    'weekdays_short' => ['нед', 'пон', 'вто', 'сре', 'чет', 'пет', 'саб'],
    'weekdays_min' => ['нe', 'пo', 'вт', 'ср', 'че', 'пе', 'сa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' и '],
    'meridiem' => ['АМ', 'ПМ'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Glavić
 * - Milos Sakovic
 */

use Carbon\CarbonInterface;
use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'sr');
    }, 'sr_Cyrl_ME');
}
// @codeCoverageIgnoreEnd

return [
    'year' => ':count година|:count године|:count година',
    'y' => ':count г.',
    'month' => ':count мјесец|:count мјесеца|:count мјесеци',
    'm' => ':count мј.',
    'week' => ':count недјеља|:count недјеље|:count недјеља',
    'w' => ':count нед.',
    'day' => ':count дан|:count дана|:count дана',
    'd' => ':count д.',
    'hour' => ':count сат|:count сата|:count сати',
    'h' => ':count ч.',
    'minute' => ':count минут|:count минута|:count минута',
    'min' => ':count мин.',
    'second' => ':count секунд|:count секунде|:count секунди',
    's' => ':count сек.',
    'ago' => 'прије :time',
    'from_now' => 'за :time',
    'after' => ':time након',
    'before' => ':time прије',

    'year_from_now' => ':count годину|:count године|:count година',
    'year_ago' => ':count годину|:count године|:count година',

    'week_from_now' => ':count недјељу|:count недјеље|:count недјеља',
    'week_ago' => ':count недјељу|:count недјеље|:count недјеља',

    'diff_now' => 'управо сада',
    'diff_today' => 'данас',
    'diff_today_regexp' => 'данас(?:\\s+у)?',
    'diff_yesterday' => 'јуче',
    'diff_yesterday_regexp' => 'јуче(?:\\s+у)?',
    'diff_tomorrow' => 'сутра',
    'diff_tomorrow_regexp' => 'сутра(?:\\s+у)?',
    'diff_before_yesterday' => 'прекјуче',
    'diff_after_tomorrow' => 'прекосјутра',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY H:mm',
        'LLLL' => 'dddd, D. MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[данас у] LT',
        'nextDay' => '[сутра у] LT',
        'nextWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[у недељу у] LT',
            3 => '[у среду у] LT',
            6 => '[у суботу у] LT',
            default => '[у] dddd [у] LT',
        },
        'lastDay' => '[јуче у] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[прошле недеље у] LT',
            1 => '[прошлог понедељка у] LT',
            2 => '[прошлог уторка у] LT',
            3 => '[прошле среде у] LT',
            4 => '[прошлог четвртка у] LT',
            5 => '[прошлог петка у] LT',
            default => '[прошле суботе у] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
    'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
    'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
    'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
    'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' и '],
    'meridiem' => ['АМ', 'ПМ'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['icheheavo', 'ichamthi'],
    'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
    'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Ijm', 'Jmo'],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Dec'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/fy.php', [
    'formats' => [
        'L' => 'DD-MM-YY',
    ],
    'months' => ['Jannewaris', 'Febrewaris', 'Maart', 'April', 'Maaie', 'Juny', 'July', 'Augustus', 'Septimber', 'Oktober', 'Novimber', 'Desimber'],
    'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Snein', 'Moandei', 'Tiisdei', 'Woansdei', 'Tongersdei', 'Freed', 'Sneon'],
    'weekdays_short' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'],
    'weekdays_min' => ['Sn', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'Sn'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['sárúwá', 'cɛɛ́nko'],
    'weekdays' => ['sɔ́ndǝ', 'lǝndí', 'maadí', 'mɛkrɛdí', 'jǝǝdí', 'júmbá', 'samdí'],
    'weekdays_short' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
    'weekdays_min' => ['sɔ́n', 'lǝn', 'maa', 'mɛk', 'jǝǝ', 'júm', 'sam'],
    'months' => ['ŋwíí a ntɔ́ntɔ', 'ŋwíí akǝ bɛ́ɛ', 'ŋwíí akǝ ráá', 'ŋwíí akǝ nin', 'ŋwíí akǝ táan', 'ŋwíí akǝ táafɔk', 'ŋwíí akǝ táabɛɛ', 'ŋwíí akǝ táaraa', 'ŋwíí akǝ táanin', 'ŋwíí akǝ ntɛk', 'ŋwíí akǝ ntɛk di bɔ́k', 'ŋwíí akǝ ntɛk di bɛ́ɛ'],
    'months_short' => ['ŋ1', 'ŋ2', 'ŋ3', 'ŋ4', 'ŋ5', 'ŋ6', 'ŋ7', 'ŋ8', 'ŋ9', 'ŋ10', 'ŋ11', 'ŋ12'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Dieter Sting
 * - François B
 * - Maxime VALY
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/fr.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/lo.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/pa.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/M/yy',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY, h:mm a',
        'LLLL' => 'dddd, D MMMM YYYY, h:mm a',
    ],
    'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
    'months_short' => ['ਜਨ', 'ਫ਼ਰ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾ', 'ਅਗ', 'ਸਤੰ', 'ਅਕਤੂ', 'ਨਵੰ', 'ਦਸੰ'],
    'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁੱਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨਿੱਚਰਵਾਰ'],
    'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕਰ', 'ਸ਼ਨਿੱਚਰ'],
    'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗ', 'ਬੁੱਧ', 'ਵੀਰ', 'ਸ਼ੁੱਕ', 'ਸ਼ਨਿੱ'],
    'weekend' => [0, 0],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kunal Marwaha
 * - Josh Soref
 * - Jørn Ølmheim
 * - Craig Patik
 * - bustta
 * - François B
 * - Tim Fish
 * - Claire Coloma
 * - Steven Heinrich
 * - JD Isaacks
 * - Raphael Amorim
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'diff_before_yesterday' => 'anteayer',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'MM/DD/YYYY',
        'LL' => 'MMMM [de] D [de] YYYY',
        'LLL' => 'MMMM [de] D [de] YYYY h:mm A',
        'LLLL' => 'dddd, MMMM [de] D [de] YYYY h:mm A',
    ],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - MOHAN M U
 * - François B
 * - rajeevnaikte
 */
return [
    'year' => '{1}:count ವರ್ಷ|[-Inf,Inf]:count ವರ್ಷಗಳು',
    'a_year' => '{1}ಒಂದು ವರ್ಷ|[-Inf,Inf]:count ವರ್ಷಗಳು',
    'month' => ':count ತಿಂಗಳು',
    'a_month' => '{1}ಒಂದು ತಿಂಗಳು|[-Inf,Inf]:count ತಿಂಗಳು',
    'week' => '{1}:count ವಾರ|[-Inf,Inf]:count ವಾರಗಳು',
    'a_week' => '{1}ಒಂದು ವಾರ|[-Inf,Inf]:count ವಾರಗಳು',
    'day' => '{1}:count ದಿನ|[-Inf,Inf]:count ದಿನಗಳು',
    'a_day' => '{1}ಒಂದು ದಿನ|[-Inf,Inf]:count ದಿನಗಳು',
    'hour' => '{1}:count ಗಂಟೆ|[-Inf,Inf]:count ಗಂಟೆಗಳು',
    'a_hour' => '{1}ಒಂದು ಗಂಟೆ|[-Inf,Inf]:count ಗಂಟೆಗಳು',
    'minute' => '{1}:count ನಿಮಿಷ|[-Inf,Inf]:count ನಿಮಿಷಗಳು',
    'a_minute' => '{1}ಒಂದು ನಿಮಿಷ|[-Inf,Inf]:count ನಿಮಿಷಗಳು',
    'second' => '{0,1}:count ಸೆಕೆಂಡ್|[-Inf,Inf]:count ಸೆಕೆಂಡುಗಳು',
    'a_second' => '{0,1}ಕೆಲವು ಕ್ಷಣಗಳು|[-Inf,Inf]:count ಸೆಕೆಂಡುಗಳು',
    'ago' => ':time ಹಿಂದೆ',
    'from_now' => ':time ನಂತರ',
    'diff_now' => 'ಈಗ',
    'diff_today' => 'ಇಂದು',
    'diff_yesterday' => 'ನಿನ್ನೆ',
    'diff_tomorrow' => 'ನಾಳೆ',
    'formats' => [
        'LT' => 'A h:mm',
        'LTS' => 'A h:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
    ],
    'calendar' => [
        'sameDay' => '[ಇಂದು] LT',
        'nextDay' => '[ನಾಳೆ] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[ನಿನ್ನೆ] LT',
        'lastWeek' => '[ಕೊನೆಯ] dddd, LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberನೇ',
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'ರಾತ್ರಿ';
        }
        if ($hour < 10) {
            return 'ಬೆಳಿಗ್ಗೆ';
        }
        if ($hour < 17) {
            return 'ಮಧ್ಯಾಹ್ನ';
        }
        if ($hour < 20) {
            return 'ಸಂಜೆ';
        }

        return 'ರಾತ್ರಿ';
    },
    'months' => ['ಜನವರಿ', 'ಫೆಬ್ರವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'],
    'months_short' => ['ಜನ', 'ಫೆಬ್ರ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂ', 'ಅಕ್ಟೋ', 'ನವೆಂ', 'ಡಿಸೆಂ'],
    'weekdays' => ['ಭಾನುವಾರ', 'ಸೋಮವಾರ', 'ಮಂಗಳವಾರ', 'ಬುಧವಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರವಾರ', 'ಶನಿವಾರ'],
    'weekdays_short' => ['ಭಾನು', 'ಸೋಮ', 'ಮಂಗಳ', 'ಬುಧ', 'ಗುರು', 'ಶುಕ್ರ', 'ಶನಿ'],
    'weekdays_min' => ['ಭಾ', 'ಸೋ', 'ಮಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
    'list' => ', ',
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Serhan Apaydın
 * - Dominika
 */
return [
    'year' => '{1}wa’ DIS|:count DIS',
    'month' => '{1}wa’ jar|:count jar',
    'week' => '{1}wa’ hogh|:count hogh',
    'day' => '{1}wa’ jaj|:count jaj',
    'hour' => '{1}wa’ rep|:count rep',
    'minute' => '{1}wa’ tup|:count tup',
    'second' => '{1}puS lup|:count lup',
    'ago' => static function ($time) {
        $output = strtr($time, [
            'jaj' => 'Hu’',
            'jar' => 'wen',
            'DIS' => 'ben',
        ]);

        return $output === $time ? "$time ret" : $output;
    },
    'from_now' => static function ($time) {
        $output = strtr($time, [
            'jaj' => 'leS',
            'jar' => 'waQ',
            'DIS' => 'nem',
        ]);

        return $output === $time ? "$time pIq" : $output;
    },
    'diff_yesterday' => 'wa’Hu’',
    'diff_today' => 'DaHjaj',
    'diff_tomorrow' => 'wa’leS',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[DaHjaj] LT',
        'nextDay' => '[wa’leS] LT',
        'nextWeek' => 'LLL',
        'lastDay' => '[wa’Hu’] LT',
        'lastWeek' => 'LLL',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['tera’ jar wa’', 'tera’ jar cha’', 'tera’ jar wej', 'tera’ jar loS', 'tera’ jar vagh', 'tera’ jar jav', 'tera’ jar Soch', 'tera’ jar chorgh', 'tera’ jar Hut', 'tera’ jar wa’maH', 'tera’ jar wa’maH wa’', 'tera’ jar wa’maH cha’'],
    'months_short' => ['jar wa’', 'jar cha’', 'jar wej', 'jar loS', 'jar vagh', 'jar jav', 'jar Soch', 'jar chorgh', 'jar Hut', 'jar wa’maH', 'jar wa’maH wa’', 'jar wa’maH cha’'],
    'weekdays' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
    'weekdays_short' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
    'weekdays_min' => ['lojmItjaj', 'DaSjaj', 'povjaj', 'ghItlhjaj', 'loghjaj', 'buqjaj', 'ghInjaj'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' ’ej '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Tim Fish
 * - JD Isaacks
 */
return [
    'year' => ':count jier|:count jierren',
    'a_year' => 'ien jier|:count jierren',
    'y' => ':count j',
    'month' => ':count moanne|:count moannen',
    'a_month' => 'ien moanne|:count moannen',
    'm' => ':count moa.',
    'week' => ':count wike|:count wiken',
    'a_week' => 'in wike|:count wiken',
    'a' => ':count w.',
    'day' => ':count dei|:count dagen',
    'a_day' => 'ien dei|:count dagen',
    'd' => ':count d.',
    'hour' => ':count oere|:count oeren',
    'a_hour' => 'ien oere|:count oeren',
    'h' => ':count o.',
    'minute' => ':count minút|:count minuten',
    'a_minute' => 'ien minút|:count minuten',
    'min' => ':count min.',
    'second' => ':count sekonde|:count sekonden',
    'a_second' => 'in pear sekonden|:count sekonden',
    's' => ':count s.',
    'ago' => ':time lyn',
    'from_now' => 'oer :time',
    'diff_yesterday' => 'juster',
    'diff_yesterday_regexp' => 'juster(?:\\s+om)?',
    'diff_today' => 'hjoed',
    'diff_today_regexp' => 'hjoed(?:\\s+om)?',
    'diff_tomorrow' => 'moarn',
    'diff_tomorrow_regexp' => 'moarn(?:\\s+om)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD-MM-YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[hjoed om] LT',
        'nextDay' => '[moarn om] LT',
        'nextWeek' => 'dddd [om] LT',
        'lastDay' => '[juster om] LT',
        'lastWeek' => '[ôfrûne] dddd [om] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
    },
    'months' => ['jannewaris', 'febrewaris', 'maart', 'april', 'maaie', 'juny', 'july', 'augustus', 'septimber', 'oktober', 'novimber', 'desimber'],
    'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
    'mmm_suffix' => '.',
    'weekdays' => ['snein', 'moandei', 'tiisdei', 'woansdei', 'tongersdei', 'freed', 'sneon'],
    'weekdays_short' => ['si.', 'mo.', 'ti.', 'wo.', 'to.', 'fr.', 'so.'],
    'weekdays_min' => ['Si', 'Mo', 'Ti', 'Wo', 'To', 'Fr', 'So'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' en '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 6,
    'weekend' => [5, 6],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - mestremuten
 * - François B
 * - Marc Ordinas i Llopis
 * - Pere Orga
 * - JD Isaacks
 * - Quentí
 * - Víctor Díaz
 * - Xavi
 * - qcardona
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count any|:count anys',
    'a_year' => 'un any|:count anys',
    'y' => ':count any|:count anys',
    'month' => ':count mes|:count mesos',
    'a_month' => 'un mes|:count mesos',
    'm' => ':count mes|:count mesos',
    'week' => ':count setmana|:count setmanes',
    'a_week' => 'una setmana|:count setmanes',
    'w' => ':count setmana|:count setmanes',
    'day' => ':count dia|:count dies',
    'a_day' => 'un dia|:count dies',
    'd' => ':count d',
    'hour' => ':count hora|:count hores',
    'a_hour' => 'una hora|:count hores',
    'h' => ':count h',
    'minute' => ':count minut|:count minuts',
    'a_minute' => 'un minut|:count minuts',
    'min' => ':count min',
    'second' => ':count segon|:count segons',
    'a_second' => 'uns segons|:count segons',
    's' => ':count s',
    'ago' => 'fa :time',
    'from_now' => 'd\'aquí a :time',
    'after' => ':time després',
    'before' => ':time abans',
    'diff_now' => 'ara mateix',
    'diff_today' => 'avui',
    'diff_today_regexp' => 'avui(?:\\s+a)?(?:\\s+les)?',
    'diff_yesterday' => 'ahir',
    'diff_yesterday_regexp' => 'ahir(?:\\s+a)?(?:\\s+les)?',
    'diff_tomorrow' => 'demà',
    'diff_tomorrow_regexp' => 'demà(?:\\s+a)?(?:\\s+les)?',
    'diff_before_yesterday' => 'abans d\'ahir',
    'diff_after_tomorrow' => 'demà passat',
    'period_recurrences' => ':count cop|:count cops',
    'period_interval' => 'cada :interval',
    'period_start_date' => 'de :date',
    'period_end_date' => 'fins a :date',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM [de] YYYY',
        'LLL' => 'D MMMM [de] YYYY [a les] H:mm',
        'LLLL' => 'dddd D MMMM [de] YYYY [a les] H:mm',
    ],
    'calendar' => [
        'sameDay' => static function (CarbonInterface $current) {
            return '[avui a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
        },
        'nextDay' => static function (CarbonInterface $current) {
            return '[demà a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
        },
        'nextWeek' => static function (CarbonInterface $current) {
            return 'dddd [a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
        },
        'lastDay' => static function (CarbonInterface $current) {
            return '[ahir a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
        },
        'lastWeek' => static function (CarbonInterface $current) {
            return '[el] dddd [passat a '.($current->hour !== 1 ? 'les' : 'la').'] LT';
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return $number.(
            ($period === 'w' || $period === 'W') ? 'a' : (
                ($number === 1) ? 'r' : (
                    ($number === 2) ? 'n' : (
                        ($number === 3) ? 'r' : (
                            ($number === 4) ? 't' : 'è'
                        )
                    )
                )
            )
        );
    },
    'months' => ['de gener', 'de febrer', 'de març', 'd\'abril', 'de maig', 'de juny', 'de juliol', 'd\'agost', 'de setembre', 'd\'octubre', 'de novembre', 'de desembre'],
    'months_standalone' => ['gener', 'febrer', 'març', 'abril', 'maig', 'juny', 'juliol', 'agost', 'setembre', 'octubre', 'novembre', 'desembre'],
    'months_short' => ['de gen.', 'de febr.', 'de març', 'd\'abr.', 'de maig', 'de juny', 'de jul.', 'd\'ag.', 'de set.', 'd\'oct.', 'de nov.', 'de des.'],
    'months_short_standalone' => ['gen.', 'febr.', 'març', 'abr.', 'maig', 'juny', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 'des.'],
    'months_regexp' => '/(D[oD]?[\s,]+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte'],
    'weekdays_short' => ['dg.', 'dl.', 'dt.', 'dc.', 'dj.', 'dv.', 'ds.'],
    'weekdays_min' => ['dg', 'dl', 'dt', 'dc', 'dj', 'dv', 'ds'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' i '],
    'meridiem' => ['a. m.', 'p. m.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Quentí
 * - Quentin PAGÈS
 */
// @codeCoverageIgnoreStart
use Symfony\Component\Translation\PluralizationRules;

if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
    PluralizationRules::set(static function ($number) {
        return $number == 1 ? 0 : 1;
    }, 'oc');
}
// @codeCoverageIgnoreEnd

return [
    'year' => ':count an|:count ans',
    'a_year' => 'un an|:count ans',
    'y' => ':count an|:count ans',
    'month' => ':count mes|:count meses',
    'a_month' => 'un mes|:count meses',
    'm' => ':count mes|:count meses',
    'week' => ':count setmana|:count setmanas',
    'a_week' => 'una setmana|:count setmanas',
    'w' => ':count setmana|:count setmanas',
    'day' => ':count jorn|:count jorns',
    'a_day' => 'un jorn|:count jorns',
    'd' => ':count jorn|:count jorns',
    'hour' => ':count ora|:count oras',
    'a_hour' => 'una ora|:count oras',
    'h' => ':count ora|:count oras',
    'minute' => ':count minuta|:count minutas',
    'a_minute' => 'una minuta|:count minutas',
    'min' => ':count minuta|:count minutas',
    'second' => ':count segonda|:count segondas',
    'a_second' => 'una segonda|:count segondas',
    's' => ':count segonda|:count segondas',
    'ago' => 'fa :time',
    'from_now' => 'd\'aquí :time',
    'after' => ':time aprèp',
    'before' => ':time abans',
    'diff_now' => 'ara meteis',
    'diff_today' => 'Uèi',
    'diff_today_regexp' => 'Uèi(?:\\s+a)?',
    'diff_yesterday' => 'ièr',
    'diff_yesterday_regexp' => 'Ièr(?:\\s+a)?',
    'diff_tomorrow' => 'deman',
    'diff_tomorrow_regexp' => 'Deman(?:\\s+a)?',
    'diff_before_yesterday' => 'ièr delà',
    'diff_after_tomorrow' => 'deman passat',
    'period_recurrences' => ':count còp|:count còps',
    'period_interval' => 'cada :interval',
    'period_start_date' => 'de :date',
    'period_end_date' => 'fins a :date',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM [de] YYYY',
        'LLL' => 'D MMMM [de] YYYY [a] H:mm',
        'LLLL' => 'dddd D MMMM [de] YYYY [a] H:mm',
    ],
    'calendar' => [
        'sameDay' => '[Uèi a] LT',
        'nextDay' => '[Deman a] LT',
        'nextWeek' => 'dddd [a] LT',
        'lastDay' => '[Ièr a] LT',
        'lastWeek' => 'dddd [passat a] LT',
        'sameElse' => 'L',
    ],
    'months' => ['de genièr', 'de febrièr', 'de març', 'd\'abrial', 'de mai', 'de junh', 'de julhet', 'd\'agost', 'de setembre', 'd’octòbre', 'de novembre', 'de decembre'],
    'months_standalone' => ['genièr', 'febrièr', 'març', 'abrial', 'mai', 'junh', 'julh', 'agost', 'setembre', 'octòbre', 'novembre', 'decembre'],
    'months_short' => ['gen.', 'feb.', 'març', 'abr.', 'mai', 'junh', 'julh', 'ago.', 'sep.', 'oct.', 'nov.', 'dec.'],
    'weekdays' => ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'],
    'weekdays_short' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
    'weekdays_min' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
    'ordinal' => static function ($number, string $period = '') {
        $ordinal = [1 => 'èr', 2 => 'nd'][(int) $number] ?? 'en';

        // feminine for week, hour, minute, second
        if (preg_match('/^[wWhHgGis]$/', $period)) {
            $ordinal .= 'a';
        }

        return $number.$ordinal;
    },
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' e '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre'],
    'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'set', 'oct', 'nov', 'dic'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat, Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/ur.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'weekdays' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
    'weekdays_short' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
    'weekdays_min' => ['اتوار', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'سنیچر'],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Michael Hohl
 * - sheriffmarley
 * - dennisoderwald
 * - Timo
 * - Karag2006
 * - Pete Scopes (pdscopes)
 */
return [
    'year' => ':count Jahr|:count Jahre',
    'a_year' => 'ein Jahr|:count Jahre',
    'y' => ':count J.',
    'month' => ':count Monat|:count Monate',
    'a_month' => 'ein Monat|:count Monate',
    'm' => ':count Mon.',
    'week' => ':count Woche|:count Wochen',
    'a_week' => 'eine Woche|:count Wochen',
    'w' => ':count Wo.',
    'day' => ':count Tag|:count Tage',
    'a_day' => 'ein Tag|:count Tage',
    'd' => ':count Tg.',
    'hour' => ':count Stunde|:count Stunden',
    'a_hour' => 'eine Stunde|:count Stunden',
    'h' => ':count Std.',
    'minute' => ':count Minute|:count Minuten',
    'a_minute' => 'eine Minute|:count Minuten',
    'min' => ':count Min.',
    'second' => ':count Sekunde|:count Sekunden',
    'a_second' => 'ein paar Sekunden|:count Sekunden',
    's' => ':count Sek.',
    'millisecond' => ':count Millisekunde|:count Millisekunden',
    'a_millisecond' => 'eine Millisekunde|:count Millisekunden',
    'ms' => ':countms',
    'microsecond' => ':count Mikrosekunde|:count Mikrosekunden',
    'a_microsecond' => 'eine Mikrosekunde|:count Mikrosekunden',
    'µs' => ':countµs',
    'ago' => 'vor :time',
    'from_now' => 'in :time',
    'after' => ':time später',
    'before' => ':time zuvor',

    'year_from_now' => ':count Jahr|:count Jahren',
    'month_from_now' => ':count Monat|:count Monaten',
    'week_from_now' => ':count Woche|:count Wochen',
    'day_from_now' => ':count Tag|:count Tagen',
    'year_ago' => ':count Jahr|:count Jahren',
    'month_ago' => ':count Monat|:count Monaten',
    'week_ago' => ':count Woche|:count Wochen',
    'day_ago' => ':count Tag|:count Tagen',
    'a_year_from_now' => 'ein Jahr|:count Jahren',
    'a_month_from_now' => 'ein Monat|:count Monaten',
    'a_week_from_now' => 'eine Woche|:count Wochen',
    'a_day_from_now' => 'ein Tag|:count Tagen',
    'a_year_ago' => 'ein Jahr|:count Jahren',
    'a_month_ago' => 'ein Monat|:count Monaten',
    'a_week_ago' => 'eine Woche|:count Wochen',
    'a_day_ago' => 'ein Tag|:count Tagen',

    'diff_now' => 'Gerade eben',
    'diff_today' => 'heute',
    'diff_today_regexp' => 'heute(?:\\s+um)?',
    'diff_yesterday' => 'Gestern',
    'diff_yesterday_regexp' => 'gestern(?:\\s+um)?',
    'diff_tomorrow' => 'Morgen',
    'diff_tomorrow_regexp' => 'morgen(?:\\s+um)?',
    'diff_before_yesterday' => 'Vorgestern',
    'diff_after_tomorrow' => 'Übermorgen',

    'period_recurrences' => 'einmal|:count mal',
    'period_interval' => static function (string $interval = '') {
        /** @var string $output */
        $output = preg_replace('/^(ein|eine|1)\s+/u', '', $interval);

        if (preg_match('/^(ein|1)( Monat| Mon.| Tag| Tg.)/u', $interval)) {
            return "jeden $output";
        }

        if (preg_match('/^(ein|1)( Jahr| J.)/u', $interval)) {
            return "jedes $output";
        }

        return "jede $output";
    },
    'period_start_date' => 'von :date',
    'period_end_date' => 'bis :date',

    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D. MMMM YYYY HH:mm',
    ],

    'calendar' => [
        'sameDay' => '[heute um] LT [Uhr]',
        'nextDay' => '[morgen um] LT [Uhr]',
        'nextWeek' => 'dddd [um] LT [Uhr]',
        'lastDay' => '[gestern um] LT [Uhr]',
        'lastWeek' => '[letzten] dddd [um] LT [Uhr]',
        'sameElse' => 'L',
    ],

    'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    'weekdays' => ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
    'weekdays_short' => ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],
    'weekdays_min' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    'ordinal' => ':number.',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' und '],
    'ordinal_words' => [
        'of' => 'im',
        'first' => 'erster',
        'second' => 'zweiter',
        'third' => 'dritter',
        'fourth' => 'vierten',
        'fifth' => 'fünfter',
        'last' => 'letzten',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/pt.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Dmitriy Shabanov
 * - JD Isaacks
 * - Inoyatulloh
 * - Jamshid
 * - aarkhipov
 * - Philippe Vaucher
 * - felixthemagnificent
 * - Tsutomu Kuroda
 * - tjku
 * - Max Melentiev
 * - Juanito Fatas
 * - Alisher Ulugbekov
 * - Ergashev Adizbek
 */
return [
    'year' => ':count йил',
    'a_year' => '{1}бир йил|:count йил',
    'y' => ':count й',
    'month' => ':count ой',
    'a_month' => '{1}бир ой|:count ой',
    'm' => ':count о',
    'week' => ':count ҳафта',
    'a_week' => '{1}бир ҳафта|:count ҳафта',
    'w' => ':count ҳ',
    'day' => ':count кун',
    'a_day' => '{1}бир кун|:count кун',
    'd' => ':count к',
    'hour' => ':count соат',
    'a_hour' => '{1}бир соат|:count соат',
    'h' => ':count с',
    'minute' => ':count дақиқа',
    'a_minute' => '{1}бир дақиқа|:count дақиқа',
    'min' => ':count д',
    'second' => ':count сония',
    'a_second' => '{1}сония|:count сония',
    's' => ':count с',
    'ago' => ':time аввал',
    'from_now' => 'Якин :time ичида',
    'after' => ':timeдан кейин',
    'before' => ':time олдин',
    'diff_now' => 'ҳозир',
    'diff_today' => 'Бугун',
    'diff_today_regexp' => 'Бугун(?:\\s+соат)?',
    'diff_yesterday' => 'Кеча',
    'diff_yesterday_regexp' => 'Кеча(?:\\s+соат)?',
    'diff_tomorrow' => 'Эртага',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'D MMMM YYYY, dddd HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Бугун соат] LT [да]',
        'nextDay' => '[Эртага] LT [да]',
        'nextWeek' => 'dddd [куни соат] LT [да]',
        'lastDay' => '[Кеча соат] LT [да]',
        'lastWeek' => '[Утган] dddd [куни соат] LT [да]',
        'sameElse' => 'L',
    ],
    'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'],
    'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'weekdays' => ['якшанба', 'душанба', 'сешанба', 'чоршанба', 'пайшанба', 'жума', 'шанба'],
    'weekdays_short' => ['якш', 'душ', 'сеш', 'чор', 'пай', 'жум', 'шан'],
    'weekdays_min' => ['як', 'ду', 'се', 'чо', 'па', 'жу', 'ша'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['эрталаб', 'кечаси'],
    'list' => [', ', ' ва '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Pablo Saratxaga pablo@mandrakesoft.com
 */
return [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD. MM. YY',
        'LL' => 'DD di MMMM dal YYYY',
        'LLL' => 'DD di MMM HH:mm',
        'LLLL' => 'DD di MMMM dal YYYY HH:mm',
    ],
    'months' => ['zenâr', 'fevrâr', 'març', 'avrîl', 'mai', 'jugn', 'lui', 'avost', 'setembar', 'otubar', 'novembar', 'dicembar'],
    'months_short' => ['zen', 'fev', 'mar', 'avr', 'mai', 'jug', 'lui', 'avo', 'set', 'otu', 'nov', 'dic'],
    'weekdays' => ['domenie', 'lunis', 'martars', 'miercus', 'joibe', 'vinars', 'sabide'],
    'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
    'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'joi', 'vin', 'sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'year' => ':count an',
    'month' => ':count mês',
    'week' => ':count setemane',
    'day' => ':count zornade',
    'hour' => ':count ore',
    'minute' => ':count minût',
    'second' => ':count secont',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 * - Cătălin Georgescu
 * - Valentin Ivaşcu (oriceon)
 */
return [
    'year' => ':count an|:count ani|:count ani',
    'a_year' => 'un an|:count ani|:count ani',
    'y' => ':count a.',
    'month' => ':count lună|:count luni|:count luni',
    'a_month' => 'o lună|:count luni|:count luni',
    'm' => ':count l.',
    'week' => ':count săptămână|:count săptămâni|:count săptămâni',
    'a_week' => 'o săptămână|:count săptămâni|:count săptămâni',
    'w' => ':count săp.',
    'day' => ':count zi|:count zile|:count zile',
    'a_day' => 'o zi|:count zile|:count zile',
    'd' => ':count z.',
    'hour' => ':count oră|:count ore|:count ore',
    'a_hour' => 'o oră|:count ore|:count ore',
    'h' => ':count o.',
    'minute' => ':count minut|:count minute|:count minute',
    'a_minute' => 'un minut|:count minute|:count minute',
    'min' => ':count m.',
    'second' => ':count secundă|:count secunde|:count secunde',
    'a_second' => 'câteva secunde|:count secunde|:count secunde',
    's' => ':count sec.',
    'ago' => ':time în urmă',
    'from_now' => 'peste :time',
    'after' => 'peste :time',
    'before' => 'acum :time',
    'diff_now' => 'acum',
    'diff_today' => 'azi',
    'diff_today_regexp' => 'azi(?:\\s+la)?',
    'diff_yesterday' => 'ieri',
    'diff_yesterday_regexp' => 'ieri(?:\\s+la)?',
    'diff_tomorrow' => 'mâine',
    'diff_tomorrow_regexp' => 'mâine(?:\\s+la)?',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY H:mm',
        'LLLL' => 'dddd, D MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[azi la] LT',
        'nextDay' => '[mâine la] LT',
        'nextWeek' => 'dddd [la] LT',
        'lastDay' => '[ieri la] LT',
        'lastWeek' => '[fosta] dddd [la] LT',
        'sameElse' => 'L',
    ],
    'months' => ['ianuarie', 'februarie', 'martie', 'aprilie', 'mai', 'iunie', 'iulie', 'august', 'septembrie', 'octombrie', 'noiembrie', 'decembrie'],
    'months_short' => ['ian.', 'feb.', 'mar.', 'apr.', 'mai', 'iun.', 'iul.', 'aug.', 'sept.', 'oct.', 'nov.', 'dec.'],
    'weekdays' => ['duminică', 'luni', 'marți', 'miercuri', 'joi', 'vineri', 'sâmbătă'],
    'weekdays_short' => ['dum', 'lun', 'mar', 'mie', 'joi', 'vin', 'sâm'],
    'weekdays_min' => ['du', 'lu', 'ma', 'mi', 'jo', 'vi', 'sâ'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' și '],
    'meridiem' => ['a.m.', 'p.m.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - kostas
 * - François B
 * - Tim Fish
 * - Chiel Robben
 * - Claire Coloma
 * - Steven Heinrich
 * - JD Isaacks
 * - Raphael Amorim
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'diff_before_yesterday' => 'anteayer',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'LLL' => 'D [de] MMMM [de] YYYY h:mm A',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm A',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/az.php', [
    'meridiem' => ['a', 'p'],
    'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    'weekdays_short' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
    'weekdays_min' => ['B.', 'B.E.', 'Ç.A.', 'Ç.', 'C.A.', 'C.', 'Ş.'],
    'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
    'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'D MMMM YYYY, dddd HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Danish Standards Association  bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/gsw.php', [
    'meridiem' => ['vorm.', 'nam.'],
    'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    'first_day_of_week' => 1,
    'formats' => [
        'LLL' => 'Do MMMM YYYY HH:mm',
        'LLLL' => 'dddd, Do MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['a', 'p'],
    'weekdays' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sabadu'],
    'weekdays_short' => ['dum', 'sig', 'ter', 'kua', 'kin', 'ses', 'sab'],
    'weekdays_min' => ['du', 'si', 'te', 'ku', 'ki', 'se', 'sa'],
    'weekdays_standalone' => ['dumingu', 'sigunda-fera', 'tersa-fera', 'kuarta-fera', 'kinta-fera', 'sesta-fera', 'sábadu'],
    'months' => ['Janeru', 'Febreru', 'Marsu', 'Abril', 'Maiu', 'Junhu', 'Julhu', 'Agostu', 'Setenbru', 'Otubru', 'Nuvenbru', 'Dizenbru'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Otu', 'Nuv', 'Diz'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D [di] MMMM [di] YYYY HH:mm',
        'LLLL' => 'dddd, D [di] MMMM [di] YYYY HH:mm',
    ],

    'year' => ':count otunu', // less reliable
    'y' => ':count otunu', // less reliable
    'a_year' => ':count otunu', // less reliable

    'week' => ':count día dumingu', // less reliable
    'w' => ':count día dumingu', // less reliable
    'a_week' => ':count día dumingu', // less reliable

    'day' => ':count diâ', // less reliable
    'd' => ':count diâ', // less reliable
    'a_day' => ':count diâ', // less reliable

    'minute' => ':count sugundu', // less reliable
    'min' => ':count sugundu', // less reliable
    'a_minute' => ':count sugundu', // less reliable

    'second' => ':count dós', // less reliable
    's' => ':count dós', // less reliable
    'a_second' => ':count dós', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Glavić
 * - Milos Sakovic
 */

use Carbon\CarbonInterface;
use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'sr');
    }, 'sr_Latn_ME');
}
// @codeCoverageIgnoreEnd

return array_replace_recursive(require __DIR__.'/sr.php', [
    'month' => ':count mjesec|:count mjeseca|:count mjeseci',
    'week' => ':count nedjelja|:count nedjelje|:count nedjelja',
    'second' => ':count sekund|:count sekunde|:count sekundi',
    'ago' => 'prije :time',
    'from_now' => 'za :time',
    'after' => ':time nakon',
    'before' => ':time prije',
    'week_from_now' => ':count nedjelju|:count nedjelje|:count nedjelja',
    'week_ago' => ':count nedjelju|:count nedjelje|:count nedjelja',
    'second_ago' => ':count sekund|:count sekunde|:count sekundi',
    'diff_tomorrow' => 'sjutra',
    'calendar' => [
        'nextDay' => '[sjutra u] LT',
        'nextWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[u nedjelju u] LT',
            3 => '[u srijedu u] LT',
            6 => '[u subotu u] LT',
            default => '[u] dddd [u] LT',
        },
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[prošle nedjelje u] LT',
            1 => '[prošle nedjelje u] LT',
            2 => '[prošlog utorka u] LT',
            3 => '[prošle srijede u] LT',
            4 => '[prošlog četvrtka u] LT',
            5 => '[prošlog petka u] LT',
            default => '[prošle subote u] LT',
        },
    ],
    'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
    'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Matthias Dieter Wallno:fer libc-locales@sourceware.org
 */
return require __DIR__.'/de.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - pablo@mandriva.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM, YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM, YYYY HH:mm',
    ],
    'months' => ['Janairu', 'Faburairu', 'Maris', 'Afirilu', 'Mayu', 'Yuni', 'Yuli', 'Agusta', 'Satumba', 'Oktoba', 'Nuwamba', 'Disamba'],
    'months_short' => ['Jan', 'Fab', 'Mar', 'Afi', 'May', 'Yun', 'Yul', 'Agu', 'Sat', 'Okt', 'Nuw', 'Dis'],
    'weekdays' => ['Lahadi', 'Litini', 'Talata', 'Laraba', 'Alhamis', 'Jumaʼa', 'Asabar'],
    'weekdays_short' => ['Lah', 'Lit', 'Tal', 'Lar', 'Alh', 'Jum', 'Asa'],
    'weekdays_min' => ['Lh', 'Li', 'Ta', 'Lr', 'Al', 'Ju', 'As'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => 'shekara :count',
    'y' => 'shekara :count',
    'a_year' => 'shekara :count',

    'month' => ':count wátàa',
    'm' => ':count wátàa',
    'a_month' => ':count wátàa',

    'week' => ':count mako',
    'w' => ':count mako',
    'a_week' => ':count mako',

    'day' => ':count rana',
    'd' => ':count rana',
    'a_day' => ':count rana',

    'hour' => ':count áwàa',
    'h' => ':count áwàa',
    'a_hour' => ':count áwàa',

    'minute' => 'minti :count',
    'min' => 'minti :count',
    'a_minute' => 'minti :count',

    'second' => ':count ná bíyú',
    's' => ':count ná bíyú',
    'a_second' => ':count ná bíyú',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fo.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - JD Isaacks
 */
return [
    'year' => ':count ҫул',
    'a_year' => '{1}пӗр ҫул|:count ҫул',
    'month' => ':count уйӑх',
    'a_month' => '{1}пӗр уйӑх|:count уйӑх',
    'week' => ':count эрне',
    'a_week' => '{1}пӗр эрне|:count эрне',
    'day' => ':count кун',
    'a_day' => '{1}пӗр кун|:count кун',
    'hour' => ':count сехет',
    'a_hour' => '{1}пӗр сехет|:count сехет',
    'minute' => ':count минут',
    'a_minute' => '{1}пӗр минут|:count минут',
    'second' => ':count ҫеккунт',
    'a_second' => '{1}пӗр-ик ҫеккунт|:count ҫеккунт',
    'ago' => ':time каялла',
    'from_now' => static function ($time) {
        return $time.(preg_match('/сехет$/u', $time) ? 'рен' : (preg_match('/ҫул/', $time) ? 'тан' : 'ран'));
    },
    'diff_yesterday' => 'Ӗнер',
    'diff_today' => 'Паян',
    'diff_tomorrow' => 'Ыран',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD-MM-YYYY',
        'LL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
        'LLL' => 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
        'LLLL' => 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Паян] LT [сехетре]',
        'nextDay' => '[Ыран] LT [сехетре]',
        'nextWeek' => '[Ҫитес] dddd LT [сехетре]',
        'lastDay' => '[Ӗнер] LT [сехетре]',
        'lastWeek' => '[Иртнӗ] dddd LT [сехетре]',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number-мӗш',
    'months' => ['кӑрлач', 'нарӑс', 'пуш', 'ака', 'май', 'ҫӗртме', 'утӑ', 'ҫурла', 'авӑн', 'юпа', 'чӳк', 'раштав'],
    'months_short' => ['кӑр', 'нар', 'пуш', 'ака', 'май', 'ҫӗр', 'утӑ', 'ҫур', 'авн', 'юпа', 'чӳк', 'раш'],
    'weekdays' => ['вырсарникун', 'тунтикун', 'ытларикун', 'юнкун', 'кӗҫнерникун', 'эрнекун', 'шӑматкун'],
    'weekdays_short' => ['выр', 'тун', 'ытл', 'юн', 'кӗҫ', 'эрн', 'шӑм'],
    'weekdays_min' => ['вр', 'тн', 'ыт', 'юн', 'кҫ', 'эр', 'шм'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' тата '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kunal Marwaha
 * - Josh Soref
 * - François B
 * - kc
 */
return [
    'year' => ':count సంవత్సరం|:count సంవత్సరాలు',
    'a_year' => 'ఒక సంవత్సరం|:count సంవత్సరాలు',
    'y' => ':count సం.',
    'month' => ':count నెల|:count నెలలు',
    'a_month' => 'ఒక నెల|:count నెలలు',
    'm' => ':count నెల|:count నెల.',
    'week' => ':count వారం|:count వారాలు',
    'a_week' => 'ఒక వారం|:count వారాలు',
    'w' => ':count వార.|:count వారా.',
    'day' => ':count రోజు|:count రోజులు',
    'a_day' => 'ఒక రోజు|:count రోజులు',
    'd' => ':count రోజు|:count రోజు.',
    'hour' => ':count గంట|:count గంటలు',
    'a_hour' => 'ఒక గంట|:count గంటలు',
    'h' => ':count గం.',
    'minute' => ':count నిమిషం|:count నిమిషాలు',
    'a_minute' => 'ఒక నిమిషం|:count నిమిషాలు',
    'min' => ':count నిమి.',
    'second' => ':count సెకను|:count సెకన్లు',
    'a_second' => 'కొన్ని క్షణాలు|:count సెకన్లు',
    's' => ':count సెక.',
    'ago' => ':time క్రితం',
    'from_now' => ':time లో',
    'diff_now' => 'ప్రస్తుతం',
    'diff_today' => 'నేడు',
    'diff_yesterday' => 'నిన్న',
    'diff_tomorrow' => 'రేపు',
    'formats' => [
        'LT' => 'A h:mm',
        'LTS' => 'A h:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
    ],
    'calendar' => [
        'sameDay' => '[నేడు] LT',
        'nextDay' => '[రేపు] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[నిన్న] LT',
        'lastWeek' => '[గత] dddd, LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberవ',
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'రాత్రి';
        }
        if ($hour < 10) {
            return 'ఉదయం';
        }
        if ($hour < 17) {
            return 'మధ్యాహ్నం';
        }
        if ($hour < 20) {
            return 'సాయంత్రం';
        }

        return ' రాత్రి';
    },
    'months' => ['జనవరి', 'ఫిబ్రవరి', 'మార్చి', 'ఏప్రిల్', 'మే', 'జూన్', 'జూలై', 'ఆగస్టు', 'సెప్టెంబర్', 'అక్టోబర్', 'నవంబర్', 'డిసెంబర్'],
    'months_short' => ['జన.', 'ఫిబ్ర.', 'మార్చి', 'ఏప్రి.', 'మే', 'జూన్', 'జూలై', 'ఆగ.', 'సెప్.', 'అక్టో.', 'నవ.', 'డిసె.'],
    'weekdays' => ['ఆదివారం', 'సోమవారం', 'మంగళవారం', 'బుధవారం', 'గురువారం', 'శుక్రవారం', 'శనివారం'],
    'weekdays_short' => ['ఆది', 'సోమ', 'మంగళ', 'బుధ', 'గురు', 'శుక్ర', 'శని'],
    'weekdays_min' => ['ఆ', 'సో', 'మం', 'బు', 'గు', 'శు', 'శ'],
    'list' => ', ',
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/yue_HK.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/miq_NI.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/dz_BT.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

$months = [
    'جنوری',
    'فروری',
    'مارچ',
    'اپریل',
    'مئی',
    'جون',
    'جولائی',
    'اگست',
    'ستمبر',
    'اکتوبر',
    'نومبر',
    'دسمبر',
];

$weekdays = [
    'اتوار',
    'پیر',
    'منگل',
    'بدھ',
    'جمعرات',
    'جمعہ',
    'ہفتہ',
];

/*
 * Authors:
 * - Sawood Alam
 * - Mehshan
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - tjku
 * - Zaid Akram
 * - Max Melentiev
 * - hafezdivandari
 * - Hossein Jabbari
 * - nimamo
 * - Usman Zahid
 */
return [
    'year' => ':count '.'سال',
    'a_year' => 'ایک سال|:count سال',
    'month' => ':count '.'ماہ',
    'a_month' => 'ایک ماہ|:count ماہ',
    'week' => ':count '.'ہفتے',
    'day' => ':count '.'دن',
    'a_day' => 'ایک دن|:count دن',
    'hour' => ':count '.'گھنٹے',
    'a_hour' => 'ایک گھنٹہ|:count گھنٹے',
    'minute' => ':count '.'منٹ',
    'a_minute' => 'ایک منٹ|:count منٹ',
    'second' => ':count '.'سیکنڈ',
    'a_second' => 'چند سیکنڈ|:count سیکنڈ',
    'ago' => ':time قبل',
    'from_now' => ':time بعد',
    'after' => ':time بعد',
    'before' => ':time پہلے',
    'diff_now' => 'اب',
    'diff_today' => 'آج',
    'diff_today_regexp' => 'آج(?:\\s+بوقت)?',
    'diff_yesterday' => 'گزشتہ کل',
    'diff_yesterday_regexp' => 'گذشتہ(?:\\s+روز)?(?:\\s+بوقت)?',
    'diff_tomorrow' => 'آئندہ کل',
    'diff_tomorrow_regexp' => 'کل(?:\\s+بوقت)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd، D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[آج بوقت] LT',
        'nextDay' => '[کل بوقت] LT',
        'nextWeek' => 'dddd [بوقت] LT',
        'lastDay' => '[گذشتہ روز بوقت] LT',
        'lastWeek' => '[گذشتہ] dddd [بوقت] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['صبح', 'شام'],
    'months' => $months,
    'months_short' => $months,
    'weekdays' => $weekdays,
    'weekdays_short' => $weekdays,
    'weekdays_min' => $weekdays,
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => ['، ', ' اور '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ro.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY, HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    'weekdays_short' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    'weekdays_min' => ['ꕞꕌꔵ', 'ꗳꗡꘉ', 'ꕚꕞꕚ', 'ꕉꕞꕒ', 'ꕉꔤꕆꕢ', 'ꕉꔤꕀꕮ', 'ꔻꔬꔳ'],
    'months' => ['ꖨꖕ ꕪꕴ ꔞꔀꕮꕊ', 'ꕒꕡꖝꖕ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞꔤ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋꕔꕿ ꕸꖃꗏ', 'ꖨꖕ ꕪꕴ ꗏꖺꕮꕊ'],
    'months_short' => ['ꖨꖕꔞ', 'ꕒꕡ', 'ꕾꖺ', 'ꖢꖕ', 'ꖑꕱ', 'ꖱꘋ', 'ꖱꕞ', 'ꗛꔕ', 'ꕢꕌ', 'ꕭꖃ', 'ꔞꘋ', 'ꖨꖕꗏ'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd, D MMMM YYYY h:mm a',
    ],

    'year' => ':count ꕀ', // less reliable
    'y' => ':count ꕀ', // less reliable
    'a_year' => ':count ꕀ', // less reliable

    'second' => ':count ꗱꕞꕯꕊ', // less reliable
    's' => ':count ꗱꕞꕯꕊ', // less reliable
    'a_second' => ':count ꗱꕞꕯꕊ', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Information from native speakers Hannah Sarvasy nungon.localization@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['jenuari', 'febuari', 'mas', 'epril', 'mei', 'jun', 'julai', 'ögus', 'septemba', 'öktoba', 'nöwemba', 'diksemba'],
    'months_short' => ['jen', 'feb', 'mas', 'epr', 'mei', 'jun', 'jul', 'ögu', 'sep', 'ökt', 'nöw', 'dis'],
    'weekdays' => ['sönda', 'mönda', 'sinda', 'mitiwö', 'sogipbono', 'nenggo', 'söndanggie'],
    'weekdays_short' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'],
    'weekdays_min' => ['sön', 'mön', 'sin', 'mit', 'soi', 'nen', 'sab'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/nl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - Azri Jamil
 * - JD Isaacks
 * - Josh Soref
 * - Azri Jamil
 * - Hariadi Hinta
 * - Ashraf Kamarudin
 */
return [
    'year' => ':count tahun',
    'a_year' => '{1}setahun|[-Inf,Inf]:count tahun',
    'y' => ':count tahun',
    'month' => ':count bulan',
    'a_month' => '{1}sebulan|[-Inf,Inf]:count bulan',
    'm' => ':count bulan',
    'week' => ':count minggu',
    'a_week' => '{1}seminggu|[-Inf,Inf]:count minggu',
    'w' => ':count minggu',
    'day' => ':count hari',
    'a_day' => '{1}sehari|[-Inf,Inf]:count hari',
    'd' => ':count hari',
    'hour' => ':count jam',
    'a_hour' => '{1}sejam|[-Inf,Inf]:count jam',
    'h' => ':count jam',
    'minute' => ':count minit',
    'a_minute' => '{1}seminit|[-Inf,Inf]:count minit',
    'min' => ':count minit',
    'second' => ':count saat',
    'a_second' => '{1}beberapa saat|[-Inf,Inf]:count saat',
    'millisecond' => ':count milisaat',
    'a_millisecond' => '{1}semilisaat|[-Inf,Inf]:count milliseconds',
    'microsecond' => ':count mikrodetik',
    'a_microsecond' => '{1}semikrodetik|[-Inf,Inf]:count mikrodetik',
    's' => ':count saat',
    'ago' => ':time yang lepas',
    'from_now' => ':time dari sekarang',
    'after' => ':time kemudian',
    'before' => ':time sebelum',
    'diff_now' => 'sekarang',
    'diff_today' => 'Hari',
    'diff_today_regexp' => 'Hari(?:\\s+ini)?(?:\\s+pukul)?',
    'diff_yesterday' => 'semalam',
    'diff_yesterday_regexp' => 'Semalam(?:\\s+pukul)?',
    'diff_tomorrow' => 'esok',
    'diff_tomorrow_regexp' => 'Esok(?:\\s+pukul)?',
    'diff_before_yesterday' => 'kelmarin',
    'diff_after_tomorrow' => 'lusa',
    'formats' => [
        'LT' => 'HH.mm',
        'LTS' => 'HH.mm.ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY [pukul] HH.mm',
        'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
    ],
    'calendar' => [
        'sameDay' => '[Hari ini pukul] LT',
        'nextDay' => '[Esok pukul] LT',
        'nextWeek' => 'dddd [pukul] LT',
        'lastDay' => '[Kelmarin pukul] LT',
        'lastWeek' => 'dddd [lepas pukul] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 1) {
            return 'tengah malam';
        }

        if ($hour < 12) {
            return 'pagi';
        }

        if ($hour < 13) {
            return 'tengah hari';
        }

        if ($hour < 19) {
            return 'petang';
        }

        return 'malam';
    },
    'months' => ['Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ogs', 'Sep', 'Okt', 'Nov', 'Dis'],
    'weekdays' => ['Ahad', 'Isnin', 'Selasa', 'Rabu', 'Khamis', 'Jumaat', 'Sabtu'],
    'weekdays_short' => ['Ahd', 'Isn', 'Sel', 'Rab', 'Kha', 'Jum', 'Sab'],
    'weekdays_min' => ['Ah', 'Is', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' dan '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/aa_DJ.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ta.php', [
    'formats' => [
        'LT' => 'a h:mm',
        'LTS' => 'a h:mm:ss',
        'L' => 'D/M/yy',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM, YYYY, a h:mm',
        'LLLL' => 'dddd, D MMMM, YYYY, a h:mm',
    ],
    'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
    'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
    'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'],
    'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'first_day_of_week' => 1,
    'meridiem' => ['மு.ப', 'பி.ப'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - JD Isaacks
 */
return [
    'year' => ':count വർഷം',
    'a_year' => 'ഒരു വർഷം|:count വർഷം',
    'month' => ':count മാസം',
    'a_month' => 'ഒരു മാസം|:count മാസം',
    'week' => ':count ആഴ്ച',
    'a_week' => 'ഒരാഴ്ച|:count ആഴ്ച',
    'day' => ':count ദിവസം',
    'a_day' => 'ഒരു ദിവസം|:count ദിവസം',
    'hour' => ':count മണിക്കൂർ',
    'a_hour' => 'ഒരു മണിക്കൂർ|:count മണിക്കൂർ',
    'minute' => ':count മിനിറ്റ്',
    'a_minute' => 'ഒരു മിനിറ്റ്|:count മിനിറ്റ്',
    'second' => ':count സെക്കൻഡ്',
    'a_second' => 'അൽപ നിമിഷങ്ങൾ|:count സെക്കൻഡ്',
    'ago' => ':time മുൻപ്',
    'from_now' => ':time കഴിഞ്ഞ്',
    'diff_now' => 'ഇപ്പോൾ',
    'diff_today' => 'ഇന്ന്',
    'diff_yesterday' => 'ഇന്നലെ',
    'diff_tomorrow' => 'നാളെ',
    'formats' => [
        'LT' => 'A h:mm -നു',
        'LTS' => 'A h:mm:ss -നു',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm -നു',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm -നു',
    ],
    'calendar' => [
        'sameDay' => '[ഇന്ന്] LT',
        'nextDay' => '[നാളെ] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[ഇന്നലെ] LT',
        'lastWeek' => '[കഴിഞ്ഞ] dddd, LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'രാത്രി';
        }
        if ($hour < 12) {
            return 'രാവിലെ';
        }
        if ($hour < 17) {
            return 'ഉച്ച കഴിഞ്ഞ്';
        }
        if ($hour < 20) {
            return 'വൈകുന്നേരം';
        }

        return 'രാത്രി';
    },
    'months' => ['ജനുവരി', 'ഫെബ്രുവരി', 'മാർച്ച്', 'ഏപ്രിൽ', 'മേയ്', 'ജൂൺ', 'ജൂലൈ', 'ഓഗസ്റ്റ്', 'സെപ്റ്റംബർ', 'ഒക്ടോബർ', 'നവംബർ', 'ഡിസംബർ'],
    'months_short' => ['ജനു.', 'ഫെബ്രു.', 'മാർ.', 'ഏപ്രി.', 'മേയ്', 'ജൂൺ', 'ജൂലൈ.', 'ഓഗ.', 'സെപ്റ്റ.', 'ഒക്ടോ.', 'നവം.', 'ഡിസം.'],
    'weekdays' => ['ഞായറാഴ്ച', 'തിങ്കളാഴ്ച', 'ചൊവ്വാഴ്ച', 'ബുധനാഴ്ച', 'വ്യാഴാഴ്ച', 'വെള്ളിയാഴ്ച', 'ശനിയാഴ്ച'],
    'weekdays_short' => ['ഞായർ', 'തിങ്കൾ', 'ചൊവ്വ', 'ബുധൻ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
    'weekdays_min' => ['ഞാ', 'തി', 'ചൊ', 'ബു', 'വ്യാ', 'വെ', 'ശ'],
    'list' => ', ',
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - tjku
 * - Max Melentiev
 * - Juanito Fatas
 * - Tsutomu Kuroda
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Nicolás Hock Isaza
 * - sebastian de castelberg
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'Do MMMM YYYY',
        'LLL' => 'Do MMMM, HH:mm [Uhr]',
        'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]',
    ],
    'year' => ':count onn|:count onns',
    'month' => ':count mais',
    'week' => ':count emna|:count emnas',
    'day' => ':count di|:count dis',
    'hour' => ':count oura|:count ouras',
    'minute' => ':count minuta|:count minutas',
    'second' => ':count secunda|:count secundas',
    'weekdays' => ['dumengia', 'glindesdi', 'mardi', 'mesemna', 'gievgia', 'venderdi', 'sonda'],
    'weekdays_short' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
    'weekdays_min' => ['du', 'gli', 'ma', 'me', 'gie', 've', 'so'],
    'months' => ['schaner', 'favrer', 'mars', 'avrigl', 'matg', 'zercladur', 'fanadur', 'avust', 'settember', 'october', 'november', 'december'],
    'months_short' => ['schan', 'favr', 'mars', 'avr', 'matg', 'zercl', 'fan', 'avust', 'sett', 'oct', 'nov', 'dec'],
    'meridiem' => ['avantmezdi', 'suentermezdi'],
    'list' => [', ', ' e '],
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mhr_RU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Fidel Pita
 * - JD Isaacks
 * - Diego Vilariño
 * - Sebastian Thierer
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count ano|:count anos',
    'a_year' => 'un ano|:count anos',
    'y' => ':count a.',
    'month' => ':count mes|:count meses',
    'a_month' => 'un mes|:count meses',
    'm' => ':count mes.',
    'week' => ':count semana|:count semanas',
    'a_week' => 'unha semana|:count semanas',
    'w' => ':count sem.',
    'day' => ':count día|:count días',
    'a_day' => 'un día|:count días',
    'd' => ':count d.',
    'hour' => ':count hora|:count horas',
    'a_hour' => 'unha hora|:count horas',
    'h' => ':count h.',
    'minute' => ':count minuto|:count minutos',
    'a_minute' => 'un minuto|:count minutos',
    'min' => ':count min.',
    'second' => ':count segundo|:count segundos',
    'a_second' => 'uns segundos|:count segundos',
    's' => ':count seg.',
    'ago' => 'hai :time',
    'from_now' => static function ($time) {
        if (str_starts_with($time, 'un')) {
            return "n$time";
        }

        return "en $time";
    },
    'diff_now' => 'agora',
    'diff_today' => 'hoxe',
    'diff_today_regexp' => 'hoxe(?:\\s+ás)?',
    'diff_yesterday' => 'onte',
    'diff_yesterday_regexp' => 'onte(?:\\s+á)?',
    'diff_tomorrow' => 'mañá',
    'diff_tomorrow_regexp' => 'mañá(?:\\s+ás)?',
    'after' => ':time despois',
    'before' => ':time antes',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D [de] MMMM [de] YYYY',
        'LLL' => 'D [de] MMMM [de] YYYY H:mm',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => static function (CarbonInterface $current) {
            return '[hoxe '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
        },
        'nextDay' => static function (CarbonInterface $current) {
            return '[mañá '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
        },
        'nextWeek' => static function (CarbonInterface $current) {
            return 'dddd ['.($current->hour !== 1 ? 'ás' : 'á').'] LT';
        },
        'lastDay' => static function (CarbonInterface $current) {
            return '[onte '.($current->hour !== 1 ? 'á' : 'a').'] LT';
        },
        'lastWeek' => static function (CarbonInterface $current) {
            return '[o] dddd [pasado '.($current->hour !== 1 ? 'ás' : 'á').'] LT';
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberº',
    'months' => ['xaneiro', 'febreiro', 'marzo', 'abril', 'maio', 'xuño', 'xullo', 'agosto', 'setembro', 'outubro', 'novembro', 'decembro'],
    'months_short' => ['xan.', 'feb.', 'mar.', 'abr.', 'mai.', 'xuñ.', 'xul.', 'ago.', 'set.', 'out.', 'nov.', 'dec.'],
    'weekdays' => ['domingo', 'luns', 'martes', 'mércores', 'xoves', 'venres', 'sábado'],
    'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mér.', 'xov.', 'ven.', 'sáb.'],
    'weekdays_min' => ['do', 'lu', 'ma', 'mé', 'xo', 've', 'sá'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' e '],
    'meridiem' => ['a.m.', 'p.m.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Serhan Apaydın
 * - JD Isaacks
 * - Malinda Weerasinghe (MalindaWMD)
 */
return [
    'year' => '{1}වසර 1|වසර :count',
    'a_year' => '{1}වසරක්|වසර :count',
    'month' => '{1}මාස 1|මාස :count',
    'a_month' => '{1}මාසය|මාස :count',
    'week' => '{1}සති 1|සති :count',
    'a_week' => '{1}සතියක්|සති :count',
    'day' => '{1}දින 1|දින :count',
    'a_day' => '{1}දිනක්|දින :count',
    'hour' => '{1}පැය 1|පැය :count',
    'a_hour' => '{1}පැයක්|පැය :count',
    'minute' => '{1}මිනිත්තු 1|මිනිත්තු :count',
    'a_minute' => '{1}මිනිත්තුවක්|මිනිත්තු :count',
    'second' => '{1}තත්පර 1|තත්පර :count',
    'a_second' => '{1}තත්පර කිහිපයකට|තත්පර :count',
    'ago' => ':time කට පෙර',
    'from_now' => static function ($time) {
        if (preg_match('/දින \d+/u', $time)) {
            return $time.' න්';
        }

        return $time.' කින්';
    },
    'before' => ':time කට පෙර',
    'after' => static function ($time) {
        if (preg_match('/දින \d+/u', $time)) {
            return $time.' න්';
        }

        return $time.' කින්';
    },
    'diff_now' => 'දැන්',
    'diff_today' => 'අද',
    'diff_yesterday' => 'ඊයේ',
    'diff_tomorrow' => 'හෙට',
    'formats' => [
        'LT' => 'a h:mm',
        'LTS' => 'a h:mm:ss',
        'L' => 'YYYY/MM/DD',
        'LL' => 'YYYY MMMM D',
        'LLL' => 'YYYY MMMM D, a h:mm',
        'LLLL' => 'YYYY MMMM D [වැනි] dddd, a h:mm:ss',
    ],
    'calendar' => [
        'sameDay' => '[අද] LT[ට]',
        'nextDay' => '[හෙට] LT[ට]',
        'nextWeek' => 'dddd LT[ට]',
        'lastDay' => '[ඊයේ] LT[ට]',
        'lastWeek' => '[පසුගිය] dddd LT[ට]',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number වැනි',
    'meridiem' => ['පෙර වරු', 'පස් වරු', 'පෙ.ව.', 'ප.ව.'],
    'months' => ['ජනවාරි', 'පෙබරවාරි', 'මාර්තු', 'අප්‍රේල්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝස්තු', 'සැප්තැම්බර්', 'ඔක්තෝබර්', 'නොවැම්බර්', 'දෙසැම්බර්'],
    'months_short' => ['ජන', 'පෙබ', 'මාර්', 'අප්', 'මැයි', 'ජූනි', 'ජූලි', 'අගෝ', 'සැප්', 'ඔක්', 'නොවැ', 'දෙසැ'],
    'weekdays' => ['ඉරිදා', 'සඳුදා', 'අඟහරුවාදා', 'බදාදා', 'බ්‍රහස්පතින්දා', 'සිකුරාදා', 'සෙනසුරාදා'],
    'weekdays_short' => ['ඉරි', 'සඳු', 'අඟ', 'බදා', 'බ්‍රහ', 'සිකු', 'සෙන'],
    'weekdays_min' => ['ඉ', 'ස', 'අ', 'බ', 'බ්‍ර', 'සි', 'සෙ'],
    'first_day_of_week' => 1,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Vikram-enyota
 */
return [
    'year' => ':count वर्ष',
    'y' => ':count वर्ष',
    'month' => ':count महिना|:count महिने',
    'm' => ':count महिना|:count महिने',
    'week' => ':count आठवडा|:count आठवडे',
    'w' => ':count आठवडा|:count आठवडे',
    'day' => ':count दिवस',
    'd' => ':count दिवस',
    'hour' => ':count तास',
    'h' => ':count तास',
    'minute' => ':count मिनिटे',
    'min' => ':count मिनिटे',
    'second' => ':count सेकंद',
    's' => ':count सेकंद',

    'ago' => ':timeपूर्वी',
    'from_now' => ':timeमध्ये',
    'before' => ':timeपूर्वी',
    'after' => ':timeनंतर',

    'diff_now' => 'आत्ता',
    'diff_today' => 'आज',
    'diff_yesterday' => 'काल',
    'diff_tomorrow' => 'उद्या',

    'formats' => [
        'LT' => 'A h:mm वाजता',
        'LTS' => 'A h:mm:ss वाजता',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm वाजता',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm वाजता',
    ],

    'calendar' => [
        'sameDay' => '[आज] LT',
        'nextDay' => '[उद्या] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[काल] LT',
        'lastWeek' => '[मागील] dddd, LT',
        'sameElse' => 'L',
    ],

    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'रात्री';
        }
        if ($hour < 10) {
            return 'सकाळी';
        }
        if ($hour < 17) {
            return 'दुपारी';
        }
        if ($hour < 20) {
            return 'सायंकाळी';
        }

        return 'रात्री';
    },

    'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ऑगस्ट', 'सप्टेंबर', 'ऑक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
    'months_short' => ['जाने.', 'फेब्रु.', 'मार्च.', 'एप्रि.', 'मे.', 'जून.', 'जुलै.', 'ऑग.', 'सप्टें.', 'ऑक्टो.', 'नोव्हें.', 'डिसें.'],
    'weekdays' => ['रविवार', 'सोमवार', 'मंगळवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],
    'weekdays_short' => ['रवि', 'सोम', 'मंगळ', 'बुध', 'गुरू', 'शुक्र', 'शनि'],
    'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],
    'list' => [', ', ' आणि '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/id.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/be.php', [
    'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'мая', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'],
    'months_short' => ['сту', 'лют', 'сак', 'кра', 'мая', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
    'weekdays' => ['Нядзеля', 'Панядзелак', 'Аўторак', 'Серада', 'Чацвер', 'Пятніца', 'Субота'],
    'weekdays_short' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'],
    'weekdays_min' => ['Няд', 'Пан', 'Аўт', 'Срд', 'Чцв', 'Пят', 'Суб'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'first_day_of_week' => 6,
    'weekend' => [5, 6],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hant.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Jon Ashdown
 */
return [
    'year' => ':count bliadhna',
    'a_year' => '{1}bliadhna|:count bliadhna',
    'y' => ':count b.',
    'month' => ':count mìosan',
    'a_month' => '{1}mìos|:count mìosan',
    'm' => ':count ms.',
    'week' => ':count seachdainean',
    'a_week' => '{1}seachdain|:count seachdainean',
    'w' => ':count s.',
    'day' => ':count latha',
    'a_day' => '{1}latha|:count latha',
    'd' => ':count l.',
    'hour' => ':count uairean',
    'a_hour' => '{1}uair|:count uairean',
    'h' => ':count u.',
    'minute' => ':count mionaidean',
    'a_minute' => '{1}mionaid|:count mionaidean',
    'min' => ':count md.',
    'second' => ':count diogan',
    'a_second' => '{1}beagan diogan|:count diogan',
    's' => ':count d.',
    'ago' => 'bho chionn :time',
    'from_now' => 'ann an :time',
    'diff_yesterday' => 'An-dè',
    'diff_yesterday_regexp' => 'An-dè(?:\\s+aig)?',
    'diff_today' => 'An-diugh',
    'diff_today_regexp' => 'An-diugh(?:\\s+aig)?',
    'diff_tomorrow' => 'A-màireach',
    'diff_tomorrow_regexp' => 'A-màireach(?:\\s+aig)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[An-diugh aig] LT',
        'nextDay' => '[A-màireach aig] LT',
        'nextWeek' => 'dddd [aig] LT',
        'lastDay' => '[An-dè aig] LT',
        'lastWeek' => 'dddd [seo chaidh] [aig] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        return $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh'));
    },
    'months' => ['Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'],
    'months_short' => ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'],
    'weekdays' => ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'],
    'weekdays_short' => ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'],
    'weekdays_min' => ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' agus '],
    'meridiem' => ['m', 'f'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/da.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
        'LL' => 'D. MMM YYYY',
        'LLL' => 'D. MMMM YYYY HH.mm',
        'LLLL' => 'dddd [den] D. MMMM YYYY HH.mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com
 */
return require __DIR__.'/pap.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/dsb_DE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory  bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation & Sagalee Oromoo Publishing Co. Inc.    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'dd-MMM-YYYY',
        'LLL' => 'dd MMMM YYYY HH:mm',
        'LLLL' => 'dddd, MMMM D, YYYY HH:mm',
    ],
    'months' => ['Amajjii', 'Guraandhala', 'Bitooteessa', 'Elba', 'Caamsa', 'Waxabajjii', 'Adooleessa', 'Hagayya', 'Fuulbana', 'Onkololeessa', 'Sadaasa', 'Muddee'],
    'months_short' => ['Ama', 'Gur', 'Bit', 'Elb', 'Cam', 'Wax', 'Ado', 'Hag', 'Ful', 'Onk', 'Sad', 'Mud'],
    'weekdays' => ['Dilbata', 'Wiixata', 'Qibxata', 'Roobii', 'Kamiisa', 'Jimaata', 'Sanbata'],
    'weekdays_short' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
    'weekdays_min' => ['Dil', 'Wix', 'Qib', 'Rob', 'Kam', 'Jim', 'San'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['WD', 'WB'],

    'year' => 'wggoota :count',
    'y' => 'wggoota :count',
    'a_year' => 'wggoota :count',

    'month' => 'ji’a :count',
    'm' => 'ji’a :count',
    'a_month' => 'ji’a :count',

    'week' => 'torban :count',
    'w' => 'torban :count',
    'a_week' => 'torban :count',

    'day' => 'guyyaa :count',
    'd' => 'guyyaa :count',
    'a_day' => 'guyyaa :count',

    'hour' => 'saʼaatii :count',
    'h' => 'saʼaatii :count',
    'a_hour' => 'saʼaatii :count',

    'minute' => 'daqiiqaa :count',
    'min' => 'daqiiqaa :count',
    'a_minute' => 'daqiiqaa :count',

    'second' => 'sekoondii :count',
    's' => 'sekoondii :count',
    'a_second' => 'sekoondii :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'meridiem' => ['mat.', 'soir'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Estelle Comment
 */
return [
    'year' => 'san :count',
    'a_year' => '{1}san kelen|san :count',
    'y' => 'san :count',
    'month' => 'kalo :count',
    'a_month' => '{1}kalo kelen|kalo :count',
    'm' => 'k. :count',
    'week' => 'dɔgɔkun :count',
    'a_week' => 'dɔgɔkun kelen',
    'w' => 'd. :count',
    'day' => 'tile :count',
    'd' => 't. :count',
    'a_day' => '{1}tile kelen|tile :count',
    'hour' => 'lɛrɛ :count',
    'a_hour' => '{1}lɛrɛ kelen|lɛrɛ :count',
    'h' => 'l. :count',
    'minute' => 'miniti :count',
    'a_minute' => '{1}miniti kelen|miniti :count',
    'min' => 'm. :count',
    'second' => 'sekondi :count',
    'a_second' => '{1}sanga dama dama|sekondi :count',
    's' => 'sek. :count',
    'ago' => 'a bɛ :time bɔ',
    'from_now' => ':time kɔnɔ',
    'diff_today' => 'Bi',
    'diff_yesterday' => 'Kunu',
    'diff_yesterday_regexp' => 'Kunu(?:\\s+lɛrɛ)?',
    'diff_tomorrow' => 'Sini',
    'diff_tomorrow_regexp' => 'Sini(?:\\s+lɛrɛ)?',
    'diff_today_regexp' => 'Bi(?:\\s+lɛrɛ)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'MMMM [tile] D [san] YYYY',
        'LLL' => 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
        'LLLL' => 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Bi lɛrɛ] LT',
        'nextDay' => '[Sini lɛrɛ] LT',
        'nextWeek' => 'dddd [don lɛrɛ] LT',
        'lastDay' => '[Kunu lɛrɛ] LT',
        'lastWeek' => 'dddd [tɛmɛnen lɛrɛ] LT',
        'sameElse' => 'L',
    ],
    'months' => ['Zanwuyekalo', 'Fewuruyekalo', 'Marisikalo', 'Awirilikalo', 'Mɛkalo', 'Zuwɛnkalo', 'Zuluyekalo', 'Utikalo', 'Sɛtanburukalo', 'ɔkutɔburukalo', 'Nowanburukalo', 'Desanburukalo'],
    'months_short' => ['Zan', 'Few', 'Mar', 'Awi', 'Mɛ', 'Zuw', 'Zul', 'Uti', 'Sɛt', 'ɔku', 'Now', 'Des'],
    'weekdays' => ['Kari', 'Ntɛnɛn', 'Tarata', 'Araba', 'Alamisa', 'Juma', 'Sibiri'],
    'weekdays_short' => ['Kar', 'Ntɛ', 'Tar', 'Ara', 'Ala', 'Jum', 'Sib'],
    'weekdays_min' => ['Ka', 'Nt', 'Ta', 'Ar', 'Al', 'Ju', 'Si'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' ni '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - DarkoDevelop
 */
return array_replace_recursive(require __DIR__.'/hr.php', [
    'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
    'weekdays_short' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    'weekdays_min' => ['ned', 'pon', 'uto', 'sri', 'čet', 'pet', 'sub'],
    'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
    'months_short' => ['sij', 'velj', 'ožu', 'tra', 'svi', 'lip', 'srp', 'kol', 'ruj', 'lis', 'stu', 'pro'],
    'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D. M. yy.',
        'LL' => 'D. MMM YYYY.',
        'LLL' => 'D. MMMM YYYY. HH:mm',
        'LLLL' => 'dddd, D. MMMM YYYY. HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/it.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Arne Goetje arne@canonical.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
    'months' => ['1goe̍h', '2goe̍h', '3goe̍h', '4goe̍h', '5goe̍h', '6goe̍h', '7goe̍h', '8goe̍h', '9goe̍h', '10goe̍h', '11goe̍h', '12goe̍h'],
    'months_short' => ['1g', '2g', '3g', '4g', '5g', '6g', '7g', '8g', '9g', '10g', '11g', '12g'],
    'weekdays' => ['lé-pài-ji̍t', 'pài-it', 'pài-jī', 'pài-saⁿ', 'pài-sì', 'pài-gō͘', 'pài-la̍k'],
    'weekdays_short' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'],
    'weekdays_min' => ['lp', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['téng-po͘', 'ē-po͘'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['jannewarie', 'fibberwarie', 'miert', 'eprèl', 'meij', 'junie', 'julie', 'augustus', 'september', 'oktober', 'november', 'desember'],
    'months_short' => ['jan', 'fib', 'mie', 'epr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
    'weekdays' => ['zóndig', 'maondig', 'daensdig', 'goonsdig', 'dónderdig', 'vriedig', 'zaoterdig'],
    'weekdays_short' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'],
    'weekdays_min' => ['zón', 'mao', 'dae', 'goo', 'dón', 'vri', 'zao'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'minute' => ':count momênt', // less reliable
    'min' => ':count momênt', // less reliable
    'a_minute' => ':count momênt', // less reliable

    'year' => ':count jaor',
    'y' => ':count jaor',
    'a_year' => ':count jaor',

    'month' => ':count maond',
    'm' => ':count maond',
    'a_month' => ':count maond',

    'week' => ':count waek',
    'w' => ':count waek',
    'a_week' => ':count waek',

    'day' => ':count daag',
    'd' => ':count daag',
    'a_day' => ':count daag',

    'hour' => ':count oer',
    'h' => ':count oer',
    'a_hour' => ':count oer',

    'second' => ':count Secónd',
    's' => ':count Secónd',
    'a_second' => ':count Secónd',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Christopher Dell
 * - Akira Matsuda
 * - Enrique Vidal
 * - Simone Carletti
 * - Henning Kiel
 * - Aaron Patterson
 * - Florian Hanke
 */
return [
    'year' => ':count Johr',
    'month' => ':count Monet',
    'week' => ':count Woche',
    'day' => ':count Tag',
    'hour' => ':count Schtund',
    'minute' => ':count Minute',
    'second' => ':count Sekunde',
    'weekdays' => ['Sunntig', 'Mäntig', 'Ziischtig', 'Mittwuch', 'Dunschtig', 'Friitig', 'Samschtig'],
    'weekdays_short' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'],
    'weekdays_min' => ['Su', 'Mä', 'Zi', 'Mi', 'Du', 'Fr', 'Sa'],
    'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'September', 'Oktober', 'November', 'Dezember'],
    'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    'meridiem' => ['am Vormittag', 'am Namittag'],
    'ordinal' => ':number.',
    'list' => [', ', ' und '],
    'diff_now' => 'now',
    'diff_yesterday' => 'geschter',
    'diff_tomorrow' => 'moorn',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'Do MMMM YYYY',
        'LLL' => 'Do MMMM, HH:mm [Uhr]',
        'LLLL' => 'dddd, Do MMMM YYYY, HH:mm [Uhr]',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['utuko', 'kyiukonyi'],
    'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sgs_LT.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/qu.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fi.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['январы', 'февралы', 'мартъийы', 'апрелы', 'майы', 'июны', 'июлы', 'августы', 'сентябры', 'октябры', 'ноябры', 'декабры'],
    'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
    'weekdays' => ['Хуыцаубон', 'Къуырисæр', 'Дыццæг', 'Æртыццæг', 'Цыппæрæм', 'Майрæмбон', 'Сабат'],
    'weekdays_short' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'],
    'weekdays_min' => ['Хцб', 'Крс', 'Дцг', 'Æрт', 'Цпр', 'Мрб', 'Сбт'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'minute' => ':count гыццыл', // less reliable
    'min' => ':count гыццыл', // less reliable
    'a_minute' => ':count гыццыл', // less reliable

    'second' => ':count æндæр', // less reliable
    's' => ':count æндæр', // less reliable
    'a_second' => ':count æндæр', // less reliable

    'year' => ':count аз',
    'y' => ':count аз',
    'a_year' => ':count аз',

    'month' => ':count мӕй',
    'm' => ':count мӕй',
    'a_month' => ':count мӕй',

    'week' => ':count къуыри',
    'w' => ':count къуыри',
    'a_week' => ':count къуыри',

    'day' => ':count бон',
    'd' => ':count бон',
    'a_day' => ':count бон',

    'hour' => ':count сахат',
    'h' => ':count сахат',
    'a_hour' => ':count сахат',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
    'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'YYYY MMMM D, dddd HH:mm',
    ],

    'year' => ':count yel',
    'y' => ':count yel',
    'a_year' => ':count yel',

    'month' => ':count mul',
    'm' => ':count mul',
    'a_month' => ':count mul',

    'week' => ':count vig',
    'w' => ':count vig',
    'a_week' => ':count vig',

    'day' => ':count del',
    'd' => ':count del',
    'a_day' => ':count del',

    'hour' => ':count düp',
    'h' => ':count düp',
    'a_hour' => ':count düp',

    'minute' => ':count minut',
    'min' => ':count minut',
    'a_minute' => ':count minut',

    'second' => ':count sekun',
    's' => ':count sekun',
    'a_second' => ':count sekun',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ca.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['OD', 'OT'],
    'weekdays' => ['Jumapil', 'Wuok Tich', 'Tich Ariyo', 'Tich Adek', 'Tich Ang’wen', 'Tich Abich', 'Ngeso'],
    'weekdays_short' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
    'weekdays_min' => ['JMP', 'WUT', 'TAR', 'TAD', 'TAN', 'TAB', 'NGS'],
    'months' => ['Dwe mar Achiel', 'Dwe mar Ariyo', 'Dwe mar Adek', 'Dwe mar Ang’wen', 'Dwe mar Abich', 'Dwe mar Auchiel', 'Dwe mar Abiriyo', 'Dwe mar Aboro', 'Dwe mar Ochiko', 'Dwe mar Apar', 'Dwe mar gi achiel', 'Dwe mar Apar gi ariyo'],
    'months_short' => ['DAC', 'DAR', 'DAD', 'DAN', 'DAH', 'DAU', 'DAO', 'DAB', 'DOC', 'DAP', 'DGI', 'DAG'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'year' => 'higni :count',
    'y' => 'higni :count',
    'a_year' => ':higni :count',

    'month' => 'dweche :count',
    'm' => 'dweche :count',
    'a_month' => 'dweche :count',

    'week' => 'jumbe :count',
    'w' => 'jumbe :count',
    'a_week' => 'jumbe :count',

    'day' => 'ndalo :count',
    'd' => 'ndalo :count',
    'a_day' => 'ndalo :count',

    'hour' => 'seche :count',
    'h' => 'seche :count',
    'a_hour' => 'seche :count',

    'minute' => 'dakika :count',
    'min' => 'dakika :count',
    'a_minute' => 'dakika :count',

    'second' => 'nus dakika :count',
    's' => 'nus dakika :count',
    'a_second' => 'nus dakika :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/cmn_TW.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/de.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/tpi_PG.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/to_TO.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/nr_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Jannuaar', 'Feberwaar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    'months_short' => ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    'weekdays' => ['Sünndag', 'Maandag', 'Dingsdag', 'Middeweek', 'Dunnersdag', 'Freedag', 'Sünnavend'],
    'weekdays_short' => ['Sdag', 'Maan', 'Ding', 'Midd', 'Dunn', 'Free', 'Svd.'],
    'weekdays_min' => ['Sd', 'Ma', 'Di', 'Mi', 'Du', 'Fr', 'Sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count Johr',
    'y' => ':countJ',
    'a_year' => '{1}een Johr|:count Johr',

    'month' => ':count Maand',
    'm' => ':countM',
    'a_month' => '{1}een Maand|:count Maand',

    'week' => ':count Week|:count Weken',
    'w' => ':countW',
    'a_week' => '{1}een Week|:count Week|:count Weken',

    'day' => ':count Dag|:count Daag',
    'd' => ':countD',
    'a_day' => '{1}een Dag|:count Dag|:count Daag',

    'hour' => ':count Stünn|:count Stünnen',
    'h' => ':countSt',
    'a_hour' => '{1}een Stünn|:count Stünn|:count Stünnen',

    'minute' => ':count Minuut|:count Minuten',
    'min' => ':countm',
    'a_minute' => '{1}een Minuut|:count Minuut|:count Minuten',

    'second' => ':count Sekunn|:count Sekunnen',
    's' => ':counts',
    'a_second' => 'en poor Sekunnen|:count Sekunn|:count Sekunnen',

    'ago' => 'vör :time',
    'from_now' => 'in :time',
    'before' => ':time vörher',
    'after' => ':time later',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/mas.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/mt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'],
    'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
    'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Mayank Badola
 * - Luke McGregor
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm A',
        'LLLL' => 'dddd, D MMMM YYYY h:mm A',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ልደትሪ', 'ካብኽብቲ', 'ክብላ', 'ፋጅኺሪ', 'ክቢቅሪ', 'ምኪኤል ትጓ̅ኒሪ', 'ኰርኩ', 'ማርያም ትሪ', 'ያኸኒ መሳቅለሪ', 'መተሉ', 'ምኪኤል መሽወሪ', 'ተሕሳስሪ'],
    'months_short' => ['ልደት', 'ካብኽ', 'ክብላ', 'ፋጅኺ', 'ክቢቅ', 'ም/ት', 'ኰር', 'ማርያ', 'ያኸኒ', 'መተሉ', 'ም/ም', 'ተሕሳ'],
    'weekdays' => ['ሰንበር ቅዳዅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ ወሪ ለብዋ', 'ኣምድ', 'ኣርብ', 'ሰንበር ሽጓዅ'],
    'weekdays_short' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'],
    'weekdays_min' => ['ሰ/ቅ', 'ሰኑ', 'ሰሊጝ', 'ለጓ', 'ኣምድ', 'ኣርብ', 'ሰ/ሽ'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ፋዱስ ጃብ', 'ፋዱስ ደምቢ'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['iniru', 'phiwriru', 'marsu', 'awril', 'mayu', 'huniyu', 'huliyu', 'agustu', 'siptiyimri', 'uktuwri', 'nuwiyimri', 'tisiyimri'],
    'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'hun', 'hul', 'agu', 'sip', 'ukt', 'nuw', 'tis'],
    'weekdays' => ['tuminku', 'lunis', 'martis', 'miyirkulis', 'juywis', 'wiyirnis', 'sawatu'],
    'weekdays_short' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'],
    'weekdays_min' => ['tum', 'lun', 'mar', 'miy', 'juy', 'wiy', 'saw'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'minute' => ':count uchuy', // less reliable
    'min' => ':count uchuy', // less reliable
    'a_minute' => ':count uchuy', // less reliable

    'year' => ':count wata',
    'y' => ':count wata',
    'a_year' => ':count wata',

    'month' => ':count killa',
    'm' => ':count killa',
    'a_month' => ':count killa',

    'week' => ':count simana',
    'w' => ':count simana',
    'a_week' => ':count simana',

    'day' => ':count pʼunchaw',
    'd' => ':count pʼunchaw',
    'a_day' => ':count pʼunchaw',

    'hour' => ':count ura',
    'h' => ':count ura',
    'a_hour' => ':count ura',

    'second' => ':count iskay ñiqin',
    's' => ':count iskay ñiqin',
    'a_second' => ':count iskay ñiqin',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Fedora Project Nik Kalach nikka@fedoraproject.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['januario', 'februario', 'martio', 'april', 'maio', 'junio', 'julio', 'augusto', 'septembre', 'octobre', 'novembre', 'decembre'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
    'weekdays' => ['dominica', 'lunedi', 'martedi', 'mercuridi', 'jovedi', 'venerdi', 'sabbato'],
    'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
    'weekdays_min' => ['dom', 'lun', 'mar', 'mer', 'jov', 'ven', 'sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => 'anno :count',
    'y' => 'anno :count',
    'a_year' => 'anno :count',

    'month' => ':count mense',
    'm' => ':count mense',
    'a_month' => ':count mense',

    'week' => ':count septimana',
    'w' => ':count septimana',
    'a_week' => ':count septimana',

    'day' => ':count die',
    'd' => ':count die',
    'a_day' => ':count die',

    'hour' => ':count hora',
    'h' => ':count hora',
    'a_hour' => ':count hora',

    'minute' => ':count minuscule',
    'min' => ':count minuscule',
    'a_minute' => ':count minuscule',

    'second' => ':count secunda',
    's' => ':count secunda',
    'a_second' => ':count secunda',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['ŋ', 'ɣ'],
    'weekdays' => ['kɔsiɖa', 'dzoɖa', 'blaɖa', 'kuɖa', 'yawoɖa', 'fiɖa', 'memleɖa'],
    'weekdays_short' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
    'weekdays_min' => ['kɔs', 'dzo', 'bla', 'kuɖ', 'yaw', 'fiɖ', 'mem'],
    'months' => ['dzove', 'dzodze', 'tedoxe', 'afɔfĩe', 'dama', 'masa', 'siamlɔm', 'deasiamime', 'anyɔnyɔ', 'kele', 'adeɛmekpɔxe', 'dzome'],
    'months_short' => ['dzv', 'dzd', 'ted', 'afɔ', 'dam', 'mas', 'sia', 'dea', 'any', 'kel', 'ade', 'dzm'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'a [ga] h:mm',
        'LTS' => 'a [ga] h:mm:ss',
        'L' => 'M/D/YYYY',
        'LL' => 'MMM D [lia], YYYY',
        'LLL' => 'a [ga] h:mm MMMM D [lia] YYYY',
        'LLLL' => 'a [ga] h:mm dddd, MMMM D [lia] YYYY',
    ],

    'year' => 'ƒe :count',
    'y' => 'ƒe :count',
    'a_year' => 'ƒe :count',

    'month' => 'ɣleti :count',
    'm' => 'ɣleti :count',
    'a_month' => 'ɣleti :count',

    'week' => 'kwasiɖa :count',
    'w' => 'kwasiɖa :count',
    'a_week' => 'kwasiɖa :count',

    'day' => 'ŋkeke :count',
    'd' => 'ŋkeke :count',
    'a_day' => 'ŋkeke :count',

    'hour' => 'gaƒoƒo :count',
    'h' => 'gaƒoƒo :count',
    'a_hour' => 'gaƒoƒo :count',

    'minute' => 'miniti :count', // less reliable
    'min' => 'miniti :count', // less reliable
    'a_minute' => 'miniti :count', // less reliable

    'second' => 'sɛkɛnd :count', // less reliable
    's' => 'sɛkɛnd :count', // less reliable
    'a_second' => 'sɛkɛnd :count', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - csb_PL locale Michal Ostrowski bug-glibc-locales@gnu.org
 */
return [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'MMMM DD, YYYY',
        'LLL' => 'DD MMM HH:mm',
        'LLLL' => 'MMMM DD, YYYY HH:mm',
    ],
    'months' => ['stëcznika', 'gromicznika', 'strëmiannika', 'łżëkwiata', 'maja', 'czerwińca', 'lëpińca', 'zélnika', 'séwnika', 'rujana', 'lëstopadnika', 'gòdnika'],
    'months_short' => ['stë', 'gro', 'str', 'łżë', 'maj', 'cze', 'lëp', 'zél', 'séw', 'ruj', 'lës', 'gòd'],
    'weekdays' => ['niedzela', 'pòniedzôłk', 'wtórk', 'strzoda', 'czwiôrtk', 'piątk', 'sobòta'],
    'weekdays_short' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'],
    'weekdays_min' => ['nie', 'pòn', 'wtó', 'str', 'czw', 'pią', 'sob'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' a téż '],
    'two_words_connector' => ' a téż ',
    'year' => ':count rok',
    'month' => ':count miesiąc',
    'week' => ':count tidzéń',
    'day' => ':count dzéń',
    'hour' => ':count gòdzëna',
    'minute' => ':count minuta',
    'second' => ':count sekunda',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/nb.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ln.php', [
    'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
    'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/nb.php', [
    'formats' => [
        'LL' => 'D. MMM YYYY',
        'LLL' => 'D. MMMM YYYY, HH:mm',
        'LLLL' => 'dddd D. MMMM YYYY, HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
    'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
    'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'],
    'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
    'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ጽባሕ', 'ምሴት'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Mayank Badola
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/lij_IT.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Author:
 * - Abdifatah Abdilahi(@abdifatahz)
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'year' => ':count sanad|:count sanadood',
    'a_year' => 'sanad|:count sanadood',
    'y' => '{1}:countsn|{0}:countsns|[-Inf,Inf]:countsn',
    'month' => ':count bil|:count bilood',
    'a_month' => 'bil|:count bilood',
    'm' => ':countbil',
    'week' => ':count isbuuc',
    'a_week' => 'isbuuc|:count isbuuc',
    'w' => ':countis',
    'day' => ':count maalin|:count maalmood',
    'a_day' => 'maalin|:count maalmood',
    'd' => ':countml',
    'hour' => ':count saac',
    'a_hour' => 'saacad|:count saac',
    'h' => ':countsc',
    'minute' => ':count daqiiqo',
    'a_minute' => 'daqiiqo|:count daqiiqo',
    'min' => ':countdq',
    'second' => ':count ilbidhiqsi',
    'a_second' => 'xooga ilbidhiqsiyo|:count ilbidhiqsi',
    's' => ':countil',
    'ago' => ':time kahor',
    'from_now' => ':time gudahood',
    'after' => ':time kedib',
    'before' => ':time kahor',
    'diff_now' => 'hada',
    'diff_today' => 'maanta',
    'diff_today_regexp' => 'maanta(?:\s+markay\s+(?:tahay|ahayd))?',
    'diff_yesterday' => 'shalayto',
    'diff_yesterday_regexp' => 'shalayto(?:\s+markay\s+ahayd)?',
    'diff_tomorrow' => 'beri',
    'diff_tomorrow_regexp' => 'beri(?:\s+markay\s+tahay)?',
    'diff_before_yesterday' => 'doraato',
    'diff_after_tomorrow' => 'saadanbe',
    'period_recurrences' => 'mar|:count jeer',
    'period_interval' => ':interval kasta',
    'period_start_date' => 'laga bilaabo :date',
    'period_end_date' => 'ilaa :date',
    'months' => ['Janaayo', 'Febraayo', 'Abriil', 'Maajo', 'Juun', 'Luuliyo', 'Agoosto', 'Sebteembar', 'Oktoobar', 'Nofeembar', 'Diseembar'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Abr', 'Mjo', 'Jun', 'Lyo', 'Agt', 'Seb', 'Okt', 'Nof', 'Dis'],
    'weekdays' => ['Axad', 'Isniin', 'Talaada', 'Arbaca', 'Khamiis', 'Jimce', 'Sabti'],
    'weekdays_short' => ['Axd', 'Isn', 'Tal', 'Arb', 'Kha', 'Jim', 'Sbt'],
    'weekdays_min' => ['Ax', 'Is', 'Ta', 'Ar', 'Kh', 'Ji', 'Sa'],
    'list' => [', ', ' and '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'calendar' => [
        'sameDay' => '[Maanta markay tahay] LT',
        'nextDay' => '[Beri markay tahay] LT',
        'nextWeek' => 'dddd [markay tahay] LT',
        'lastDay' => '[Shalay markay ahayd] LT',
        'lastWeek' => '[Hore] dddd [Markay ahayd] LT',
        'sameElse' => 'L',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - ubuntu Myanmar LoCo Team https://ubuntu-mm.net Bone Pyae Sone bone.burma@mail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'OY MMM OD dddd',
    ],
    'months' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'],
    'months_short' => ['လိူၼ်ၵမ်', 'လိူၼ်သၢမ်', 'လိူၼ်သီ', 'လိူၼ်ႁႃႈ', 'လိူၼ်ႁူၵ်း', 'လိူၼ်ၸဵတ်း', 'လိူၼ်ပႅတ်ႇ', 'လိူၼ်ၵဝ်ႈ', 'လိူၼ်သိပ်း', 'လိူၼ်သိပ်းဢိတ်း', 'လိူၼ်သိပ်းဢိတ်းသွင်', 'လိူၼ်ၸဵင်'],
    'weekdays' => ['ဝၼ်းဢႃးတိတ်ႉ', 'ဝၼ်းၸၼ်', 'ဝၼ်း​ဢၢင်း​ၵၢၼ်း', 'ဝၼ်းပူတ်ႉ', 'ဝၼ်းၽတ်း', 'ဝၼ်းသုၵ်း', 'ဝၼ်းသဝ်'],
    'weekdays_short' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'],
    'weekdays_min' => ['တိတ့်', 'ၸၼ်', 'ၵၢၼ်း', 'ပုတ့်', 'ၽတ်း', 'သုၵ်း', 'သဝ်'],
    'alt_numbers' => ['႐႐', '႐႑', '႐႒', '႐႓', '႐႔', '႐႕', '႐႖', '႐႗', '႐႘', '႐႙', '႑႐', '႑႑', '႑႒', '႑႓', '႑႔', '႑႕', '႑႖', '႑႗', '႑႘', '႑႙', '႒႐', '႒႑', '႒႒', '႒႓', '႒႔', '႒႕', '႒႖', '႒႗', '႒႘', '႒႙', '႓႐', '႓႑', '႓႒', '႓႓', '႓႔', '႓႕', '႓႖', '႓႗', '႓႘', '႓႙', '႔႐', '႔႑', '႔႒', '႔႓', '႔႔', '႔႕', '႔႖', '႔႗', '႔႘', '႔႙', '႕႐', '႕႑', '႕႒', '႕႓', '႕႔', '႕႕', '႕႖', '႕႗', '႕႘', '႕႙', '႖႐', '႖႑', '႖႒', '႖႓', '႖႔', '႖႕', '႖႖', '႖႗', '႖႘', '႖႙', '႗႐', '႗႑', '႗႒', '႗႓', '႗႔', '႗႕', '႗႖', '႗႗', '႗႘', '႗႙', '႘႐', '႘႑', '႘႒', '႘႓', '႘႔', '႘႕', '႘႖', '႘႗', '႘႘', '႘႙', '႙႐', '႙႑', '႙႒', '႙႓', '႙႔', '႙႕', '႙႖', '႙႗', '႙႘', '႙႙'],
    'meridiem' => ['ၵၢင်ၼႂ်', 'တၢမ်းၶမ်ႈ'],

    'month' => ':count လိူၼ်', // less reliable
    'm' => ':count လိူၼ်', // less reliable
    'a_month' => ':count လိူၼ်', // less reliable

    'week' => ':count ဝၼ်း', // less reliable
    'w' => ':count ဝၼ်း', // less reliable
    'a_week' => ':count ဝၼ်း', // less reliable

    'hour' => ':count ຕີ', // less reliable
    'h' => ':count ຕີ', // less reliable
    'a_hour' => ':count ຕີ', // less reliable

    'minute' => ':count ເດັກ', // less reliable
    'min' => ':count ເດັກ', // less reliable
    'a_minute' => ':count ເດັກ', // less reliable

    'second' => ':count ဢိုၼ်ႇ', // less reliable
    's' => ':count ဢိုၼ်ႇ', // less reliable
    'a_second' => ':count ဢိုၼ်ႇ', // less reliable

    'year' => ':count ပီ',
    'y' => ':count ပီ',
    'a_year' => ':count ပီ',

    'day' => ':count ກາງວັນ',
    'd' => ':count ກາງວັນ',
    'a_day' => ':count ກາງວັນ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/gv_GB.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['studzienia', 'lutaha', 'sakavika', 'krasavika', 'maja', 'červienia', 'lipienia', 'žniŭnia', 'vieraśnia', 'kastryčnika', 'listapada', 'śniežnia'],
    'months_short' => ['Stu', 'Lut', 'Sak', 'Kra', 'Maj', 'Čer', 'Lip', 'Žni', 'Vie', 'Kas', 'Lis', 'Śni'],
    'weekdays' => ['Niadziela', 'Paniadziełak', 'Aŭtorak', 'Sierada', 'Čaćvier', 'Piatnica', 'Subota'],
    'weekdays_short' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'],
    'weekdays_min' => ['Nia', 'Pan', 'Aŭt', 'Sie', 'Čać', 'Pia', 'Sub'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['Ma', 'Mo'],
    'weekdays' => ['Chumapiri', 'Chumatato', 'Chumaine', 'Chumatano', 'Aramisi', 'Ichuma', 'Esabato'],
    'weekdays_short' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
    'weekdays_min' => ['Cpr', 'Ctt', 'Cmn', 'Cmt', 'Ars', 'Icm', 'Est'],
    'months' => ['Chanuari', 'Feburari', 'Machi', 'Apiriri', 'Mei', 'Juni', 'Chulai', 'Agosti', 'Septemba', 'Okitoba', 'Nobemba', 'Disemba'],
    'months_short' => ['Can', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Cul', 'Agt', 'Sep', 'Okt', 'Nob', 'Dis'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'month' => ':count omotunyi', // less reliable
    'm' => ':count omotunyi', // less reliable
    'a_month' => ':count omotunyi', // less reliable

    'week' => ':count isano naibere', // less reliable
    'w' => ':count isano naibere', // less reliable
    'a_week' => ':count isano naibere', // less reliable

    'second' => ':count ibere', // less reliable
    's' => ':count ibere', // less reliable
    'a_second' => ':count ibere', // less reliable

    'year' => ':count omwaka',
    'y' => ':count omwaka',
    'a_year' => ':count omwaka',

    'day' => ':count rituko',
    'd' => ':count rituko',
    'a_day' => ':count rituko',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Ferikgong', 'Tlhakole', 'Mopitlwe', 'Moranang', 'Motsheganong', 'Seetebosigo', 'Phukwi', 'Phatwe', 'Lwetse', 'Diphalane', 'Ngwanatsele', 'Sedimonthole'],
    'months_short' => ['Fer', 'Tlh', 'Mop', 'Mor', 'Mot', 'See', 'Phu', 'Pha', 'Lwe', 'Dip', 'Ngw', 'Sed'],
    'weekdays' => ['laTshipi', 'Mosupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labotlhano', 'Lamatlhatso'],
    'weekdays_short' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'],
    'weekdays_min' => ['Tsh', 'Mos', 'Bed', 'Rar', 'Ne', 'Tlh', 'Mat'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => 'dingwaga di le :count',
    'y' => 'dingwaga di le :count',
    'a_year' => 'dingwaga di le :count',

    'month' => 'dikgwedi di le :count',
    'm' => 'dikgwedi di le :count',
    'a_month' => 'dikgwedi di le :count',

    'week' => 'dibeke di le :count',
    'w' => 'dibeke di le :count',
    'a_week' => 'dibeke di le :count',

    'day' => 'malatsi :count',
    'd' => 'malatsi :count',
    'a_day' => 'malatsi :count',

    'hour' => 'diura di le :count',
    'h' => 'diura di le :count',
    'a_hour' => 'diura di le :count',

    'minute' => 'metsotso e le :count',
    'min' => 'metsotso e le :count',
    'a_minute' => 'metsotso e le :count',

    'second' => 'metsotswana e le :count',
    's' => 'metsotswana e le :count',
    'a_second' => 'metsotswana e le :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mni_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/sq.php', [
    'formats' => [
        'L' => 'D.M.YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY, HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Ian De La Cruz
 * - JD Isaacks
 */
return require __DIR__.'/tl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - JD Isaacks
 * - Pierre du Plessis
 */
return [
    'year' => ':count jaar',
    'a_year' => '\'n jaar|:count jaar',
    'y' => ':count j.',
    'month' => ':count maand|:count maande',
    'a_month' => '\'n maand|:count maande',
    'm' => ':count maa.',
    'week' => ':count week|:count weke',
    'a_week' => '\'n week|:count weke',
    'w' => ':count w.',
    'day' => ':count dag|:count dae',
    'a_day' => '\'n dag|:count dae',
    'd' => ':count d.',
    'hour' => ':count uur',
    'a_hour' => '\'n uur|:count uur',
    'h' => ':count u.',
    'minute' => ':count minuut|:count minute',
    'a_minute' => '\'n minuut|:count minute',
    'min' => ':count min.',
    'second' => ':count sekond|:count sekondes',
    'a_second' => '\'n paar sekondes|:count sekondes',
    's' => ':count s.',
    'ago' => ':time gelede',
    'from_now' => 'oor :time',
    'after' => ':time na',
    'before' => ':time voor',
    'diff_now' => 'Nou',
    'diff_today' => 'Vandag',
    'diff_today_regexp' => 'Vandag(?:\\s+om)?',
    'diff_yesterday' => 'Gister',
    'diff_yesterday_regexp' => 'Gister(?:\\s+om)?',
    'diff_tomorrow' => 'Môre',
    'diff_tomorrow_regexp' => 'Môre(?:\\s+om)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Vandag om] LT',
        'nextDay' => '[Môre om] LT',
        'nextWeek' => 'dddd [om] LT',
        'lastDay' => '[Gister om] LT',
        'lastWeek' => '[Laas] dddd [om] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static fn ($number) => $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de'),
    'meridiem' => ['VM', 'NM'],
    'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    'months_short' => ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
    'weekdays_short' => ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
    'weekdays_min' => ['So', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' en '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ps.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕሪል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክቶበር', 'ኖቬምበር', 'ዲሴምበር'],
    'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
    'weekdays' => ['እሑድ', 'ሰኞ', 'ማክሰኞ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    'weekdays_short' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    'weekdays_min' => ['እሑድ', 'ሰኞ ', 'ማክሰ', 'ረቡዕ', 'ሐሙስ', 'ዓርብ', 'ቅዳሜ'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ጡዋት', 'ከሰዓት'],

    'year' => ':count አመት',
    'y' => ':count አመት',
    'a_year' => ':count አመት',

    'month' => ':count ወር',
    'm' => ':count ወር',
    'a_month' => ':count ወር',

    'week' => ':count ሳምንት',
    'w' => ':count ሳምንት',
    'a_week' => ':count ሳምንት',

    'day' => ':count ቀን',
    'd' => ':count ቀን',
    'a_day' => ':count ቀን',

    'hour' => ':count ሰዓት',
    'h' => ':count ሰዓት',
    'a_hour' => ':count ሰዓት',

    'minute' => ':count ደቂቃ',
    'min' => ':count ደቂቃ',
    'a_minute' => ':count ደቂቃ',

    'second' => ':count ሴኮንድ',
    's' => ':count ሴኮንድ',
    'a_second' => ':count ሴኮንድ',

    'ago' => 'ከ:time በፊት',
    'from_now' => 'በ:time ውስጥ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Dinda', 'Dilolo'],
    'weekdays' => ['Lumingu', 'Nkodya', 'Ndàayà', 'Ndangù', 'Njòwa', 'Ngòvya', 'Lubingu'],
    'weekdays_short' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
    'weekdays_min' => ['Lum', 'Nko', 'Ndy', 'Ndg', 'Njw', 'Ngv', 'Lub'],
    'months' => ['Ciongo', 'Lùishi', 'Lusòlo', 'Mùuyà', 'Lumùngùlù', 'Lufuimi', 'Kabàlàshìpù', 'Lùshìkà', 'Lutongolo', 'Lungùdi', 'Kaswèkèsè', 'Ciswà'],
    'months_short' => ['Cio', 'Lui', 'Lus', 'Muu', 'Lum', 'Luf', 'Kab', 'Lush', 'Lut', 'Lun', 'Kas', 'Cis'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Alexander Tømmerås
 * - Sigurd Gartmann
 * - JD Isaacks
 */
return [
    'year' => ':count år|:count år',
    'a_year' => 'ett år|:count år',
    'y' => ':count år|:count år',
    'month' => ':count måned|:count måneder',
    'a_month' => 'en måned|:count måneder',
    'm' => ':count md.',
    'week' => ':count uke|:count uker',
    'a_week' => 'en uke|:count uker',
    'w' => ':count u.',
    'day' => ':count dag|:count dager',
    'a_day' => 'en dag|:count dager',
    'd' => ':count d.',
    'hour' => ':count time|:count timer',
    'a_hour' => 'en time|:count timer',
    'h' => ':count t',
    'minute' => ':count minutt|:count minutter',
    'a_minute' => 'ett minutt|:count minutter',
    'min' => ':count min',
    'second' => ':count sekund|:count sekunder',
    'a_second' => 'noen sekunder|:count sekunder',
    's' => ':count sek',
    'ago' => ':time siden',
    'from_now' => 'om :time',
    'after' => ':time etter',
    'before' => ':time før',
    'diff_now' => 'akkurat nå',
    'diff_today' => 'i dag',
    'diff_today_regexp' => 'i dag(?:\\s+kl.)?',
    'diff_yesterday' => 'i går',
    'diff_yesterday_regexp' => 'i går(?:\\s+kl.)?',
    'diff_tomorrow' => 'i morgen',
    'diff_tomorrow_regexp' => 'i morgen(?:\\s+kl.)?',
    'diff_before_yesterday' => 'i forgårs',
    'diff_after_tomorrow' => 'i overmorgen',
    'period_recurrences' => 'en gang|:count ganger',
    'period_interval' => 'hver :interval',
    'period_start_date' => 'fra :date',
    'period_end_date' => 'til :date',
    'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
    'weekdays' => ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'],
    'weekdays_short' => ['søn', 'man', 'tir', 'ons', 'tor', 'fre', 'lør'],
    'weekdays_min' => ['sø', 'ma', 'ti', 'on', 'to', 'fr', 'lø'],
    'ordinal' => ':number.',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY [kl.] HH:mm',
        'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[i dag kl.] LT',
        'nextDay' => '[i morgen kl.] LT',
        'nextWeek' => 'dddd [kl.] LT',
        'lastDay' => '[i går kl.] LT',
        'lastWeek' => '[forrige] dddd [kl.] LT',
        'sameElse' => 'L',
    ],
    'list' => [', ', ' og '],
    'meridiem' => ['a.m.', 'p.m.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return [
    'formats' => [
        'LT' => 'HH.mm',
        'LTS' => 'HH.mm:ss',
        'L' => 'DD-MM-YY',
        'LL' => 'MMMM [di] DD, YYYY',
        'LLL' => 'DD MMM HH.mm',
        'LLLL' => 'MMMM DD, YYYY HH.mm',
    ],
    'months' => ['yanüari', 'febrüari', 'mart', 'aprel', 'mei', 'yüni', 'yüli', 'ougùstùs', 'sèptèmber', 'oktober', 'novèmber', 'desèmber'],
    'months_short' => ['yan', 'feb', 'mar', 'apr', 'mei', 'yün', 'yül', 'oug', 'sèp', 'okt', 'nov', 'des'],
    'weekdays' => ['djadomingo', 'djaluna', 'djamars', 'djawebs', 'djarason', 'djabierne', 'djasabra'],
    'weekdays_short' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'],
    'weekdays_min' => ['do', 'lu', 'ma', 'we', 'ra', 'bi', 'sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'year' => ':count aña',
    'month' => ':count luna',
    'week' => ':count siman',
    'day' => ':count dia',
    'hour' => ':count ora',
    'minute' => ':count minüt',
    'second' => ':count sekònde',
    'list' => [', ', ' i '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['kiɛmɛ́ɛm', 'kisɛ́ndɛ'],
    'weekdays' => ['sɔ́ndiɛ', 'móndie', 'muányáŋmóndie', 'metúkpíápɛ', 'kúpélimetúkpiapɛ', 'feléte', 'séselé'],
    'weekdays_short' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
    'weekdays_min' => ['sd', 'md', 'mw', 'et', 'kl', 'fl', 'ss'],
    'months' => ['pikítíkítie, oólí ú kutúan', 'siɛyɛ́, oóli ú kándíɛ', 'ɔnsúmbɔl, oóli ú kátátúɛ', 'mesiŋ, oóli ú kénie', 'ensil, oóli ú kátánuɛ', 'ɔsɔn', 'efute', 'pisuyú', 'imɛŋ i puɔs', 'imɛŋ i putúk,oóli ú kátíɛ', 'makandikɛ', 'pilɔndɔ́'],
    'months_short' => ['o.1', 'o.2', 'o.3', 'o.4', 'o.5', 'o.6', 'o.7', 'o.8', 'o.9', 'o.10', 'o.11', 'o.12'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/nl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['utuko', 'kyiukonyi'],
    'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ce_RU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/M/yy',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D [de] MMMM [de] YYYY h:mm a',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - Serhan Apaydın
 * - JD Isaacks
 * - Glavić
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count година|:count години',
    'a_year' => 'година|:count години',
    'y' => ':count година|:count години',
    'month' => ':count месец|:count месеца',
    'a_month' => 'месец|:count месеца',
    'm' => ':count месец|:count месеца',
    'week' => ':count седмица|:count седмици',
    'a_week' => 'седмица|:count седмици',
    'w' => ':count седмица|:count седмици',
    'day' => ':count ден|:count дни',
    'a_day' => 'ден|:count дни',
    'd' => ':count ден|:count дни',
    'hour' => ':count час|:count часа',
    'a_hour' => 'час|:count часа',
    'h' => ':count час|:count часа',
    'minute' => ':count минута|:count минути',
    'a_minute' => 'минута|:count минути',
    'min' => ':count минута|:count минути',
    'second' => ':count секунда|:count секунди',
    'a_second' => 'няколко секунди|:count секунди',
    's' => ':count секунда|:count секунди',
    'ago' => 'преди :time',
    'from_now' => 'след :time',
    'after' => 'след :time',
    'before' => 'преди :time',
    'diff_now' => 'сега',
    'diff_today' => 'Днес',
    'diff_today_regexp' => 'Днес(?:\\s+в)?',
    'diff_yesterday' => 'вчера',
    'diff_yesterday_regexp' => 'Вчера(?:\\s+в)?',
    'diff_tomorrow' => 'утре',
    'diff_tomorrow_regexp' => 'Утре(?:\\s+в)?',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'D.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY H:mm',
        'LLLL' => 'dddd, D MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[Днес в] LT',
        'nextDay' => '[Утре в] LT',
        'nextWeek' => 'dddd [в] LT',
        'lastDay' => '[Вчера в] LT',
        'lastWeek' => static fn (CarbonInterface $current) => match ($current->dayOfWeek) {
            0, 3, 6 => '[В изминалата] dddd [в] LT',
            default => '[В изминалия] dddd [в] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        $lastDigit = $number % 10;
        $last2Digits = $number % 100;
        if ($number === 0) {
            return "$number-ев";
        }
        if ($last2Digits === 0) {
            return "$number-ен";
        }
        if ($last2Digits > 10 && $last2Digits < 20) {
            return "$number-ти";
        }
        if ($lastDigit === 1) {
            return "$number-ви";
        }
        if ($lastDigit === 2) {
            return "$number-ри";
        }
        if ($lastDigit === 7 || $lastDigit === 8) {
            return "$number-ми";
        }

        return "$number-ти";
    },
    'months' => ['януари', 'февруари', 'март', 'април', 'май', 'юни', 'юли', 'август', 'септември', 'октомври', 'ноември', 'декември'],
    'months_short' => ['яну', 'фев', 'мар', 'апр', 'май', 'юни', 'юли', 'авг', 'сеп', 'окт', 'ное', 'дек'],
    'weekdays' => ['неделя', 'понеделник', 'вторник', 'сряда', 'четвъртък', 'петък', 'събота'],
    'weekdays_short' => ['нед', 'пон', 'вто', 'сря', 'чет', 'пет', 'съб'],
    'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' и '],
    'meridiem' => ['преди обяд', 'следобед'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return require __DIR__.'/es.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/shs_CA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/brx_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/hr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/et.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ru.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 * - Atef Ben Ali (atefBB)
 * - Mohamed Sabil (mohamedsabil83)
 */
$months = [
    'يناير',
    'فبراير',
    'مارس',
    'أبريل',
    'ماي',
    'يونيو',
    'يوليوز',
    'غشت',
    'شتنبر',
    'أكتوبر',
    'نونبر',
    'دجنبر',
];

return [
    'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => 'في :time',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم على الساعة] LT',
        'nextDay' => '[غدا على الساعة] LT',
        'nextWeek' => 'dddd [على الساعة] LT',
        'lastDay' => '[أمس على الساعة] LT',
        'lastWeek' => 'dddd [على الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/lv.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['a', 'p'],
    'weekdays' => ['Svondo', 'Muvhuro', 'Chipiri', 'Chitatu', 'China', 'Chishanu', 'Mugovera'],
    'weekdays_short' => ['Svo', 'Muv', 'Chp', 'Cht', 'Chn', 'Chs', 'Mug'],
    'weekdays_min' => ['Sv', 'Mu', 'Cp', 'Ct', 'Cn', 'Cs', 'Mg'],
    'months' => ['Ndira', 'Kukadzi', 'Kurume', 'Kubvumbi', 'Chivabvu', 'Chikumi', 'Chikunguru', 'Nyamavhuvhu', 'Gunyana', 'Gumiguru', 'Mbudzi', 'Zvita'],
    'months_short' => ['Ndi', 'Kuk', 'Kur', 'Kub', 'Chv', 'Chk', 'Chg', 'Nya', 'Gun', 'Gum', 'Mbu', 'Zvi'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'YYYY MMMM D, dddd HH:mm',
    ],

    'year' => 'makore :count',
    'y' => 'makore :count',
    'a_year' => 'makore :count',

    'month' => 'mwedzi :count',
    'm' => 'mwedzi :count',
    'a_month' => 'mwedzi :count',

    'week' => 'vhiki :count',
    'w' => 'vhiki :count',
    'a_week' => 'vhiki :count',

    'day' => 'mazuva :count',
    'd' => 'mazuva :count',
    'a_day' => 'mazuva :count',

    'hour' => 'maawa :count',
    'h' => 'maawa :count',
    'a_hour' => 'maawa :count',

    'minute' => 'minitsi :count',
    'min' => 'minitsi :count',
    'a_minute' => 'minitsi :count',

    'second' => 'sekonzi :count',
    's' => 'sekonzi :count',
    'a_second' => 'sekonzi :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - ks-gnome-trans-commits@lists.code.indlinux.net
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'M/D/YY',
    ],
    'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'weekdays' => ['आथवार', 'चॅ़दुरवार', 'बोमवार', 'ब्वदवार', 'ब्रसवार', 'शोकुरवार', 'बटुवार'],
    'weekdays_short' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'],
    'weekdays_min' => ['आथ ', 'चॅ़दुर', 'बोम', 'ब्वद', 'ब्रस', 'शोकुर', 'बटु'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Martin Suja
 * - Tsutomu Kuroda
 * - tjku
 * - Max Melentiev
 * - Juanito Fatas
 * - Ivan Stana
 * - Akira Matsuda
 * - Christopher Dell
 * - James McKinney
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Jozef Fulop
 * - Nicolás Hock Isaza
 * - Tom Hughes
 * - Simon Hürlimann (CyT)
 * - jofi
 * - Jakub ADAMEC
 * - Marek Adamický
 * - AlterwebStudio
 * - Peter Kundis
 */

use Carbon\CarbonInterface;

$fromNow = function ($time) {
    return 'o '.strtr($time, [
            'hodina' => 'hodinu',
            'minúta' => 'minútu',
            'sekunda' => 'sekundu',
        ]);
};

$ago = function ($time) {
    $replacements = [
        '/\bhodina\b/' => 'hodinou',
        '/\bminúta\b/' => 'minútou',
        '/\bsekunda\b/' => 'sekundou',
        '/\bdeň\b/u' => 'dňom',
        '/\btýždeň\b/u' => 'týždňom',
        '/\bmesiac\b/' => 'mesiacom',
        '/\brok\b/' => 'rokom',
    ];

    $replacementsPlural = [
        '/\b(?:hodiny|hodín)\b/' => 'hodinami',
        '/\b(?:minúty|minút)\b/' => 'minútami',
        '/\b(?:sekundy|sekúnd)\b/' => 'sekundami',
        '/\bdeň\b/' => 'dňom',
        '/\bdni\b/' => 'dňami',
        '/\bdní\b/u' => 'dňami',
        '/\b(?:týždne|týždňov)\b/' => 'týždňami',
        '/\b(?:mesiace|mesiacov)\b/' => 'mesiacmi',
        '/\b(?:roky|rokov)\b/' => 'rokmi',
    ];

    foreach ($replacements + $replacementsPlural as $pattern => $replacement) {
        $time = preg_replace($pattern, $replacement, $time);
    }

    return "pred $time";
};

return [
    'year' => ':count rok|:count roky|:count rokov',
    'a_year' => 'rok|:count roky|:count rokov',
    'y' => ':count r',
    'month' => ':count mesiac|:count mesiace|:count mesiacov',
    'a_month' => 'mesiac|:count mesiace|:count mesiacov',
    'm' => ':count m',
    'week' => ':count týždeň|:count týždne|:count týždňov',
    'a_week' => 'týždeň|:count týždne|:count týždňov',
    'w' => ':count t',
    'day' => ':count deň|:count dni|:count dní',
    'a_day' => 'deň|:count dni|:count dní',
    'd' => ':count d',
    'hour' => ':count hodina|:count hodiny|:count hodín',
    'a_hour' => 'hodina|:count hodiny|:count hodín',
    'h' => ':count h',
    'minute' => ':count minúta|:count minúty|:count minút',
    'a_minute' => 'minúta|:count minúty|:count minút',
    'min' => ':count min',
    'second' => ':count sekunda|:count sekundy|:count sekúnd',
    'a_second' => 'sekunda|:count sekundy|:count sekúnd',
    's' => ':count s',
    'millisecond' => ':count milisekunda|:count milisekundy|:count milisekúnd',
    'a_millisecond' => 'milisekunda|:count milisekundy|:count milisekúnd',
    'ms' => ':count ms',
    'microsecond' => ':count mikrosekunda|:count mikrosekundy|:count mikrosekúnd',
    'a_microsecond' => 'mikrosekunda|:count mikrosekundy|:count mikrosekúnd',
    'µs' => ':count µs',

    'ago' => $ago,
    'from_now' => $fromNow,
    'before' => ':time pred',
    'after' => ':time po',

    'hour_after' => ':count hodinu|:count hodiny|:count hodín',
    'minute_after' => ':count minútu|:count minúty|:count minút',
    'second_after' => ':count sekundu|:count sekundy|:count sekúnd',

    'hour_before' => ':count hodinu|:count hodiny|:count hodín',
    'minute_before' => ':count minútu|:count minúty|:count minút',
    'second_before' => ':count sekundu|:count sekundy|:count sekúnd',

    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' a '],
    'diff_now' => 'teraz',
    'diff_yesterday' => 'včera',
    'diff_tomorrow' => 'zajtra',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'DD. MMMM YYYY',
        'LLL' => 'D. M. HH:mm',
        'LLLL' => 'dddd D. MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[dnes o] LT',
        'nextDay' => '[zajtra o] LT',
        'lastDay' => '[včera o] LT',
        'nextWeek' => 'dddd [o] LT',
        'lastWeek' => static function (CarbonInterface $date) {
            switch ($date->dayOfWeek) {
                case 1:
                case 2:
                case 4:
                case 5:
                    return '[minulý] dddd [o] LT'; //pondelok/utorok/štvrtok/piatok
                default:
                    return '[minulá] dddd [o] LT';
            }
        },
        'sameElse' => 'L',
    ],
    'weekdays' => ['nedeľa', 'pondelok', 'utorok', 'streda', 'štvrtok', 'piatok', 'sobota'],
    'weekdays_short' => ['ned', 'pon', 'uto', 'str', 'štv', 'pia', 'sob'],
    'weekdays_min' => ['ne', 'po', 'ut', 'st', 'št', 'pi', 'so'],
    'months' => ['januára', 'februára', 'marca', 'apríla', 'mája', 'júna', 'júla', 'augusta', 'septembra', 'októbra', 'novembra', 'decembra'],
    'months_standalone' => ['január', 'február', 'marec', 'apríl', 'máj', 'jún', 'júl', 'august', 'september', 'október', 'november', 'december'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'máj', 'jún', 'júl', 'aug', 'sep', 'okt', 'nov', 'dec'],
    'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'meridiem' => ['dopoludnia', 'popoludní'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en_US.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Information from Michael Wolf Andrzej Krzysztofowicz ankry@mif.pg.gda.pl
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'DD. MMMM YYYY',
        'LLL' => 'DD. MMMM, HH:mm [hodź.]',
        'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [hodź.]',
    ],
    'months' => ['januara', 'februara', 'měrca', 'apryla', 'meje', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
    'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Mej', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'],
    'weekdays' => ['Njedźela', 'Póndźela', 'Wutora', 'Srjeda', 'Štvórtk', 'Pjatk', 'Sobota'],
    'weekdays_short' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'],
    'weekdays_min' => ['Nj', 'Pó', 'Wu', 'Sr', 'Št', 'Pj', 'So'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count lěto',
    'y' => ':count lěto',
    'a_year' => ':count lěto',

    'month' => ':count měsac',
    'm' => ':count měsac',
    'a_month' => ':count měsac',

    'week' => ':count tydźeń',
    'w' => ':count tydźeń',
    'a_week' => ':count tydźeń',

    'day' => ':count dźeń',
    'd' => ':count dźeń',
    'a_day' => ':count dźeń',

    'hour' => ':count hodźina',
    'h' => ':count hodźina',
    'a_hour' => ':count hodźina',

    'minute' => ':count chwila',
    'min' => ':count chwila',
    'a_minute' => ':count chwila',

    'second' => ':count druhi',
    's' => ':count druhi',
    'a_second' => ':count druhi',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - ryanhart2
 */
return [
    'year' => ':count ປີ',
    'y' => ':count ປີ',
    'month' => ':count ເດືອນ',
    'm' => ':count ດ. ',
    'week' => ':count ອາທິດ',
    'w' => ':count ອທ. ',
    'day' => ':count ມື້',
    'd' => ':count ມື້',
    'hour' => ':count ຊົ່ວໂມງ',
    'h' => ':count ຊມ. ',
    'minute' => ':count ນາທີ',
    'min' => ':count ນທ. ',
    'second' => ':count ວິນາທີ',
    'a_second' => '{0,1}ບໍ່ເທົ່າໃດວິນາທີ|[-Inf,Inf]:count ວິນາທີ',
    's' => ':count ວິ. ',
    'ago' => ':timeຜ່ານມາ',
    'from_now' => 'ອີກ :time',
    'diff_now' => 'ຕອນນີ້',
    'diff_today' => 'ມື້ນີ້ເວລາ',
    'diff_yesterday' => 'ມື້ວານນີ້ເວລາ',
    'diff_tomorrow' => 'ມື້ອື່ນເວລາ',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'ວັນdddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[ມື້ນີ້ເວລາ] LT',
        'nextDay' => '[ມື້ອື່ນເວລາ] LT',
        'nextWeek' => '[ວັນ]dddd[ໜ້າເວລາ] LT',
        'lastDay' => '[ມື້ວານນີ້ເວລາ] LT',
        'lastWeek' => '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => 'ທີ່:number',
    'meridiem' => ['ຕອນເຊົ້າ', 'ຕອນແລງ'],
    'months' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
    'months_short' => ['ມັງກອນ', 'ກຸມພາ', 'ມີນາ', 'ເມສາ', 'ພຶດສະພາ', 'ມິຖຸນາ', 'ກໍລະກົດ', 'ສິງຫາ', 'ກັນຍາ', 'ຕຸລາ', 'ພະຈິກ', 'ທັນວາ'],
    'weekdays' => ['ອາທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'],
    'weekdays_short' => ['ທິດ', 'ຈັນ', 'ອັງຄານ', 'ພຸດ', 'ພະຫັດ', 'ສຸກ', 'ເສົາ'],
    'weekdays_min' => ['ທ', 'ຈ', 'ອຄ', 'ພ', 'ພຫ', 'ສກ', 'ສ'],
    'list' => [', ', 'ແລະ '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ti_ER.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Samsung Electronics Co., Ltd.    akhilesh.k@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'dddd DD MMM YYYY',
    ],
    'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    'weekdays' => ['Ravivar', 'Somvar', 'Mangalvar', 'Budhvar', 'Guruvar', 'Shukravar', 'Shanivar'],
    'weekdays_short' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'],
    'weekdays_min' => ['Ravi', 'Som', 'Mangal', 'Budh', 'Guru', 'Shukra', 'Shani'],
    'meridiem' => ['Purvahan', 'Aparaahna'],

    'hour' => ':count minit', // less reliable
    'h' => ':count minit', // less reliable
    'a_hour' => ':count minit', // less reliable

    'year' => ':count saal',
    'y' => ':count saal',
    'a_year' => ':count saal',

    'month' => ':count Mahina',
    'm' => ':count Mahina',
    'a_month' => ':count Mahina',

    'week' => ':count Hafta',
    'w' => ':count Hafta',
    'a_week' => ':count Hafta',

    'day' => ':count Din',
    'd' => ':count Din',
    'a_day' => ':count Din',

    'minute' => ':count Minit',
    'min' => ':count Minit',
    'a_minute' => ':count Minit',

    'second' => ':count Second',
    's' => ':count Second',
    'a_second' => ':count Second',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'weekend' => [5, 6],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return require __DIR__.'/it.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
    'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'YYYY MMMM D, dddd HH:mm',
    ],

    'year' => ':count лѣто',
    'y' => ':count лѣто',
    'a_year' => ':count лѣто',

    'month' => ':count мѣсѧць',
    'm' => ':count мѣсѧць',
    'a_month' => ':count мѣсѧць',

    'week' => ':count сєдмица',
    'w' => ':count сєдмица',
    'a_week' => ':count сєдмица',

    'day' => ':count дьнь',
    'd' => ':count дьнь',
    'a_day' => ':count дьнь',

    'hour' => ':count година',
    'h' => ':count година',
    'a_hour' => ':count година',

    'minute' => ':count малъ', // less reliable
    'min' => ':count малъ', // less reliable
    'a_minute' => ':count малъ', // less reliable

    'second' => ':count въторъ',
    's' => ':count въторъ',
    'a_second' => ':count въторъ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['Ɛnkakɛnyá', 'Ɛndámâ'],
    'weekdays' => ['Jumapílí', 'Jumatátu', 'Jumane', 'Jumatánɔ', 'Alaámisi', 'Jumáa', 'Jumamósi'],
    'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'months' => ['Oladalʉ́', 'Arát', 'Ɔɛnɨ́ɔɨŋɔk', 'Olodoyíóríê inkókúâ', 'Oloilépūnyīē inkókúâ', 'Kújúɔrɔk', 'Mórusásin', 'Ɔlɔ́ɨ́bɔ́rárɛ', 'Kúshîn', 'Olgísan', 'Pʉshʉ́ka', 'Ntʉ́ŋʉ́s'],
    'months_short' => ['Dal', 'Ará', 'Ɔɛn', 'Doy', 'Lép', 'Rok', 'Sás', 'Bɔ́r', 'Kús', 'Gís', 'Shʉ́', 'Ntʉ́'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'year' => ':count olameyu', // less reliable
    'y' => ':count olameyu', // less reliable
    'a_year' => ':count olameyu', // less reliable

    'week' => ':count engolongeare orwiki', // less reliable
    'w' => ':count engolongeare orwiki', // less reliable
    'a_week' => ':count engolongeare orwiki', // less reliable

    'hour' => ':count esahabu', // less reliable
    'h' => ':count esahabu', // less reliable
    'a_hour' => ':count esahabu', // less reliable

    'second' => ':count are', // less reliable
    's' => ':count are', // less reliable
    'a_second' => ':count are', // less reliable

    'month' => ':count olapa',
    'm' => ':count olapa',
    'a_month' => ':count olapa',

    'day' => ':count enkolongʼ',
    'd' => ':count enkolongʼ',
    'a_day' => ':count enkolongʼ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
    'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
    'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bhashaghar@googlegroups.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'weekdays' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
    'weekdays_short' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
    'weekdays_min' => ['एतवार', 'सोमार', 'मंगर', 'बुध', 'बिफे', 'सूक', 'सनिचर'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'months' => ['siilo', 'colte', 'mbooy', 'seeɗto', 'duujal', 'korse', 'morso', 'juko', 'siilto', 'yarkomaa', 'jolal', 'bowte'],
    'months_short' => ['sii', 'col', 'mbo', 'see', 'duu', 'kor', 'mor', 'juk', 'slt', 'yar', 'jol', 'bow'],
    'weekdays' => ['dewo', 'aaɓnde', 'mawbaare', 'njeslaare', 'naasaande', 'mawnde', 'hoore-biir'],
    'weekdays_short' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
    'weekdays_min' => ['dew', 'aaɓ', 'maw', 'nje', 'naa', 'mwd', 'hbi'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['subaka', 'kikiiɗe'],

    'year' => ':count baret', // less reliable
    'y' => ':count baret', // less reliable
    'a_year' => ':count baret', // less reliable

    'month' => ':count lewru', // less reliable
    'm' => ':count lewru', // less reliable
    'a_month' => ':count lewru', // less reliable

    'week' => ':count naange', // less reliable
    'w' => ':count naange', // less reliable
    'a_week' => ':count naange', // less reliable

    'day' => ':count dian', // less reliable
    'd' => ':count dian', // less reliable
    'a_day' => ':count dian', // less reliable

    'hour' => ':count montor', // less reliable
    'h' => ':count montor', // less reliable
    'a_hour' => ':count montor', // less reliable

    'minute' => ':count tokossuoum', // less reliable
    'min' => ':count tokossuoum', // less reliable
    'a_minute' => ':count tokossuoum', // less reliable

    'second' => ':count tenen', // less reliable
    's' => ':count tenen', // less reliable
    'a_second' => ':count tenen', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت '],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/iu_CA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ln.php', [
    'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
    'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kunal Marwaha
 * - kostas
 * - François B
 * - Tim Fish
 * - Claire Coloma
 * - Steven Heinrich
 * - JD Isaacks
 * - Raphael Amorim
 * - Jorge Y. Castillo
 * - Víctor Díaz
 * - Diego
 * - Sebastian Thierer
 * - quinterocesar
 * - Daniel Commesse Liévanos (danielcommesse)
 * - Pete Scopes (pdscopes)
 * - gam04
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count año|:count años',
    'a_year' => 'un año|:count años',
    'y' => ':count año|:count años',
    'month' => ':count mes|:count meses',
    'a_month' => 'un mes|:count meses',
    'm' => ':count mes|:count meses',
    'week' => ':count semana|:count semanas',
    'a_week' => 'una semana|:count semanas',
    'w' => ':countsem',
    'day' => ':count día|:count días',
    'a_day' => 'un día|:count días',
    'd' => ':countd',
    'hour' => ':count hora|:count horas',
    'a_hour' => 'una hora|:count horas',
    'h' => ':counth',
    'minute' => ':count minuto|:count minutos',
    'a_minute' => 'un minuto|:count minutos',
    'min' => ':countm',
    'second' => ':count segundo|:count segundos',
    'a_second' => 'unos segundos|:count segundos',
    's' => ':counts',
    'millisecond' => ':count milisegundo|:count milisegundos',
    'a_millisecond' => 'un milisegundo|:count milisegundos',
    'ms' => ':countms',
    'microsecond' => ':count microsegundo|:count microsegundos',
    'a_microsecond' => 'un microsegundo|:count microsegundos',
    'µs' => ':countµs',
    'ago' => 'hace :time',
    'from_now' => 'en :time',
    'after' => ':time después',
    'before' => ':time antes',
    'diff_now' => 'ahora mismo',
    'diff_today' => 'hoy',
    'diff_today_regexp' => 'hoy(?:\\s+a)?(?:\\s+las)?',
    'diff_yesterday' => 'ayer',
    'diff_yesterday_regexp' => 'ayer(?:\\s+a)?(?:\\s+las)?',
    'diff_tomorrow' => 'mañana',
    'diff_tomorrow_regexp' => 'mañana(?:\\s+a)?(?:\\s+las)?',
    'diff_before_yesterday' => 'anteayer',
    'diff_after_tomorrow' => 'pasado mañana',
    'period_recurrences' => 'una vez|:count veces',
    'period_interval' => 'cada :interval',
    'period_start_date' => 'de :date',
    'period_end_date' => 'a :date',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D [de] MMMM [de] YYYY',
        'LLL' => 'D [de] MMMM [de] YYYY H:mm',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => static function (CarbonInterface $current) {
            return '[hoy a la'.($current->hour !== 1 ? 's' : '').'] LT';
        },
        'nextDay' => static function (CarbonInterface $current) {
            return '[mañana a la'.($current->hour !== 1 ? 's' : '').'] LT';
        },
        'nextWeek' => static function (CarbonInterface $current) {
            return 'dddd [a la'.($current->hour !== 1 ? 's' : '').'] LT';
        },
        'lastDay' => static function (CarbonInterface $current) {
            return '[ayer a la'.($current->hour !== 1 ? 's' : '').'] LT';
        },
        'lastWeek' => static function (CarbonInterface $current) {
            return '[el] dddd [pasado a la'.($current->hour !== 1 ? 's' : '').'] LT';
        },
        'sameElse' => 'L',
    ],
    'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
    'mmm_suffix' => '.',
    'ordinal' => ':numberº',
    'weekdays' => ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
    'weekdays_short' => ['dom.', 'lun.', 'mar.', 'mié.', 'jue.', 'vie.', 'sáb.'],
    'weekdays_min' => ['do', 'lu', 'ma', 'mi', 'ju', 'vi', 'sá'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' y '],
    'meridiem' => ['a. m.', 'p. m.'],
    'ordinal_words' => [
        'of' => 'de',
        'first' => 'primer',
        'second' => 'segundo',
        'third' => 'tercer',
        'fourth' => 'cuarto',
        'fifth' => 'quinto',
        'last' => 'último',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/zu_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ht_HT.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.  bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Bobir Ismailov Bobir Ismailov, Pablo Saratxaga, Mashrab Kuvatov bobir_is@yahoo.com, pablo@mandrakesoft.com, kmashrab@uni-bremen.de
 */
return array_replace_recursive(require __DIR__.'/uz_Latn.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
    'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyn', 'Iyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
    'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'],
    'weekdays_short' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'],
    'weekdays_min' => ['Yak', 'Du', 'Se', 'Cho', 'Pay', 'Ju', 'Sha'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/cs.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

$months = [
    'جنوري',
    'فيبروري',
    'مارچ',
    'اپريل',
    'مئي',
    'جون',
    'جولاءِ',
    'آگسٽ',
    'سيپٽمبر',
    'آڪٽوبر',
    'نومبر',
    'ڊسمبر',
];

$weekdays = [
    'آچر',
    'سومر',
    'اڱارو',
    'اربع',
    'خميس',
    'جمع',
    'ڇنڇر',
];

/*
 * Authors:
 * - Narain Sagar
 * - Sawood Alam
 */
return [
    'year' => ':count '.'سال',
    'a_year' => '{1}'.'هڪ سال'.'|:count '.'سال',
    'month' => ':count '.'مهينا',
    'a_month' => '{1}'.'هڪ مهينو'.'|:count '.'مهينا',
    'week' => ':count '.'هفتا',
    'a_week' => '{1}'.'ھڪ ھفتو'.'|:count '.'هفتا',
    'day' => ':count '.'ڏينهن',
    'a_day' => '{1}'.'هڪ ڏينهن'.'|:count '.'ڏينهن',
    'hour' => ':count '.'ڪلاڪ',
    'a_hour' => '{1}'.'هڪ ڪلاڪ'.'|:count '.'ڪلاڪ',
    'minute' => ':count '.'منٽ',
    'a_minute' => '{1}'.'هڪ منٽ'.'|:count '.'منٽ',
    'second' => ':count '.'سيڪنڊ',
    'a_second' => '{1}'.'چند سيڪنڊ'.'|:count '.'سيڪنڊ',
    'ago' => ':time اڳ',
    'from_now' => ':time پوء',
    'diff_yesterday' => 'ڪالهه',
    'diff_today' => 'اڄ',
    'diff_tomorrow' => 'سڀاڻي',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd، D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اڄ] LT',
        'nextDay' => '[سڀاڻي] LT',
        'nextWeek' => 'dddd [اڳين هفتي تي] LT',
        'lastDay' => '[ڪالهه] LT',
        'lastWeek' => '[گزريل هفتي] dddd [تي] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['صبح', 'شام'],
    'months' => $months,
    'months_short' => $months,
    'weekdays' => $weekdays,
    'weekdays_short' => $weekdays,
    'weekdays_min' => $weekdays,
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => ['، ', ' ۽ '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Reşat SABIQ tilde.birlik@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'Mayıs', 'İyun', 'İyul', 'Avgust', 'Sentâbr', 'Oktâbr', 'Noyabr', 'Dekabr'],
    'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
    'weekdays' => ['Bazar', 'Bazarertesi', 'Salı', 'Çarşembe', 'Cumaaqşamı', 'Cuma', 'Cumaertesi'],
    'weekdays_short' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'],
    'weekdays_min' => ['Baz', 'Ber', 'Sal', 'Çar', 'Caq', 'Cum', 'Cer'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ÜE', 'ÜS'],

    'year' => ':count yıl',
    'y' => ':count yıl',
    'a_year' => ':count yıl',

    'month' => ':count ay',
    'm' => ':count ay',
    'a_month' => ':count ay',

    'week' => ':count afta',
    'w' => ':count afta',
    'a_week' => ':count afta',

    'day' => ':count kün',
    'd' => ':count kün',
    'a_day' => ':count kün',

    'hour' => ':count saat',
    'h' => ':count saat',
    'a_hour' => ':count saat',

    'minute' => ':count daqqa',
    'min' => ':count daqqa',
    'a_minute' => ':count daqqa',

    'second' => ':count ekinci',
    's' => ':count ekinci',
    'a_second' => ':count ekinci',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Adam
 * - monkeycon
 * - François B
 * - Jason Katz-Brown
 * - Chris Lam
 * - Serhan Apaydın
 * - Gary Lo
 * - JD Isaacks
 * - Chris Hemp
 * - Eddie
 * - KID
 * - shankesgk2
 * - Daniel Cheung (danvim)
 */
return [
    'year' => ':count:optional-space年',
    'y' => ':count:optional-space年',
    'month' => ':count:optional-space個月',
    'm' => ':count:optional-space月',
    'week' => ':count:optional-space週',
    'w' => ':count:optional-space週',
    'day' => ':count:optional-space天',
    'd' => ':count:optional-space天',
    'hour' => ':count:optional-space小時',
    'h' => ':count:optional-space小時',
    'minute' => ':count:optional-space分鐘',
    'min' => ':count:optional-space分鐘',
    'second' => ':count:optional-space秒',
    'a_second' => '{1}幾秒|[-Inf,Inf]:count:optional-space秒',
    's' => ':count:optional-space秒',
    'ago' => ':time前',
    'from_now' => ':time後',
    'after' => ':time後',
    'before' => ':time前',
    'diff_now' => '現在',
    'diff_today' => '今天',
    'diff_yesterday' => '昨天',
    'diff_tomorrow' => '明天',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY/MM/DD',
        'LL' => 'YYYY年M月D日',
        'LLL' => 'YYYY年M月D日 HH:mm',
        'LLLL' => 'YYYY年M月D日dddd HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[今天] LT',
        'nextDay' => '[明天] LT',
        'nextWeek' => '[下]dddd LT',
        'lastDay' => '[昨天] LT',
        'lastWeek' => '[上]dddd LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'd', 'D', 'DDD' => $number.'日',
            'M' => $number.'月',
            'w', 'W' => $number.'周',
            default => $number,
        };
    },
    'meridiem' => static function ($hour, $minute) {
        $time = $hour * 100 + $minute;
        if ($time < 600) {
            return '凌晨';
        }
        if ($time < 900) {
            return '早上';
        }
        if ($time < 1130) {
            return '上午';
        }
        if ($time < 1230) {
            return '中午';
        }
        if ($time < 1800) {
            return '下午';
        }

        return '晚上';
    },
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    'weekdays_short' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => '',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ca.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/fr.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Cherokee Nation Joseph Erb josepherb7@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'MM/DD/YYYY',
    ],
    'months' => ['ᎤᏃᎸᏔᏅ', 'ᎧᎦᎵ', 'ᎠᏅᏱ', 'ᎧᏬᏂ', 'ᎠᏂᏍᎬᏘ', 'ᏕᎭᎷᏱ', 'ᎫᏰᏉᏂ', 'ᎦᎶᏂ', 'ᏚᎵᏍᏗ', 'ᏚᏂᏅᏗ', 'ᏅᏓᏕᏆ', 'ᎥᏍᎩᏱ'],
    'months_short' => ['ᎤᏃ', 'ᎧᎦ', 'ᎠᏅ', 'ᎧᏬ', 'ᎠᏂ', 'ᏕᎭ', 'ᎫᏰ', 'ᎦᎶ', 'ᏚᎵ', 'ᏚᏂ', 'ᏅᏓ', 'ᎥᏍ'],
    'weekdays' => ['ᎤᎾᏙᏓᏆᏍᎬ', 'ᎤᎾᏙᏓᏉᏅᎯ', 'ᏔᎵᏁᎢᎦ', 'ᏦᎢᏁᎢᎦ', 'ᏅᎩᏁᎢᎦ', 'ᏧᎾᎩᎶᏍᏗ', 'ᎤᎾᏙᏓᏈᏕᎾ'],
    'weekdays_short' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
    'weekdays_min' => ['ᏆᏍᎬ', 'ᏉᏅᎯ', 'ᏔᎵᏁ', 'ᏦᎢᏁ', 'ᏅᎩᏁ', 'ᏧᎾᎩ', 'ᏈᏕᎾ'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ᏌᎾᎴ', 'ᏒᎯᏱᎢᏗᏢ', 'ꮜꮎꮄ', 'ꮢꭿᏹꭲꮧꮲ'],

    'second' => ':count ᏐᎢ', // less reliable
    's' => ':count ᏐᎢ', // less reliable
    'a_second' => ':count ᏐᎢ', // less reliable

    'year' => ':count ᏑᏕᏘᏴᏓ',
    'y' => ':count ᏑᏕᏘᏴᏓ',
    'a_year' => ':count ᏑᏕᏘᏴᏓ',

    'month' => ':count ᏏᏅᏙ',
    'm' => ':count ᏏᏅᏙ',
    'a_month' => ':count ᏏᏅᏙ',

    'week' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
    'w' => ':count ᏑᎾᏙᏓᏆᏍᏗ',
    'a_week' => ':count ᏑᎾᏙᏓᏆᏍᏗ',

    'day' => ':count ᎢᎦ',
    'd' => ':count ᎢᎦ',
    'a_day' => ':count ᎢᎦ',

    'hour' => ':count ᏑᏟᎶᏛ',
    'h' => ':count ᏑᏟᎶᏛ',
    'a_hour' => ':count ᏑᏟᎶᏛ',

    'minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
    'min' => ':count ᎢᏯᏔᏬᏍᏔᏅ',
    'a_minute' => ':count ᎢᏯᏔᏬᏍᏔᏅ',

    'ago' => ':time ᏥᎨᏒ',
    'from_now' => 'ᎾᎿ :time',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return require __DIR__.'/so.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sat_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ru.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/zh.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/st_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['Ĩyakwakya', 'Ĩyawĩoo'],
    'weekdays' => ['Wa kyumwa', 'Wa kwambĩlĩlya', 'Wa kelĩ', 'Wa katatũ', 'Wa kana', 'Wa katano', 'Wa thanthatũ'],
    'weekdays_short' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
    'weekdays_min' => ['Wky', 'Wkw', 'Wkl', 'Wtũ', 'Wkn', 'Wtn', 'Wth'],
    'months' => ['Mwai wa mbee', 'Mwai wa kelĩ', 'Mwai wa katatũ', 'Mwai wa kana', 'Mwai wa katano', 'Mwai wa thanthatũ', 'Mwai wa muonza', 'Mwai wa nyaanya', 'Mwai wa kenda', 'Mwai wa ĩkumi', 'Mwai wa ĩkumi na ĩmwe', 'Mwai wa ĩkumi na ilĩ'],
    'months_short' => ['Mbe', 'Kel', 'Ktũ', 'Kan', 'Ktn', 'Tha', 'Moo', 'Nya', 'Knd', 'Ĩku', 'Ĩkm', 'Ĩkl'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    // Too unreliable
    /*
    'year' => ':count mbua', // less reliable
    'y' => ':count mbua', // less reliable
    'a_year' => ':count mbua', // less reliable

    'month' => ':count ndakitali', // less reliable
    'm' => ':count ndakitali', // less reliable
    'a_month' => ':count ndakitali', // less reliable

    'day' => ':count wia', // less reliable
    'd' => ':count wia', // less reliable
    'a_day' => ':count wia', // less reliable

    'hour' => ':count orasan', // less reliable
    'h' => ':count orasan', // less reliable
    'a_hour' => ':count orasan', // less reliable

    'minute' => ':count orasan', // less reliable
    'min' => ':count orasan', // less reliable
    'a_minute' => ':count orasan', // less reliable
    */
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['eyoMqungu', 'eyoMdumba', 'eyoKwindla', 'uTshazimpuzi', 'uCanzibe', 'eyeSilimela', 'eyeKhala', 'eyeThupa', 'eyoMsintsi', 'eyeDwarha', 'eyeNkanga', 'eyoMnga'],
    'months_short' => ['Mqu', 'Mdu', 'Kwi', 'Tsh', 'Can', 'Sil', 'Kha', 'Thu', 'Msi', 'Dwa', 'Nka', 'Mng'],
    'weekdays' => ['iCawa', 'uMvulo', 'lwesiBini', 'lwesiThathu', 'ulweSine', 'lwesiHlanu', 'uMgqibelo'],
    'weekdays_short' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'],
    'weekdays_min' => ['Caw', 'Mvu', 'Bin', 'Tha', 'Sin', 'Hla', 'Mgq'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => ':count ihlobo', // less reliable
    'y' => ':count ihlobo', // less reliable
    'a_year' => ':count ihlobo', // less reliable

    'hour' => ':count iwotshi', // less reliable
    'h' => ':count iwotshi', // less reliable
    'a_hour' => ':count iwotshi', // less reliable

    'minute' => ':count ingqalelo', // less reliable
    'min' => ':count ingqalelo', // less reliable
    'a_minute' => ':count ingqalelo', // less reliable

    'second' => ':count nceda', // less reliable
    's' => ':count nceda', // less reliable
    'a_second' => ':count nceda', // less reliable

    'month' => ':count inyanga',
    'm' => ':count inyanga',
    'a_month' => ':count inyanga',

    'week' => ':count veki',
    'w' => ':count veki',
    'a_week' => ':count veki',

    'day' => ':count imini',
    'd' => ':count imini',
    'a_day' => ':count imini',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/am_ET.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Information from Michael Wolf    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'DD. MMMM YYYY',
        'LLL' => 'DD. MMMM, HH:mm [góź.]',
        'LLLL' => 'dddd, DD. MMMM YYYY, HH:mm [góź.]',
    ],
    'months' => ['januara', 'februara', 'měrca', 'apryla', 'maja', 'junija', 'julija', 'awgusta', 'septembra', 'oktobra', 'nowembra', 'decembra'],
    'months_short' => ['Jan', 'Feb', 'Měr', 'Apr', 'Maj', 'Jun', 'Jul', 'Awg', 'Sep', 'Okt', 'Now', 'Dec'],
    'weekdays' => ['Njeźela', 'Pónjeźele', 'Wałtora', 'Srjoda', 'Stwórtk', 'Pětk', 'Sobota'],
    'weekdays_short' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'],
    'weekdays_min' => ['Nj', 'Pó', 'Wa', 'Sr', 'St', 'Pě', 'So'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count lěto',
    'y' => ':count lěto',
    'a_year' => ':count lěto',

    'month' => ':count mjasec',
    'm' => ':count mjasec',
    'a_month' => ':count mjasec',

    'week' => ':count tyźeń',
    'w' => ':count tyźeń',
    'a_week' => ':count tyźeń',

    'day' => ':count źeń',
    'd' => ':count źeń',
    'a_day' => ':count źeń',

    'hour' => ':count góźina',
    'h' => ':count góźina',
    'a_hour' => ':count góźina',

    'minute' => ':count minuta',
    'min' => ':count minuta',
    'a_minute' => ':count minuta',

    'second' => ':count drugi',
    's' => ':count drugi',
    'a_second' => ':count drugi',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/bi_VU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/kok_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/lrc.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/gd.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/ur.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنوری', 'فروری', 'مارچ', 'اپریل', 'مئی', 'جون', 'جولائی', 'اگست', 'ستمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
    'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
    'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ص', 'ش'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Walser Translation Team ml@translate-wae.ch
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
    'months' => ['Jenner', 'Hornig', 'Märze', 'Abrille', 'Meije', 'Bráčet', 'Heiwet', 'Öigšte', 'Herbštmánet', 'Wímánet', 'Wintermánet', 'Chrištmánet'],
    'months_short' => ['Jen', 'Hor', 'Mär', 'Abr', 'Mei', 'Brá', 'Hei', 'Öig', 'Her', 'Wím', 'Win', 'Chr'],
    'weekdays' => ['Suntag', 'Mäntag', 'Zischtag', 'Mittwuch', 'Frontag', 'Fritag', 'Samschtag'],
    'weekdays_short' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'],
    'weekdays_min' => ['Sun', 'Män', 'Zis', 'Mit', 'Fro', 'Fri', 'Sam'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'month' => ':count Maano', // less reliable
    'm' => ':count Maano', // less reliable
    'a_month' => ':count Maano', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Cassiano Montanari
 * - Matt Pope
 * - François B
 * - Prodis
 * - JD Isaacks
 * - Raphael Amorim
 * - João Magalhães
 * - victortobias
 * - Paulo Freitas
 * - Sebastian Thierer
 * - Claudson Martins (claudsonm)
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count ano|:count anos',
    'a_year' => 'um ano|:count anos',
    'y' => ':counta',
    'month' => ':count mês|:count meses',
    'a_month' => 'um mês|:count meses',
    'm' => ':countm',
    'week' => ':count semana|:count semanas',
    'a_week' => 'uma semana|:count semanas',
    'w' => ':countsem',
    'day' => ':count dia|:count dias',
    'a_day' => 'um dia|:count dias',
    'd' => ':countd',
    'hour' => ':count hora|:count horas',
    'a_hour' => 'uma hora|:count horas',
    'h' => ':counth',
    'minute' => ':count minuto|:count minutos',
    'a_minute' => 'um minuto|:count minutos',
    'min' => ':countmin',
    'second' => ':count segundo|:count segundos',
    'a_second' => 'alguns segundos|:count segundos',
    's' => ':counts',
    'millisecond' => ':count milissegundo|:count milissegundos',
    'a_millisecond' => 'um milissegundo|:count milissegundos',
    'ms' => ':countms',
    'microsecond' => ':count microssegundo|:count microssegundos',
    'a_microsecond' => 'um microssegundo|:count microssegundos',
    'µs' => ':countµs',
    'ago' => 'há :time',
    'from_now' => 'em :time',
    'after' => ':time depois',
    'before' => ':time antes',
    'diff_now' => 'agora',
    'diff_today' => 'Hoje',
    'diff_today_regexp' => 'Hoje(?:\\s+às)?',
    'diff_yesterday' => 'ontem',
    'diff_yesterday_regexp' => 'Ontem(?:\\s+às)?',
    'diff_tomorrow' => 'amanhã',
    'diff_tomorrow_regexp' => 'Amanhã(?:\\s+às)?',
    'diff_before_yesterday' => 'anteontem',
    'diff_after_tomorrow' => 'depois de amanhã',
    'period_recurrences' => 'uma vez|:count vezes',
    'period_interval' => 'cada :interval',
    'period_start_date' => 'de :date',
    'period_end_date' => 'até :date',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D [de] MMMM [de] YYYY',
        'LLL' => 'D [de] MMMM [de] YYYY HH:mm',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Hoje às] LT',
        'nextDay' => '[Amanhã às] LT',
        'nextWeek' => 'dddd [às] LT',
        'lastDay' => '[Ontem às] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0, 6 => '[Último] dddd [às] LT',
            default => '[Última] dddd [às] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberº',
    'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'],
    'weekdays' => ['domingo', 'segunda-feira', 'terça-feira', 'quarta-feira', 'quinta-feira', 'sexta-feira', 'sábado'],
    'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    'weekdays_min' => ['Do', '2ª', '3ª', '4ª', '5ª', '6ª', 'Sá'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' e '],
    'ordinal_words' => [
        'of' => 'de',
        'first' => 'primeira',
        'second' => 'segunda',
        'third' => 'terceira',
        'fourth' => 'quarta',
        'fifth' => 'quinta',
        'last' => 'última',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
    'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'],
    'weekdays' => ['ሰንበት', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    'weekdays_short' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    'weekdays_min' => ['ሰንበ', 'ሰኑይ', 'ሰሉስ', 'ረቡዕ', 'ሓሙስ', 'ዓርቢ', 'ቀዳም'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ንጉሆ ሰዓተ', 'ድሕር ሰዓት'],

    'year' => ':count ዓመት',
    'y' => ':count ዓመት',
    'a_year' => ':count ዓመት',

    'month' => 'ወርሒ :count',
    'm' => 'ወርሒ :count',
    'a_month' => 'ወርሒ :count',

    'week' => ':count ሰሙን',
    'w' => ':count ሰሙን',
    'a_week' => ':count ሰሙን',

    'day' => ':count መዓልቲ',
    'd' => ':count መዓልቲ',
    'a_day' => ':count መዓልቲ',

    'hour' => ':count ሰዓት',
    'h' => ':count ሰዓት',
    'a_hour' => ':count ሰዓት',

    'minute' => ':count ደቒቕ',
    'min' => ':count ደቒቕ',
    'a_minute' => ':count ደቒቕ',

    'second' => ':count ሰከንድ',
    's' => ':count ሰከንድ',
    'a_second' => ':count ሰከንድ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Pablo Saratxaga pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
    'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
    'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'],
    'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
    'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'months' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
    'months_short' => ['M01', 'M02', 'M03', 'M04', 'M05', 'M06', 'M07', 'M08', 'M09', 'M10', 'M11', 'M12'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'YYYY MMMM D, dddd HH:mm',
    ],

    'year' => ':count meta',
    'y' => ':count meta',
    'a_year' => ':count meta',

    'month' => ':count mēniks', // less reliable
    'm' => ':count mēniks', // less reliable
    'a_month' => ':count mēniks', // less reliable

    'week' => ':count sawaītin', // less reliable
    'w' => ':count sawaītin', // less reliable
    'a_week' => ':count sawaītin', // less reliable

    'day' => ':count di',
    'd' => ':count di',
    'a_day' => ':count di',

    'hour' => ':count bruktēt', // less reliable
    'h' => ':count bruktēt', // less reliable
    'a_hour' => ':count bruktēt', // less reliable

    'minute' => ':count līkuts', // less reliable
    'min' => ':count līkuts', // less reliable
    'a_minute' => ':count līkuts', // less reliable

    'second' => ':count kitan', // less reliable
    's' => ':count kitan', // less reliable
    'a_second' => ':count kitan', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/fur_IT.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Roy
 * - Stephan
 * - François B
 * - Tim Fish
 * - Kevin Huang
 * - Jacob Middag
 * - JD Isaacks
 * - Roy
 * - Stephan
 * - François B
 * - Tim Fish
 * - Jacob Middag
 * - JD Isaacks
 * - Propaganistas
 * - MegaXLR
 * - adriaanzon
 * - MonkeyPhysics
 * - JeroenG
 * - RikSomers
 * - proclame
 * - Rik de Groot (hwdegroot)
 */
return [
    'year' => ':count jaar|:count jaar',
    'a_year' => 'een jaar|:count jaar',
    'y' => ':countj',
    'month' => ':count maand|:count maanden',
    'a_month' => 'een maand|:count maanden',
    'm' => ':countmnd',
    'week' => ':count week|:count weken',
    'a_week' => 'een week|:count weken',
    'w' => ':countw',
    'day' => ':count dag|:count dagen',
    'a_day' => 'een dag|:count dagen',
    'd' => ':countd',
    'hour' => ':count uur|:count uur',
    'a_hour' => 'een uur|:count uur',
    'h' => ':countu',
    'minute' => ':count minuut|:count minuten',
    'a_minute' => 'een minuut|:count minuten',
    'min' => ':countmin',
    'second' => ':count seconde|:count seconden',
    'a_second' => 'een paar seconden|:count seconden',
    's' => ':counts',
    'ago' => ':time geleden',
    'from_now' => 'over :time',
    'after' => ':time later',
    'before' => ':time eerder',
    'diff_now' => 'nu',
    'diff_today' => 'vandaag',
    'diff_today_regexp' => 'vandaag(?:\\s+om)?',
    'diff_yesterday' => 'gisteren',
    'diff_yesterday_regexp' => 'gisteren(?:\\s+om)?',
    'diff_tomorrow' => 'morgen',
    'diff_tomorrow_regexp' => 'morgen(?:\\s+om)?',
    'diff_after_tomorrow' => 'overmorgen',
    'diff_before_yesterday' => 'eergisteren',
    'period_recurrences' => ':count keer',
    'period_interval' => static function (string $interval = '') {
        /** @var string $output */
        $output = preg_replace('/^(een|één|1)\s+/u', '', $interval);

        if (preg_match('/^(een|één|1)( jaar|j| uur|u)/u', $interval)) {
            return "elk $output";
        }

        return "elke $output";
    },
    'period_start_date' => 'van :date',
    'period_end_date' => 'tot :date',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD-MM-YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[vandaag om] LT',
        'nextDay' => '[morgen om] LT',
        'nextWeek' => 'dddd [om] LT',
        'lastDay' => '[gisteren om] LT',
        'lastWeek' => '[afgelopen] dddd [om] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        return $number.(($number === 1 || $number === 8 || $number >= 20) ? 'ste' : 'de');
    },
    'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
    'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
    'mmm_suffix' => '.',
    'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
    'weekdays_short' => ['zo.', 'ma.', 'di.', 'wo.', 'do.', 'vr.', 'za.'],
    'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' en '],
    'meridiem' => ['\'s ochtends', '\'s middags'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Phando', 'Luhuhi', 'Ṱhafamuhwe', 'Lambamai', 'Shundunthule', 'Fulwi', 'Fulwana', 'Ṱhangule', 'Khubvumedzi', 'Tshimedzi', 'Ḽara', 'Nyendavhusiku'],
    'months_short' => ['Pha', 'Luh', 'Fam', 'Lam', 'Shu', 'Lwi', 'Lwa', 'Ngu', 'Khu', 'Tsh', 'Ḽar', 'Nye'],
    'weekdays' => ['Swondaha', 'Musumbuluwo', 'Ḽavhuvhili', 'Ḽavhuraru', 'Ḽavhuṋa', 'Ḽavhuṱanu', 'Mugivhela'],
    'weekdays_short' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'],
    'weekdays_min' => ['Swo', 'Mus', 'Vhi', 'Rar', 'ṋa', 'Ṱan', 'Mug'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    // Too unreliable
    /*
    'day' => ':count vhege', // less reliable
    'd' => ':count vhege', // less reliable
    'a_day' => ':count vhege', // less reliable

    'hour' => ':count watshi', // less reliable
    'h' => ':count watshi', // less reliable
    'a_hour' => ':count watshi', // less reliable

    'minute' => ':count watshi', // less reliable
    'min' => ':count watshi', // less reliable
    'a_minute' => ':count watshi', // less reliable

    'second' => ':count Mu', // less reliable
    's' => ':count Mu', // less reliable
    'a_second' => ':count Mu', // less reliable

    'week' => ':count vhege',
    'w' => ':count vhege',
    'a_week' => ':count vhege',
    */
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባት', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'],
    'months_short' => ['ጠሐረ', 'ከተተ', 'መገበ', 'አኀዘ', 'ግንባ', 'ሠንየ', 'ሐመለ', 'ነሐሰ', 'ከረመ', 'ጠቀመ', 'ኀደረ', 'ኀሠሠ'],
    'weekdays' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚት'],
    'weekdays_short' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
    'weekdays_min' => ['እኁድ', 'ሰኑይ', 'ሠሉስ', 'ራብዕ', 'ሐሙስ', 'ዓርበ', 'ቀዳሚ'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ጽባሕ', 'ምሴት'],

    'month' => ':count ወርሕ', // less reliable
    'm' => ':count ወርሕ', // less reliable
    'a_month' => ':count ወርሕ', // less reliable

    'week' => ':count ሰብዑ', // less reliable
    'w' => ':count ሰብዑ', // less reliable
    'a_week' => ':count ሰብዑ', // less reliable

    'hour' => ':count አንትሙ', // less reliable
    'h' => ':count አንትሙ', // less reliable
    'a_hour' => ':count አንትሙ', // less reliable

    'minute' => ':count ንኡስ', // less reliable
    'min' => ':count ንኡስ', // less reliable
    'a_minute' => ':count ንኡስ', // less reliable

    'year' => ':count ዓመት',
    'y' => ':count ዓመት',
    'a_year' => ':count ዓመት',

    'day' => ':count ዕለት',
    'd' => ':count ዕለት',
    'a_day' => ':count ዕለት',

    'second' => ':count ካልእ',
    's' => ':count ካልእ',
    'a_second' => ':count ካልእ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kruy Vanna
 * - Sereysethy Touch
 * - JD Isaacks
 * - Sovichet Tep
 */
return [
    'year' => ':count ឆ្នាំ',
    'a_year' => '{1}មួយឆ្នាំ|[-Inf,Inf]:count ឆ្នាំ',
    'y' => ':count ឆ្នាំ',
    'month' => ':count ខែ',
    'a_month' => '{1}មួយខែ|[-Inf,Inf]:count ខែ',
    'm' => ':count ខែ',
    'week' => ':count សប្តាហ៍',
    'w' => ':count សប្តាហ៍',
    'day' => ':count ថ្ងៃ',
    'a_day' => '{1}មួយថ្ងៃ|[-Inf,Inf]:count ថ្ងៃ',
    'd' => ':count ថ្ងៃ',
    'hour' => ':count ម៉ោង',
    'a_hour' => '{1}មួយម៉ោង|[-Inf,Inf]:count ម៉ោង',
    'h' => ':count ម៉ោង',
    'minute' => ':count នាទី',
    'a_minute' => '{1}មួយនាទី|[-Inf,Inf]:count នាទី',
    'min' => ':count នាទី',
    'second' => ':count វិនាទី',
    'a_second' => '{0,1}ប៉ុន្មានវិនាទី|[-Inf,Inf]:count វិនាទី',
    's' => ':count វិនាទី',
    'ago' => ':timeមុន',
    'from_now' => ':timeទៀត',
    'after' => 'នៅ​ក្រោយ :time',
    'before' => 'នៅ​មុន :time',
    'diff_now' => 'ឥឡូវ',
    'diff_today' => 'ថ្ងៃនេះ',
    'diff_today_regexp' => 'ថ្ងៃនេះ(?:\\s+ម៉ោង)?',
    'diff_yesterday' => 'ម្សិលមិញ',
    'diff_yesterday_regexp' => 'ម្សិលមិញ(?:\\s+ម៉ោង)?',
    'diff_tomorrow' => 'ថ្ងៃ​ស្អែក',
    'diff_tomorrow_regexp' => 'ស្អែក(?:\\s+ម៉ោង)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[ថ្ងៃនេះ ម៉ោង] LT',
        'nextDay' => '[ស្អែក ម៉ោង] LT',
        'nextWeek' => 'dddd [ម៉ោង] LT',
        'lastDay' => '[ម្សិលមិញ ម៉ោង] LT',
        'lastWeek' => 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => 'ទី:number',
    'meridiem' => ['ព្រឹក', 'ល្ងាច'],
    'months' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'],
    'months_short' => ['មករា', 'កុម្ភៈ', 'មីនា', 'មេសា', 'ឧសភា', 'មិថុនា', 'កក្កដា', 'សីហា', 'កញ្ញា', 'តុលា', 'វិច្ឆិកា', 'ធ្នូ'],
    'weekdays' => ['អាទិត្យ', 'ច័ន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],
    'weekdays_short' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'],
    'weekdays_min' => ['អា', 'ច', 'អ', 'ព', 'ព្រ', 'សុ', 'ស'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', 'និង '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ks_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/de.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
    'months' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
    'months_short' => ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
    'weekdays' => ['1', '2', '3', '4', '5', '6', '7'],
    'weekdays_short' => ['1', '2', '3', '4', '5', '6', '7'],
    'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ast.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 */
return [
    'year' => 'ལོ:count',
    'a_year' => '{1}ལོ་གཅིག|[-Inf,Inf]ལོ:count',
    'month' => 'ཟླ་བ:count',
    'a_month' => '{1}ཟླ་བ་གཅིག|[-Inf,Inf]ཟླ་བ:count',
    'week' => 'གཟའ་འཁོར་:count',
    'a_week' => 'གཟའ་འཁོར་གཅིག',
    'day' => 'ཉིན:count་',
    'a_day' => '{1}ཉིན་གཅིག|[-Inf,Inf]ཉིན:count',
    'hour' => 'ཆུ་ཚོད:count',
    'a_hour' => '{1}ཆུ་ཚོད་གཅིག|[-Inf,Inf]ཆུ་ཚོད:count',
    'minute' => 'སྐར་མ་:count',
    'a_minute' => '{1}སྐར་མ་གཅིག|[-Inf,Inf]སྐར་མ་:count',
    'second' => 'སྐར་ཆ:count',
    'a_second' => '{01}ལམ་སང|[-Inf,Inf]སྐར་ཆ:count',
    'ago' => ':time སྔན་ལ',
    'from_now' => ':time ལ་',
    'diff_yesterday' => 'ཁ་སང',
    'diff_today' => 'དི་རིང',
    'diff_tomorrow' => 'སང་ཉིན',
    'formats' => [
        'LT' => 'A h:mm',
        'LTS' => 'A h:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm',
    ],
    'calendar' => [
        'sameDay' => '[དི་རིང] LT',
        'nextDay' => '[སང་ཉིན] LT',
        'nextWeek' => '[བདུན་ཕྲག་རྗེས་མ], LT',
        'lastDay' => '[ཁ་སང] LT',
        'lastWeek' => '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'མཚན་མོ';
        }
        if ($hour < 10) {
            return 'ཞོགས་ཀས';
        }
        if ($hour < 17) {
            return 'ཉིན་གུང';
        }
        if ($hour < 20) {
            return 'དགོང་དག';
        }

        return 'མཚན་མོ';
    },
    'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
    'months_short' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
    'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
    'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'],
    'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ', 'པ་སངས་', 'སྤེན་པ་'],
    'list' => [', ', ' ཨནད་ '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - ANLoc Martin Benjamin locales@africanlocalization.net
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'MM/DD/YYYY',
    ],
    'months' => ['Januari', 'Februari', 'Machi', 'Epreo', 'Mei', 'Juni', 'Julai', 'Ogasti', 'Septemba', 'Oktoba', 'Novemba', 'Disemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Epr', 'Mei', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Dis'],
    'weekdays' => ['Pa Mulungu', 'Palichimo', 'Palichibuli', 'Palichitatu', 'Palichine', 'Palichisano', 'Pachibelushi'],
    'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['uluchelo', 'akasuba'],

    'year' => 'myaka :count',
    'y' => 'myaka :count',
    'a_year' => 'myaka :count',

    'month' => 'myeshi :count',
    'm' => 'myeshi :count',
    'a_month' => 'myeshi :count',

    'week' => 'umulungu :count',
    'w' => 'umulungu :count',
    'a_week' => 'umulungu :count',

    'day' => 'inshiku :count',
    'd' => 'inshiku :count',
    'a_day' => 'inshiku :count',

    'hour' => 'awala :count',
    'h' => 'awala :count',
    'a_hour' => 'awala :count',

    'minute' => 'miniti :count',
    'min' => 'miniti :count',
    'a_minute' => 'miniti :count',

    'second' => 'sekondi :count',
    's' => 'sekondi :count',
    'a_second' => 'sekondi :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/hak_TW.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ne.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ahmed Ali
 */

$months = [
    'ޖެނުއަރީ',
    'ފެބްރުއަރީ',
    'މާރިޗު',
    'އޭޕްރީލު',
    'މޭ',
    'ޖޫން',
    'ޖުލައި',
    'އޯގަސްޓު',
    'ސެޕްޓެމްބަރު',
    'އޮކްޓޯބަރު',
    'ނޮވެމްބަރު',
    'ޑިސެމްބަރު',
];

$weekdays = [
    'އާދިއްތަ',
    'ހޯމަ',
    'އަންގާރަ',
    'ބުދަ',
    'ބުރާސްފަތި',
    'ހުކުރު',
    'ހޮނިހިރު',
];

return [
    'year' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
    'y' => '{0}އަހަރެއް|[1,Inf]:count އަހަރު',
    'month' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
    'm' => '{0}މައްސަރެއް|[1,Inf]:count މަސް',
    'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
    'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
    'day' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
    'd' => '{0}ދުވަސް|[1,Inf]:count ދުވަސް',
    'hour' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
    'h' => '{0}ގަޑިއިރެއް|[1,Inf]:count ގަޑި',
    'minute' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
    'min' => '{0}މިނެޓެއް|[1,Inf]:count މިނެޓް',
    'second' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
    's' => '{0}ސިކުންތެއް|[1,Inf]:count ސިކުންތު',
    'ago' => ':time ކުރިން',
    'from_now' => ':time ފަހުން',
    'after' => ':time ފަހުން',
    'before' => ':time ކުރި',
    'diff_yesterday' => 'އިއްޔެ',
    'diff_today' => 'މިއަދު',
    'diff_tomorrow' => 'މާދަމާ',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[މިއަދު] LT',
        'nextDay' => '[މާދަމާ] LT',
        'nextWeek' => 'dddd LT',
        'lastDay' => '[އިއްޔެ] LT',
        'lastWeek' => '[ފާއިތުވި] dddd LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['މކ', 'މފ'],
    'months' => $months,
    'months_short' => $months,
    'weekdays' => $weekdays,
    'weekdays_short' => $weekdays,
    'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'],
    'list' => [', ', ' އަދި '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bokideckonja
 * - Josh Soref
 * - François B
 * - shaishavgandhi05
 * - Serhan Apaydın
 * - JD Isaacks
 * - Ademir Šehić
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count godina|:count godine|:count godina',
    'y' => ':count godina|:count godine|:count godina',
    'month' => ':count mjesec|:count mjeseca|:count mjeseci',
    'm' => ':count mjesec|:count mjeseca|:count mjeseci',
    'week' => ':count sedmica|:count sedmice|:count sedmica',
    'w' => ':count sedmica|:count sedmice|:count sedmica',
    'day' => ':count dan|:count dana|:count dana',
    'd' => ':count dan|:count dana|:count dana',
    'hour' => ':count sat|:count sata|:count sati',
    'h' => ':count sat|:count sata|:count sati',
    'minute' => ':count minut|:count minuta|:count minuta',
    'min' => ':count minut|:count minuta|:count minuta',
    'second' => ':count sekund|:count sekunda|:count sekundi',
    's' => ':count sekund|:count sekunda|:count sekundi',

    'ago' => 'prije :time',
    'from_now' => 'za :time',
    'after' => 'nakon :time',
    'before' => ':time ranije',

    'year_ago' => ':count godinu|:count godine|:count godina',
    'year_from_now' => ':count godinu|:count godine|:count godina',
    'week_ago' => ':count sedmicu|:count sedmice|:count sedmica',
    'week_from_now' => ':count sedmicu|:count sedmice|:count sedmica',

    'diff_now' => 'sada',
    'diff_today' => 'danas',
    'diff_today_regexp' => 'danas(?:\\s+u)?',
    'diff_yesterday' => 'jučer',
    'diff_yesterday_regexp' => 'jučer(?:\\s+u)?',
    'diff_tomorrow' => 'sutra',
    'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY H:mm',
        'LLLL' => 'dddd, D. MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[danas u] LT',
        'nextDay' => '[sutra u] LT',
        'nextWeek' => static fn (CarbonInterface $current) => match ($current->dayOfWeek) {
            0 => '[u] [nedjelju] [u] LT',
            3 => '[u] [srijedu] [u] LT',
            6 => '[u] [subotu] [u] LT',
            default => '[u] dddd [u] LT',
        },
        'lastDay' => '[jučer u] LT',
        'lastWeek' => static fn (CarbonInterface $current) => match ($current->dayOfWeek) {
            0, 3 => '[prošlu] dddd [u] LT',
            6 => '[prošle] [subote] [u] LT',
            default => '[prošli] dddd [u] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'juni', 'juli', 'august', 'septembar', 'oktobar', 'novembar', 'decembar'],
    'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj.', 'jun.', 'jul.', 'aug.', 'sep.', 'okt.', 'nov.', 'dec.'],
    'weekdays' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
    'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
    'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' i '],
    'meridiem' => ['prijepodne', 'popodne'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/tcy_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/as_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'first_day_of_week' => 6,
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hans.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Andre Polykanine A.K.A. Menelion Elensúlë
 * - JD Isaacks
 */
return [
    'year' => ':count năm',
    'a_year' => '{1}một năm|]1, Inf[:count năm',
    'y' => ':count năm',
    'month' => ':count tháng',
    'a_month' => '{1}một tháng|]1, Inf[:count tháng',
    'm' => ':count tháng',
    'week' => ':count tuần',
    'a_week' => '{1}một tuần|]1, Inf[:count tuần',
    'w' => ':count tuần',
    'day' => ':count ngày',
    'a_day' => '{1}một ngày|]1, Inf[:count ngày',
    'd' => ':count ngày',
    'hour' => ':count giờ',
    'a_hour' => '{1}một giờ|]1, Inf[:count giờ',
    'h' => ':count giờ',
    'minute' => ':count phút',
    'a_minute' => '{1}một phút|]1, Inf[:count phút',
    'min' => ':count phút',
    'second' => ':count giây',
    'a_second' => '{1}vài giây|]1, Inf[:count giây',
    's' => ':count giây',
    'ago' => ':time trước',
    'from_now' => ':time tới',
    'after' => ':time sau',
    'before' => ':time trước',
    'diff_now' => 'bây giờ',
    'diff_today' => 'Hôm',
    'diff_today_regexp' => 'Hôm(?:\\s+nay)?(?:\\s+lúc)?',
    'diff_yesterday' => 'Hôm qua',
    'diff_yesterday_regexp' => 'Hôm(?:\\s+qua)?(?:\\s+lúc)?',
    'diff_tomorrow' => 'Ngày mai',
    'diff_tomorrow_regexp' => 'Ngày(?:\\s+mai)?(?:\\s+lúc)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM [năm] YYYY',
        'LLL' => 'D MMMM [năm] YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM [năm] YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Hôm nay lúc] LT',
        'nextDay' => '[Ngày mai lúc] LT',
        'nextWeek' => 'dddd [tuần tới lúc] LT',
        'lastDay' => '[Hôm qua lúc] LT',
        'lastWeek' => 'dddd [tuần trước lúc] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['SA', 'CH'],
    'months' => ['tháng 1', 'tháng 2', 'tháng 3', 'tháng 4', 'tháng 5', 'tháng 6', 'tháng 7', 'tháng 8', 'tháng 9', 'tháng 10', 'tháng 11', 'tháng 12'],
    'months_short' => ['Th01', 'Th02', 'Th03', 'Th04', 'Th05', 'Th06', 'Th07', 'Th08', 'Th09', 'Th10', 'Th11', 'Th12'],
    'weekdays' => ['chủ nhật', 'thứ hai', 'thứ ba', 'thứ tư', 'thứ năm', 'thứ sáu', 'thứ bảy'],
    'weekdays_short' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
    'weekdays_min' => ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' và '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat, Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अपरेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितमबर', 'अकटूबर', 'नवमबर', 'दिसमबर'],
    'months_short' => ['जन', 'फर', 'मार्च', 'अप', 'मई', 'जून', 'जुला', 'अग', 'सित', 'अकटू', 'नव', 'दिस'],
    'weekdays' => ['इतवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बिरसपत', 'सुकरवार', 'सनिवार'],
    'weekdays_short' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'],
    'weekdays_min' => ['इत', 'सोम', 'मंग', 'बुध', 'बिर', 'सुक', 'सनि'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['बिहिनियाँ', 'मंझनियाँ'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Sherubtse College    bug-glibc@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'པསྱི་ལོYYཟལMMཚེསDD',
    ],
    'months' => ['ཟླ་བ་དང་པ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་ཕ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུནཔ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
    'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
    'weekdays' => ['གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་ཕ་', 'གཟའ་པུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་ཕ་', 'གཟའ་ཉི་མ་'],
    'weekdays_short' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
    'weekdays_min' => ['ཟླ་', 'མིར་', 'ལྷག་', 'པུར་', 'སངས་', 'སྤེན་', 'ཉི་'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ངས་ཆ', 'ཕྱི་ཆ'],

    'year' => ':count ཆརཔ', // less reliable
    'y' => ':count ཆརཔ', // less reliable
    'a_year' => ':count ཆརཔ', // less reliable

    'month' => ':count ཟླ་བ', // less reliable
    'm' => ':count ཟླ་བ', // less reliable
    'a_month' => ':count ཟླ་བ', // less reliable

    'day' => ':count ཉི', // less reliable
    'd' => ':count ཉི', // less reliable
    'a_day' => ':count ཉི', // less reliable

    'second' => ':count ཆ', // less reliable
    's' => ':count ཆ', // less reliable
    'a_second' => ':count ཆ', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Tornike Razmadze
 * - François B
 * - Lasha Dolidze
 * - Tim Fish
 * - JD Isaacks
 * - Tornike Razmadze
 * - François B
 * - Lasha Dolidze
 * - JD Isaacks
 * - LONGMAN
 * - Avtandil Kikabidze (akalongman)
 * - Levan Velijanashvili (Stichoza)
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count წელი',
    'y' => ':count წელი',
    'a_year' => '{1}წელი|[-Inf,Inf]:count წელი',
    'month' => ':count თვე',
    'm' => ':count თვე',
    'a_month' => '{1}თვე|[-Inf,Inf]:count თვე',
    'week' => ':count კვირა',
    'w' => ':count კვირა',
    'a_week' => '{1}კვირა|[-Inf,Inf]:count კვირა',
    'day' => ':count დღე',
    'd' => ':count დღე',
    'a_day' => '{1}დღე|[-Inf,Inf]:count დღე',
    'hour' => ':count საათი',
    'h' => ':count საათი',
    'a_hour' => '{1}საათი|[-Inf,Inf]:count საათი',
    'minute' => ':count წუთი',
    'min' => ':count წუთი',
    'a_minute' => '{1}წუთი|[-Inf,Inf]:count წუთი',
    'second' => ':count წამი',
    's' => ':count წამი',
    'a_second' => '{1}რამდენიმე წამი|[-Inf,Inf]:count წამი',
    'ago' => static function ($time) {
        $replacements = [
            // year
            'წელი' => 'წლის',
            // month
            'თვე' => 'თვის',
            // week
            'კვირა' => 'კვირის',
            // day
            'დღე' => 'დღის',
            // hour
            'საათი' => 'საათის',
            // minute
            'წუთი' => 'წუთის',
            // second
            'წამი' => 'წამის',
        ];
        $time = strtr($time, array_flip($replacements));
        $time = strtr($time, $replacements);

        return "$time წინ";
    },
    'from_now' => static function ($time) {
        $replacements = [
            // year
            'წელი' => 'წელიწადში',
            // week
            'კვირა' => 'კვირაში',
            // day
            'დღე' => 'დღეში',
            // month
            'თვე' => 'თვეში',
            // hour
            'საათი' => 'საათში',
            // minute
            'წუთი' => 'წუთში',
            // second
            'წამი' => 'წამში',
        ];
        $time = strtr($time, array_flip($replacements));
        $time = strtr($time, $replacements);

        return $time;
    },
    'after' => static function ($time) {
        $replacements = [
            // year
            'წელი' => 'წლის',
            // month
            'თვე' => 'თვის',
            // week
            'კვირა' => 'კვირის',
            // day
            'დღე' => 'დღის',
            // hour
            'საათი' => 'საათის',
            // minute
            'წუთი' => 'წუთის',
            // second
            'წამი' => 'წამის',
        ];
        $time = strtr($time, array_flip($replacements));
        $time = strtr($time, $replacements);

        return "$time შემდეგ";
    },
    'before' => static function ($time) {
        $replacements = [
            // year
            'წელი' => 'წლით',
            // month
            'თვე' => 'თვით',
            // week
            'კვირა' => 'კვირით',
            // day
            'დღე' => 'დღით',
            // hour
            'საათი' => 'საათით',
            // minute
            'წუთი' => 'წუთით',
            // second
            'წამი' => 'წამით',
        ];
        $time = strtr($time, array_flip($replacements));
        $time = strtr($time, $replacements);

        return "$time ადრე";
    },
    'diff_now' => 'ახლა',
    'diff_today' => 'დღეს',
    'diff_yesterday' => 'გუშინ',
    'diff_tomorrow' => 'ხვალ',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[დღეს], LT[-ზე]',
        'nextDay' => '[ხვალ], LT[-ზე]',
        'nextWeek' => static function (CarbonInterface $current, \Carbon\CarbonInterface $other) {
            return ($current->isSameWeek($other) ? '' : '[შემდეგ] ').'dddd, LT[-ზე]';
        },
        'lastDay' => '[გუშინ], LT[-ზე]',
        'lastWeek' => '[წინა] dddd, LT-ზე',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        if ($number === 0) {
            return $number;
        }
        if ($number === 1) {
            return $number.'-ლი';
        }
        if (($number < 20) || ($number <= 100 && ($number % 20 === 0)) || ($number % 100 === 0)) {
            return 'მე-'.$number;
        }

        return $number.'-ე';
    },
    'months' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
    'months_standalone' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილს', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტოს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
    'months_short' => ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'],
    'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['კვირას', 'ორშაბათს', 'სამშაბათს', 'ოთხშაბათს', 'ხუთშაბათს', 'პარასკევს', 'შაბათს'],
    'weekdays_standalone' => ['კვირა', 'ორშაბათი', 'სამშაბათი', 'ოთხშაბათი', 'ხუთშაბათი', 'პარასკევი', 'შაბათი'],
    'weekdays_short' => ['კვი', 'ორშ', 'სამ', 'ოთხ', 'ხუთ', 'პარ', 'შაბ'],
    'weekdays_min' => ['კვ', 'ორ', 'სა', 'ოთ', 'ხუ', 'პა', 'შა'],
    'weekdays_regexp' => '/^([^d].*|.*[^d])$/',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' და '],
    'meridiem' => static function ($hour) {
        if ($hour >= 4) {
            if ($hour < 11) {
                return 'დილის';
            }

            if ($hour < 16) {
                return 'შუადღის';
            }

            if ($hour < 22) {
                return 'საღამოს';
            }
        }

        return 'ღამის';
    },
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/is.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/uz.php', [
    'formats' => [
        'L' => 'DD/MM/yy',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM, YYYY HH:mm',
        'LLLL' => 'dddd, DD MMMM, YYYY HH:mm',
    ],
    'meridiem' => ['ТО', 'ТК'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Томица Кораћ
 * - Enrique Vidal
 * - Christopher Dell
 * - dmilisic
 * - danijel
 * - Miroslav Matkovic (mikki021)
 */
return [
    'diff_now' => 'sada',
    'diff_yesterday' => 'juče',
    'diff_tomorrow' => 'sutra',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'MMMM D, YYYY',
        'LLL' => 'DD MMM HH:mm',
        'LLLL' => 'MMMM DD, YYYY HH:mm',
    ],
    'year' => ':count godina|:count godine|:count godina',
    'y' => ':count g.',
    'month' => ':count mesec|:count meseca|:count meseci',
    'm' => ':count m.',
    'week' => ':count nedelja|:count nedelje|:count nedelja',
    'w' => ':count n.',
    'day' => ':count dan|:count dana|:count dana',
    'd' => ':count d.',
    'hour' => ':count sat|:count sata|:count sati',
    'h' => ':count č.',
    'minute' => ':count minut|:count minuta|:count minuta',
    'min' => ':count min.',
    'second' => ':count sekund|:count sekunde|:count sekundi',
    's' => ':count s.',
    'ago' => 'pre :time',
    'from_now' => 'za :time',
    'after' => 'nakon :time',
    'before' => ':time raniјe',
    'weekdays' => ['Nedelja', 'Ponedeljak', 'Utorak', 'Sreda', 'Četvrtak', 'Petak', 'Subota'],
    'weekdays_short' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'],
    'weekdays_min' => ['Ned', 'Pon', 'Uto', 'Sre', 'Čet', 'Pet', 'Sub'],
    'months' => ['Januar', 'Februar', 'Mart', 'April', 'Maj', 'Jun', 'Jul', 'Avgust', 'Septembar', 'Oktobar', 'Novembar', 'Decembar'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'],
    'list' => [', ', ' i '],
    'meridiem' => ['pre podne', 'po podne'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/so.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - dan-nl
 * - Simon Lelorrain (slelorrain)
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count Joer',
    'y' => ':countJ',
    'month' => ':count Mount|:count Méint',
    'm' => ':countMo',
    'week' => ':count Woch|:count Wochen',
    'w' => ':countWo|:countWo',
    'day' => ':count Dag|:count Deeg',
    'd' => ':countD',
    'hour' => ':count Stonn|:count Stonnen',
    'h' => ':countSto',
    'minute' => ':count Minutt|:count Minutten',
    'min' => ':countM',
    'second' => ':count Sekonn|:count Sekonnen',
    's' => ':countSek',

    'ago' => 'virun :time',
    'from_now' => 'an :time',
    'before' => ':time virdrun',
    'after' => ':time duerno',

    'diff_today' => 'Haut',
    'diff_yesterday' => 'Gëschter',
    'diff_yesterday_regexp' => 'Gëschter(?:\\s+um)?',
    'diff_tomorrow' => 'Muer',
    'diff_tomorrow_regexp' => 'Muer(?:\\s+um)?',
    'diff_today_regexp' => 'Haut(?:\\s+um)?',
    'formats' => [
        'LT' => 'H:mm [Auer]',
        'LTS' => 'H:mm:ss [Auer]',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY H:mm [Auer]',
        'LLLL' => 'dddd, D. MMMM YYYY H:mm [Auer]',
    ],

    'calendar' => [
        'sameDay' => '[Haut um] LT',
        'nextDay' => '[Muer um] LT',
        'nextWeek' => 'dddd [um] LT',
        'lastDay' => '[Gëschter um] LT',
        'lastWeek' => static function (CarbonInterface $date) {
            // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
            return match ($date->dayOfWeek) {
                2, 4 => '[Leschten] dddd [um] LT',
                default => '[Leschte] dddd [um] LT',
            };
        },
        'sameElse' => 'L',
    ],

    'months' => ['Januar', 'Februar', 'Mäerz', 'Abrëll', 'Mee', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    'months_short' => ['Jan.', 'Febr.', 'Mrz.', 'Abr.', 'Mee', 'Jun.', 'Jul.', 'Aug.', 'Sept.', 'Okt.', 'Nov.', 'Dez.'],
    'weekdays' => ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],
    'weekdays_short' => ['So.', 'Mé.', 'Dë.', 'Më.', 'Do.', 'Fr.', 'Sa.'],
    'weekdays_min' => ['So', 'Mé', 'Dë', 'Më', 'Do', 'Fr', 'Sa'],
    'ordinal' => ':number.',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' an '],
    'meridiem' => ['moies', 'mëttes'],
    'weekdays_short_standalone' => ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
    'months_short_standalone' => ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ln.php', [
    'weekdays' => ['eyenga', 'mokɔlɔ mwa yambo', 'mokɔlɔ mwa míbalé', 'mokɔlɔ mwa mísáto', 'mokɔlɔ ya mínéi', 'mokɔlɔ ya mítáno', 'mpɔ́sɔ'],
    'weekdays_short' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    'weekdays_min' => ['eye', 'ybo', 'mbl', 'mst', 'min', 'mtn', 'mps'],
    'meridiem' => ['ntɔ́ngɔ́', 'mpókwa'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ts_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY/MM/DD',
    ],
    'months' => ['Sanda-Ɔpɛpɔn', 'Kwakwar-Ɔgyefuo', 'Ebɔw-Ɔbenem', 'Ebɔbira-Oforisuo', 'Esusow Aketseaba-Kɔtɔnimba', 'Obirade-Ayɛwohomumu', 'Ayɛwoho-Kitawonsa', 'Difuu-Ɔsandaa', 'Fankwa-Ɛbɔ', 'Ɔbɛsɛ-Ahinime', 'Ɔberɛfɛw-Obubuo', 'Mumu-Ɔpɛnimba'],
    'months_short' => ['S-Ɔ', 'K-Ɔ', 'E-Ɔ', 'E-O', 'E-K', 'O-A', 'A-K', 'D-Ɔ', 'F-Ɛ', 'Ɔ-A', 'Ɔ-O', 'M-Ɔ'],
    'weekdays' => ['Kwesida', 'Dwowda', 'Benada', 'Wukuda', 'Yawda', 'Fida', 'Memeneda'],
    'weekdays_short' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
    'weekdays_min' => ['Kwe', 'Dwo', 'Ben', 'Wuk', 'Yaw', 'Fia', 'Mem'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['AN', 'EW'],

    'year' => ':count afe',
    'y' => ':count afe',
    'a_year' => ':count afe',

    'month' => ':count bosume',
    'm' => ':count bosume',
    'a_month' => ':count bosume',

    'day' => ':count ɛda',
    'd' => ':count ɛda',
    'a_day' => ':count ɛda',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Propaganistas
 */
return array_replace_recursive(require __DIR__.'/it.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['ꎸꄑ', 'ꁯꋒ'],
    'weekdays' => ['ꑭꆏꑍ', 'ꆏꊂꋍ', 'ꆏꊂꑍ', 'ꆏꊂꌕ', 'ꆏꊂꇖ', 'ꆏꊂꉬ', 'ꆏꊂꃘ'],
    'weekdays_short' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'],
    'weekdays_min' => ['ꑭꆏ', 'ꆏꋍ', 'ꆏꑍ', 'ꆏꌕ', 'ꆏꇖ', 'ꆏꉬ', 'ꆏꃘ'],
    'months' => null,
    'months_short' => ['ꋍꆪ', 'ꑍꆪ', 'ꌕꆪ', 'ꇖꆪ', 'ꉬꆪ', 'ꃘꆪ', 'ꏃꆪ', 'ꉆꆪ', 'ꈬꆪ', 'ꊰꆪ', 'ꊰꊪꆪ', 'ꊰꑋꆪ'],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D h:mm a',
        'LLLL' => 'YYYY MMMM D, dddd h:mm a',
    ],

    'year' => ':count ꒉ', // less reliable
    'y' => ':count ꒉ', // less reliable
    'a_year' => ':count ꒉ', // less reliable

    'month' => ':count ꆪ',
    'm' => ':count ꆪ',
    'a_month' => ':count ꆪ',

    'week' => ':count ꏃ', // less reliable
    'w' => ':count ꏃ', // less reliable
    'a_week' => ':count ꏃ', // less reliable

    'day' => ':count ꏜ', // less reliable
    'd' => ':count ꏜ', // less reliable
    'a_day' => ':count ꏜ', // less reliable

    'hour' => ':count ꄮꈉ',
    'h' => ':count ꄮꈉ',
    'a_hour' => ':count ꄮꈉ',

    'minute' => ':count ꀄꊭ', // less reliable
    'min' => ':count ꀄꊭ', // less reliable
    'a_minute' => ':count ꀄꊭ', // less reliable

    'second' => ':count ꇅ', // less reliable
    's' => ':count ꇅ', // less reliable
    'a_second' => ':count ꇅ', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Janne Warén
 * - digitalfrost
 * - Tsutomu Kuroda
 * - Roope Salmi
 * - tjku
 * - Max Melentiev
 * - Sami Haahtinen
 * - Teemu Leisti
 * - Artem Ignatyev
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Robert Bjarnason
 * - Aaron Patterson
 * - Nicolás Hock Isaza
 * - Tom Hughes
 * - Sven Fuchs
 * - Petri Kivikangas
 * - Nizar Jouini
 * - Marko Seppae
 * - Tomi Mynttinen (Pikseli)
 * - Petteri (powergrip)
 */
return [
    'year' => ':count vuosi|:count vuotta',
    'y' => ':count v',
    'month' => ':count kuukausi|:count kuukautta',
    'm' => ':count kk',
    'week' => ':count viikko|:count viikkoa',
    'w' => ':count vk',
    'day' => ':count päivä|:count päivää',
    'd' => ':count pv',
    'hour' => ':count tunti|:count tuntia',
    'h' => ':count t',
    'minute' => ':count minuutti|:count minuuttia',
    'min' => ':count min',
    'second' => ':count sekunti|:count sekuntia',
    'a_second' => 'muutama sekunti|:count sekuntia',
    's' => ':count s',
    'ago' => ':time sitten',
    'from_now' => ':time päästä',
    'year_from_now' => ':count vuoden',
    'month_from_now' => ':count kuukauden',
    'week_from_now' => ':count viikon',
    'day_from_now' => ':count päivän',
    'hour_from_now' => ':count tunnin',
    'minute_from_now' => ':count minuutin',
    'second_from_now' => ':count sekunnin',
    'after' => ':time sen jälkeen',
    'before' => ':time ennen',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' ja '],
    'diff_now' => 'nyt',
    'diff_yesterday' => 'eilen',
    'diff_tomorrow' => 'huomenna',
    'formats' => [
        'LT' => 'HH.mm',
        'LTS' => 'HH.mm:ss',
        'L' => 'D.M.YYYY',
        'LL' => 'dddd D. MMMM[ta] YYYY',
        'll' => 'ddd D. MMM YYYY',
        'LLL' => 'D.MM. HH.mm',
        'LLLL' => 'D. MMMM[ta] YYYY HH.mm',
        'llll' => 'D. MMM YY HH.mm',
    ],
    'weekdays' => ['sunnuntai', 'maanantai', 'tiistai', 'keskiviikko', 'torstai', 'perjantai', 'lauantai'],
    'weekdays_short' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    'weekdays_min' => ['su', 'ma', 'ti', 'ke', 'to', 'pe', 'la'],
    'months' => ['tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu', 'kesäkuu', 'heinäkuu', 'elokuu', 'syyskuu', 'lokakuu', 'marraskuu', 'joulukuu'],
    'months_short' => ['tammi', 'helmi', 'maalis', 'huhti', 'touko', 'kesä', 'heinä', 'elo', 'syys', 'loka', 'marras', 'joulu'],
    'meridiem' => ['aamupäivä', 'iltapäivä'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Authors:
 * - Josh Soref
 * - Noureddine LOUAHEDJ
 * - JD Isaacks
 * - Atef Ben Ali (atefBB)
 * - Mohamed Sabil (mohamedsabil83)
 */
$months = [
    'جانفي',
    'فيفري',
    'مارس',
    'أفريل',
    'ماي',
    'جوان',
    'جويلية',
    'أوت',
    'سبتمبر',
    'أكتوبر',
    'نوفمبر',
    'ديسمبر',
];

return [
    'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => 'في :time',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['أح', 'إث', 'ثلا', 'أر', 'خم', 'جم', 'سب'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 4,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم على الساعة] LT',
        'nextDay' => '[غدا على الساعة] LT',
        'nextWeek' => 'dddd [على الساعة] LT',
        'lastDay' => '[أمس على الساعة] LT',
        'lastWeek' => 'dddd [على الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - xuri
 * - sycuato
 * - bokideckonja
 * - Luo Ning
 * - William Yang (williamyang233)
 */
return array_merge(require __DIR__.'/zh_Hans.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY/MM/DD',
        'LL' => 'YYYY年M月D日',
        'LLL' => 'YYYY年M月D日 A h点mm分',
        'LLLL' => 'YYYY年M月D日dddd A h点mm分',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fa.php', [
    'meridiem' => ['ق', 'ب'],
    'weekend' => [4, 5],
    'formats' => [
        'L' => 'OY/OM/OD',
        'LL' => 'OD MMM OY',
        'LLL' => 'OD MMMM OY،‏ H:mm',
        'LLLL' => 'dddd OD MMMM OY،‏ H:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'first_day_of_week' => 6,
    'weekend' => [5, 6],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/bg.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/tig_ER.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/pa_Arab.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنوري', 'فروري', 'مارچ', 'اپريل', 'مٓی', 'جون', 'جولاي', 'اگست', 'ستمبر', 'اكتوبر', 'نومبر', 'دسمبر'],
    'weekdays' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
    'weekdays_short' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
    'weekdays_min' => ['اتوار', 'پير', 'منگل', 'بدھ', 'جمعرات', 'جمعه', 'هفته'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ص', 'ش'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/nn.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/gez_ER.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ankur Group, Taneem Ahmed, Jamil Ahmed
 */
return array_replace_recursive(require __DIR__.'/bn.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
    'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
    'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
    'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
    'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
    'first_day_of_week' => 5,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Milos Sakovic
 * - Paul
 * - Pete Scopes (pdscopes)
 */
return [
    /*
     * {1}, {0} and [-Inf,Inf] are not needed as it's the default for English pluralization.
     * But as some languages are using en.php as a fallback, it's better to specify it
     * explicitly so those languages also fallback to English pluralization when a unit
     * is missing.
     */
    'year' => '{1}:count year|{0}:count years|[-Inf,Inf]:count years',
    'a_year' => '{1}a year|{0}:count years|[-Inf,Inf]:count years',
    'y' => '{1}:countyr|{0}:countyrs|[-Inf,Inf]:countyrs',
    'month' => '{1}:count month|{0}:count months|[-Inf,Inf]:count months',
    'a_month' => '{1}a month|{0}:count months|[-Inf,Inf]:count months',
    'm' => '{1}:countmo|{0}:countmos|[-Inf,Inf]:countmos',
    'week' => '{1}:count week|{0}:count weeks|[-Inf,Inf]:count weeks',
    'a_week' => '{1}a week|{0}:count weeks|[-Inf,Inf]:count weeks',
    'w' => ':countw',
    'day' => '{1}:count day|{0}:count days|[-Inf,Inf]:count days',
    'a_day' => '{1}a day|{0}:count days|[-Inf,Inf]:count days',
    'd' => ':countd',
    'hour' => '{1}:count hour|{0}:count hours|[-Inf,Inf]:count hours',
    'a_hour' => '{1}an hour|{0}:count hours|[-Inf,Inf]:count hours',
    'h' => ':counth',
    'minute' => '{1}:count minute|{0}:count minutes|[-Inf,Inf]:count minutes',
    'a_minute' => '{1}a minute|{0}:count minutes|[-Inf,Inf]:count minutes',
    'min' => ':countm',
    'second' => '{1}:count second|{0}:count seconds|[-Inf,Inf]:count seconds',
    'a_second' => '{0,1}a few seconds|[-Inf,Inf]:count seconds',
    's' => ':counts',
    'millisecond' => '{1}:count millisecond|{0}:count milliseconds|[-Inf,Inf]:count milliseconds',
    'a_millisecond' => '{1}a millisecond|{0}:count milliseconds|[-Inf,Inf]:count milliseconds',
    'ms' => ':countms',
    'microsecond' => '{1}:count microsecond|{0}:count microseconds|[-Inf,Inf]:count microseconds',
    'a_microsecond' => '{1}a microsecond|{0}:count microseconds|[-Inf,Inf]:count microseconds',
    'µs' => ':countµs',
    'ago' => ':time ago',
    'from_now' => ':time from now',
    'after' => ':time after',
    'before' => ':time before',
    'diff_now' => 'just now',
    'diff_today' => 'today',
    'diff_yesterday' => 'yesterday',
    'diff_tomorrow' => 'tomorrow',
    'diff_before_yesterday' => 'before yesterday',
    'diff_after_tomorrow' => 'after tomorrow',
    'period_recurrences' => '{1}once|{0}:count times|[-Inf,Inf]:count times',
    'period_interval' => 'every :interval',
    'period_start_date' => 'from :date',
    'period_end_date' => 'to :date',
    'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    'weekdays_min' => ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
    'ordinal' => static function ($number) {
        $lastDigit = $number % 10;

        return $number.(
            ((int) ($number % 100 / 10) === 1) ? 'th' : (
                ($lastDigit === 1) ? 'st' : (
                    ($lastDigit === 2) ? 'nd' : (
                        ($lastDigit === 3) ? 'rd' : 'th'
                    )
                )
            )
        );
    },
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'MM/DD/YYYY',
        'LL' => 'MMMM D, YYYY',
        'LLL' => 'MMMM D, YYYY h:mm A',
        'LLLL' => 'dddd, MMMM D, YYYY h:mm A',
    ],
    'list' => [', ', ' and '],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['AM', 'PM'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Adduha', 'Aluula'],
    'weekdays' => ['Alhadi', 'Atini', 'Atalata', 'Alarba', 'Alhamiisa', 'Aljuma', 'Assabdu'],
    'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
    'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alj', 'Ass'],
    'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/bn.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
    'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
    'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
    'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
    'weekdays_min' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/si.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - ANCHR
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY.DD.MM',
    ],
    'months' => ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
    'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'weekdays' => ['КӀиранан де', 'Оршотан де', 'Шинарин де', 'Кхаарин де', 'Еарин де', 'ПӀераскан де', 'Шот де'],
    'weekdays_short' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'],
    'weekdays_min' => ['КӀ', 'Ор', 'Ши', 'Кх', 'Еа', 'ПӀ', 'Шо'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => ':count шо',
    'y' => ':count шо',
    'a_year' => ':count шо',

    'month' => ':count бутт',
    'm' => ':count бутт',
    'a_month' => ':count бутт',

    'week' => ':count кӏира',
    'w' => ':count кӏира',
    'a_week' => ':count кӏира',

    'day' => ':count де',
    'd' => ':count де',
    'a_day' => ':count де',

    'hour' => ':count сахьт',
    'h' => ':count сахьт',
    'a_hour' => ':count сахьт',

    'minute' => ':count минот',
    'min' => ':count минот',
    'a_minute' => ':count минот',

    'second' => ':count секунд',
    's' => ':count секунд',
    'a_second' => ':count секунд',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/raj_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - pablo@mandriva.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Jenụwarị', 'Febrụwarị', 'Maachị', 'Eprel', 'Mee', 'Juun', 'Julaị', 'Ọgọọst', 'Septemba', 'Ọktoba', 'Novemba', 'Disemba'],
    'months_short' => ['Jen', 'Feb', 'Maa', 'Epr', 'Mee', 'Juu', 'Jul', 'Ọgọ', 'Sep', 'Ọkt', 'Nov', 'Dis'],
    'weekdays' => ['sọnde', 'mọnde', 'tuzde', 'wenzde', 'tọsde', 'fraịde', 'satọde'],
    'weekdays_short' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'],
    'weekdays_min' => ['sọn', 'mọn', 'tuz', 'wen', 'tọs', 'fra', 'sat'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => 'afo :count',
    'y' => 'afo :count',
    'a_year' => 'afo :count',

    'month' => 'önwa :count',
    'm' => 'önwa :count',
    'a_month' => 'önwa :count',

    'week' => 'izu :count',
    'w' => 'izu :count',
    'a_week' => 'izu :count',

    'day' => 'ụbọchị :count',
    'd' => 'ụbọchị :count',
    'a_day' => 'ụbọchị :count',

    'hour' => 'awa :count',
    'h' => 'awa :count',
    'a_hour' => 'awa :count',

    'minute' => 'minit :count',
    'min' => 'minit :count',
    'a_minute' => 'minit :count',

    'second' => 'sekọnd :count',
    's' => 'sekọnd :count',
    'a_second' => 'sekọnd :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Dieter Sting
 * - François B
 * - Gaspard Bucher
 * - Maxime VALY
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/fr.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/sv.php', [
    'formats' => [
        'L' => 'YYYY-MM-dd',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Atef Ben Ali (atefBB)
 * - Ibrahim AshShohail
 * - MLTDev
 * - Mohamed Sabil (mohamedsabil83)
 * - Yazan Alnugnugh (yazan-alnugnugh)
 */
$months = [
    'يناير',
    'فبراير',
    'مارس',
    'أبريل',
    'مايو',
    'يونيو',
    'يوليو',
    'أغسطس',
    'سبتمبر',
    'أكتوبر',
    'نوفمبر',
    'ديسمبر',
];

return [
    'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => ':time من الآن',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم عند الساعة] LT',
        'nextDay' => '[غدًا عند الساعة] LT',
        'nextWeek' => 'dddd [عند الساعة] LT',
        'lastDay' => '[أمس عند الساعة] LT',
        'lastWeek' => 'dddd [عند الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - tgfjt
 * - JD Isaacks
 */
return [
    'year' => ':count taun',
    'a_year' => '{1}setaun|[-Inf,Inf]:count taun',
    'month' => ':count wulan',
    'a_month' => '{1}sewulan|[-Inf,Inf]:count wulan',
    'week' => ':count minggu',
    'a_week' => '{1}sakminggu|[-Inf,Inf]:count minggu',
    'day' => ':count dina',
    'a_day' => '{1}sedina|[-Inf,Inf]:count dina',
    'hour' => ':count jam',
    'a_hour' => '{1}setunggal jam|[-Inf,Inf]:count jam',
    'minute' => ':count menit',
    'a_minute' => '{1}setunggal menit|[-Inf,Inf]:count menit',
    'second' => ':count detik',
    'a_second' => '{0,1}sawetawis detik|[-Inf,Inf]:count detik',
    'ago' => ':time ingkang kepengker',
    'from_now' => 'wonten ing :time',
    'diff_today' => 'Dinten',
    'diff_yesterday' => 'Kala',
    'diff_yesterday_regexp' => 'Kala(?:\\s+wingi)?(?:\\s+pukul)?',
    'diff_tomorrow' => 'Mbenjang',
    'diff_tomorrow_regexp' => 'Mbenjang(?:\\s+pukul)?',
    'diff_today_regexp' => 'Dinten(?:\\s+puniko)?(?:\\s+pukul)?',
    'formats' => [
        'LT' => 'HH.mm',
        'LTS' => 'HH.mm.ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY [pukul] HH.mm',
        'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
    ],
    'calendar' => [
        'sameDay' => '[Dinten puniko pukul] LT',
        'nextDay' => '[Mbenjang pukul] LT',
        'nextWeek' => 'dddd [pukul] LT',
        'lastDay' => '[Kala wingi pukul] LT',
        'lastWeek' => 'dddd [kepengker pukul] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 11) {
            return 'enjing';
        }
        if ($hour < 15) {
            return 'siyang';
        }
        if ($hour < 19) {
            return 'sonten';
        }

        return 'ndalu';
    },
    'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'Nopember', 'Desember'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nop', 'Des'],
    'weekdays' => ['Minggu', 'Senen', 'Seloso', 'Rebu', 'Kemis', 'Jemuwah', 'Septu'],
    'weekdays_short' => ['Min', 'Sen', 'Sel', 'Reb', 'Kem', 'Jem', 'Sep'],
    'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sp'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' lan '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['wichishu', 'mchochil’l'],
    'weekdays' => ['Sabato', 'Jumatatu', 'Jumanne', 'Jumatano', 'Arahamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
    'weekdays_min' => ['Sab', 'Jtt', 'Jnn', 'Jtn', 'Ara', 'Iju', 'Jmo'],
    'months' => ['Mweri wo kwanza', 'Mweri wo unayeli', 'Mweri wo uneraru', 'Mweri wo unecheshe', 'Mweri wo unethanu', 'Mweri wo thanu na mocha', 'Mweri wo saba', 'Mweri wo nane', 'Mweri wo tisa', 'Mweri wo kumi', 'Mweri wo kumi na moja', 'Mweri wo kumi na yel’li'],
    'months_short' => ['Kwa', 'Una', 'Rar', 'Che', 'Tha', 'Moc', 'Sab', 'Nan', 'Tis', 'Kum', 'Moj', 'Yel'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Zhan Tong Zhang
 * - Mayank Badola
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'YYYY-MM-DD',
        'LL' => 'MMMM D, YYYY',
        'LLL' => 'MMMM D, YYYY h:mm A',
        'LLLL' => 'dddd, MMMM D, YYYY h:mm A',
    ],
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ash
 * - François B
 * - Marco Perrando
 * - Massimiliano Caniparoli
 * - JD Isaacks
 * - Andrea Martini
 * - Francesco Marasco
 * - Tizianoz93
 * - Davide Casiraghi (davide-casiraghi)
 * - Pete Scopes (pdscopes)
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count anno|:count anni',
    'a_year' => 'un anno|:count anni',
    'y' => ':count anno|:count anni',
    'month' => ':count mese|:count mesi',
    'a_month' => 'un mese|:count mesi',
    'm' => ':count mese|:count mesi',
    'week' => ':count settimana|:count settimane',
    'a_week' => 'una settimana|:count settimane',
    'w' => ':count set.',
    'day' => ':count giorno|:count giorni',
    'a_day' => 'un giorno|:count giorni',
    'd' => ':count g|:count gg',
    'hour' => ':count ora|:count ore',
    'a_hour' => 'un\'ora|:count ore',
    'h' => ':count h',
    'minute' => ':count minuto|:count minuti',
    'a_minute' => 'un minuto|:count minuti',
    'min' => ':count min.',
    'second' => ':count secondo|:count secondi',
    'a_second' => 'alcuni secondi|:count secondi',
    's' => ':count sec.',
    'millisecond' => ':count millisecondo|:count millisecondi',
    'a_millisecond' => 'un millisecondo|:count millisecondi',
    'ms' => ':countms',
    'microsecond' => ':count microsecondo|:count microsecondi',
    'a_microsecond' => 'un microsecondo|:count microsecondi',
    'µs' => ':countµs',
    'ago' => ':time fa',
    'from_now' => static function ($time) {
        return (preg_match('/^\d.+$/', $time) ? 'tra' : 'in')." $time";
    },
    'after' => ':time dopo',
    'before' => ':time prima',
    'diff_now' => 'proprio ora',
    'diff_today' => 'Oggi',
    'diff_today_regexp' => 'Oggi(?:\\s+alle)?',
    'diff_yesterday' => 'ieri',
    'diff_yesterday_regexp' => 'Ieri(?:\\s+alle)?',
    'diff_tomorrow' => 'domani',
    'diff_tomorrow_regexp' => 'Domani(?:\\s+alle)?',
    'diff_before_yesterday' => 'l\'altro ieri',
    'diff_after_tomorrow' => 'dopodomani',
    'period_interval' => 'ogni :interval',
    'period_start_date' => 'dal :date',
    'period_end_date' => 'al :date',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Oggi alle] LT',
        'nextDay' => '[Domani alle] LT',
        'nextWeek' => 'dddd [alle] LT',
        'lastDay' => '[Ieri alle] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[la scorsa] dddd [alle] LT',
            default => '[lo scorso] dddd [alle] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberº',
    'months' => ['gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'],
    'months_short' => ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic'],
    'weekdays' => ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato'],
    'weekdays_short' => ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'],
    'weekdays_min' => ['do', 'lu', 'ma', 'me', 'gi', 've', 'sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' e '],
    'ordinal_words' => [
        'of' => 'di',
        'first' => 'primo',
        'second' => 'secondo',
        'third' => 'terzo',
        'fourth' => 'quarto',
        'fifth' => 'quinto',
        'last' => 'ultimo',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/oc.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/bs.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/ta.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
    'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
    'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['காலை', 'மாலை'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - The Debian Project Christian Perrier bubulle@debian.org
 */
return [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'MMMM DD, YYYY',
        'LLL' => 'DD MMM HH:mm',
        'LLLL' => 'MMMM DD, YYYY HH:mm',
    ],
    'months' => ['sanwiy\'e', 'feebriy\'e', 'mars', 'awril', 'me', 'suwen', 'sulet', 'uut', 'septaambar', 'oktoobar', 'nowaambar', 'desaambar'],
    'months_short' => ['san', 'fee', 'mar', 'awr', 'me ', 'suw', 'sul', 'uut', 'sep', 'okt', 'now', 'des'],
    'weekdays' => ['dib\'eer', 'altine', 'talaata', 'allarba', 'alxames', 'ajjuma', 'gaawu'],
    'weekdays_short' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'],
    'weekdays_min' => ['dib', 'alt', 'tal', 'all', 'alx', 'ajj', 'gaa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'year' => ':count at',
    'month' => ':count wèr',
    'week' => ':count ayubés',
    'day' => ':count bés',
    'hour' => ':count waxtu',
    'minute' => ':count simili',
    'second' => ':count saa',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Muhi', 'Chilo'],
    'weekdays' => ['Liduva lyapili', 'Liduva lyatatu', 'Liduva lyanchechi', 'Liduva lyannyano', 'Liduva lyannyano na linji', 'Liduva lyannyano na mavili', 'Liduva litandi'],
    'weekdays_short' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
    'weekdays_min' => ['Ll2', 'Ll3', 'Ll4', 'Ll5', 'Ll6', 'Ll7', 'Ll1'],
    'months' => ['Mwedi Ntandi', 'Mwedi wa Pili', 'Mwedi wa Tatu', 'Mwedi wa Nchechi', 'Mwedi wa Nnyano', 'Mwedi wa Nnyano na Umo', 'Mwedi wa Nnyano na Mivili', 'Mwedi wa Nnyano na Mitatu', 'Mwedi wa Nnyano na Nchechi', 'Mwedi wa Nnyano na Nnyano', 'Mwedi wa Nnyano na Nnyano na U', 'Mwedi wa Nnyano na Nnyano na M'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - PeshSajSoft Ltd. Vyacheslav Kileev slavakileev@yandex.ru
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY.MM.DD',
    ],
    'months' => ['Шорыкйол', 'Пургыж', 'Ӱярня', 'Вӱдшор', 'Ага', 'Пеледыш', 'Сӱрем', 'Сорла', 'Идым', 'Шыжа', 'Кылме', 'Теле'],
    'months_short' => ['Шрк', 'Пгж', 'Ӱрн', 'Вшр', 'Ага', 'Пдш', 'Срм', 'Срл', 'Идм', 'Шыж', 'Клм', 'Тел'],
    'weekdays' => ['Рушарня', 'Шочмо', 'Кушкыжмо', 'Вӱргече', 'Изарня', 'Кугарня', 'Шуматкече'],
    'weekdays_short' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'],
    'weekdays_min' => ['Ршр', 'Шчм', 'Кжм', 'Вгч', 'Изр', 'Кгр', 'Шмт'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => ':count идалык',
    'y' => ':count идалык',
    'a_year' => ':count идалык',

    'month' => ':count Тылзе',
    'm' => ':count Тылзе',
    'a_month' => ':count Тылзе',

    'week' => ':count арня',
    'w' => ':count арня',
    'a_week' => ':count арня',

    'day' => ':count кече',
    'd' => ':count кече',
    'a_day' => ':count кече',

    'hour' => ':count час',
    'h' => ':count час',
    'a_hour' => ':count час',

    'minute' => ':count минут',
    'min' => ':count минут',
    'a_minute' => ':count минут',

    'second' => ':count кокымшан',
    's' => ':count кокымшан',
    'a_second' => ':count кокымшан',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Jordi Mallach jordi@gnu.org
 * - Adolfo Jayme-Barrientos (fitojb)
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['de xineru', 'de febreru', 'de marzu', 'd’abril', 'de mayu', 'de xunu', 'de xunetu', 'd’agostu', 'de setiembre', 'd’ochobre', 'de payares', 'd’avientu'],
    'months_short' => ['xin', 'feb', 'mar', 'abr', 'may', 'xun', 'xnt', 'ago', 'set', 'och', 'pay', 'avi'],
    'weekdays' => ['domingu', 'llunes', 'martes', 'miércoles', 'xueves', 'vienres', 'sábadu'],
    'weekdays_short' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'],
    'weekdays_min' => ['dom', 'llu', 'mar', 'mié', 'xue', 'vie', 'sáb'],

    'year' => ':count añu|:count años',
    'y' => ':count añu|:count años',
    'a_year' => 'un añu|:count años',

    'month' => ':count mes',
    'm' => ':count mes',
    'a_month' => 'un mes|:count mes',

    'week' => ':count selmana|:count selmanes',
    'w' => ':count selmana|:count selmanes',
    'a_week' => 'una selmana|:count selmanes',

    'day' => ':count día|:count díes',
    'd' => ':count día|:count díes',
    'a_day' => 'un día|:count díes',

    'hour' => ':count hora|:count hores',
    'h' => ':count hora|:count hores',
    'a_hour' => 'una hora|:count hores',

    'minute' => ':count minutu|:count minutos',
    'min' => ':count minutu|:count minutos',
    'a_minute' => 'un minutu|:count minutos',

    'second' => ':count segundu|:count segundos',
    's' => ':count segundu|:count segundos',
    'a_second' => 'un segundu|:count segundos',

    'ago' => 'hai :time',
    'from_now' => 'en :time',
    'after' => ':time dempués',
    'before' => ':time enantes',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/wae_CH.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/nl.php', [
    'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
    'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
    'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
    'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat Pune    libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'],
    'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'एप्रैल', 'मेई', 'जून', 'जूलै', 'अगस्त', 'सितंबर', 'अक्तूबर', 'नवंबर', 'दिसंबर'],
    'weekdays' => ['ऐतबार', 'सोमबार', 'मंगलबर', 'बुधबार', 'बीरबार', 'शुक्करबार', 'श्नीचरबार'],
    'weekdays_short' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'],
    'weekdays_min' => ['ऐत', 'सोम', 'मंगल', 'बुध', 'बीर', 'शुक्कर', 'श्नीचर'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['सञं', 'सबेर'],

    'second' => ':count सङार', // less reliable
    's' => ':count सङार', // less reliable
    'a_second' => ':count सङार', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'weekdays' => ['Sonto', 'Mvulo', 'Sibili', 'Sithathu', 'Sine', 'Sihlanu', 'Mgqibelo'],
    'weekdays_short' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
    'weekdays_min' => ['Son', 'Mvu', 'Sib', 'Sit', 'Sin', 'Sih', 'Mgq'],
    'months' => ['Zibandlela', 'Nhlolanja', 'Mbimbitho', 'Mabasa', 'Nkwenkwezi', 'Nhlangula', 'Ntulikazi', 'Ncwabakazi', 'Mpandula', 'Mfumfu', 'Lwezi', 'Mpalakazi'],
    'months_short' => ['Zib', 'Nhlo', 'Mbi', 'Mab', 'Nkw', 'Nhla', 'Ntu', 'Ncw', 'Mpan', 'Mfu', 'Lwe', 'Mpal'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'year' => 'okweminyaka engu-:count', // less reliable
    'y' => 'okweminyaka engu-:count', // less reliable
    'a_year' => 'okweminyaka engu-:count', // less reliable

    'month' => 'inyanga ezingu-:count',
    'm' => 'inyanga ezingu-:count',
    'a_month' => 'inyanga ezingu-:count',

    'week' => 'amaviki angu-:count',
    'w' => 'amaviki angu-:count',
    'a_week' => 'amaviki angu-:count',

    'day' => 'kwamalanga angu-:count',
    'd' => 'kwamalanga angu-:count',
    'a_day' => 'kwamalanga angu-:count',

    'hour' => 'amahola angu-:count',
    'h' => 'amahola angu-:count',
    'a_hour' => 'amahola angu-:count',

    'minute' => 'imizuzu engu-:count',
    'min' => 'imizuzu engu-:count',
    'a_minute' => 'imizuzu engu-:count',

    'second' => 'imizuzwana engu-:count',
    's' => 'imizuzwana engu-:count',
    'a_second' => 'imizuzwana engu-:count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RockET Systems Emani Fakaotimanava-Lui emani@niue.nu
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Ianuali', 'Fepuali', 'Masi', 'Apelila', 'Me', 'Iuni', 'Iulai', 'Aokuso', 'Sepetema', 'Oketopa', 'Novema', 'Tesemo'],
    'months_short' => ['Ian', 'Fep', 'Mas', 'Ape', 'Me', 'Iun', 'Iul', 'Aok', 'Sep', 'Oke', 'Nov', 'Tes'],
    'weekdays' => ['Aho Tapu', 'Aho Gofua', 'Aho Ua', 'Aho Lotu', 'Aho Tuloto', 'Aho Falaile', 'Aho Faiumu'],
    'weekdays_short' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'],
    'weekdays_min' => ['Tapu', 'Gofua', 'Ua', 'Lotu', 'Tuloto', 'Falaile', 'Faiumu'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => ':count tau',
    'y' => ':count tau',
    'a_year' => ':count tau',

    'month' => ':count mahina',
    'm' => ':count mahina',
    'a_month' => ':count mahina',

    'week' => ':count faahi tapu',
    'w' => ':count faahi tapu',
    'a_week' => ':count faahi tapu',

    'day' => ':count aho',
    'd' => ':count aho',
    'a_day' => ':count aho',

    'hour' => ':count e tulā',
    'h' => ':count e tulā',
    'a_hour' => ':count e tulā',

    'minute' => ':count minuti',
    'min' => ':count minuti',
    'a_minute' => ':count minuti',

    'second' => ':count sekone',
    's' => ':count sekone',
    'a_second' => ':count sekone',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Rene Torres Rene Torres, Pablo Saratxaga rgtorre@rocketmail.com, pablo@mandrakesoft.com
 * - Jaycee Mariano (alohajaycee)
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'MM/DD/YY',
    ],
    'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
    'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkoles', 'Huwebes', 'Biyernes', 'Sabado'],
    'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    'weekdays_min' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['N.U.', 'N.H.'],

    'before' => ':time bago',
    'after' => ':time pagkatapos',

    'year' => ':count taon',
    'y' => ':count taon',
    'a_year' => ':count taon',

    'month' => ':count buwan',
    'm' => ':count buwan',
    'a_month' => ':count buwan',

    'week' => ':count linggo',
    'w' => ':count linggo',
    'a_week' => ':count linggo',

    'day' => ':count araw',
    'd' => ':count araw',
    'a_day' => ':count araw',

    'hour' => ':count oras',
    'h' => ':count oras',
    'a_hour' => ':count oras',

    'minute' => ':count minuto',
    'min' => ':count minuto',
    'a_minute' => ':count minuto',

    'second' => ':count segundo',
    's' => ':count segundo',
    'a_second' => ':count segundo',

    'ago' => ':time ang nakalipas',
    'from_now' => 'sa :time',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kunal Marwaha
 * - Alim Boyaq
 */
return require __DIR__.'/ug.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ccp.php', [
    'weekend' => [0, 0],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/tg.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/teo.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hant.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY年MM月DD日',
    ],
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
    'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'],
    'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['頂晡', '下晡'],

    'year' => ':count 年',
    'y' => ':count 年',
    'a_year' => ':count 年',

    'month' => ':count goe̍h',
    'm' => ':count goe̍h',
    'a_month' => ':count goe̍h',

    'week' => ':count lé-pài',
    'w' => ':count lé-pài',
    'a_week' => ':count lé-pài',

    'day' => ':count 日',
    'd' => ':count 日',
    'a_day' => ':count 日',

    'hour' => ':count tiám-cheng',
    'h' => ':count tiám-cheng',
    'a_hour' => ':count tiám-cheng',

    'minute' => ':count Hun-cheng',
    'min' => ':count Hun-cheng',
    'a_minute' => ':count Hun-cheng',

    'second' => ':count Bió',
    's' => ':count Bió',
    'a_second' => ':count Bió',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/eu.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/he.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ca.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - tjku
 * - valdas406
 * - Justas Palumickas
 * - Max Melentiev
 * - Andrius Janauskas
 * - Juanito Fatas
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Nicolás Hock Isaza
 * - Laurynas Butkus
 * - Sven Fuchs
 * - Dominykas Tijūnaitis
 * - Justinas Bolys
 * - Ričardas
 * - Kirill Chalkin
 * - Rolandas
 * - Justinas (Gamesh)
 * - Sam Axe
 */
return [
    'year' => ':count metai|:count metai|:count metų',
    'y' => ':count m.',
    'month' => ':count mėnuo|:count mėnesiai|:count mėnesį',
    'm' => ':count mėn.',
    'week' => ':count savaitė|:count savaitės|:count savaitę',
    'w' => ':count sav.',
    'day' => ':count diena|:count dienos|:count dienų',
    'd' => ':count d.',
    'hour' => ':count valanda|:count valandos|:count valandų',
    'h' => ':count val.',
    'minute' => ':count minutė|:count minutės|:count minutę',
    'min' => ':count min.',
    'second' => ':count sekundė|:count sekundės|:count sekundžių',
    's' => ':count sek.',

    'year_ago' => ':count metus|:count metus|:count metų',
    'month_ago' => ':count mėnesį|:count mėnesius|:count mėnesių',
    'week_ago' => ':count savaitę|:count savaites|:count savaičių',
    'day_ago' => ':count dieną|:count dienas|:count dienų',
    'hour_ago' => ':count valandą|:count valandas|:count valandų',
    'minute_ago' => ':count minutę|:count minutes|:count minučių',
    'second_ago' => ':count sekundę|:count sekundes|:count sekundžių',

    'year_from_now' => ':count metai|:count metai|:count metų',
    'month_from_now' => ':count mėnuo|:count mėnesiai|:count mėnesių',
    'week_from_now' => ':count savaitė|:count savaitės|:count savaičių',
    'day_from_now' => ':count diena|:count dienos|:count dienų',
    'hour_from_now' => ':count valanda|:count valandos|:count valandų',
    'minute_from_now' => ':count minutė|:count minutės|:count minučių',
    'second_from_now' => ':count sekundė|:count sekundės|:count sekundžių',

    'year_after' => ':count metai|:count metai|:count metų',
    'month_after' => ':count mėnuo|:count mėnesiai|:count mėnesių',
    'week_after' => ':count savaitė|:count savaitės|:count savaičių',
    'day_after' => ':count diena|:count dienos|:count dienų',
    'hour_after' => ':count valanda|:count valandos|:count valandų',
    'minute_after' => ':count minutė|:count minutės|:count minučių',
    'second_after' => ':count sekundė|:count sekundės|:count sekundžių',

    'year_before' => ':count metų',
    'month_before' => ':count mėnesio|:count mėnesių|:count mėnesių',
    'week_before' => ':count savaitės|:count savaičių|:count savaičių',
    'day_before' => ':count dienos|:count dienų|:count dienų',
    'hour_before' => ':count valandos|:count valandų|:count valandų',
    'minute_before' => ':count minutės|:count minučių|:count minučių',
    'second_before' => ':count sekundės|:count sekundžių|:count sekundžių',

    'ago' => 'prieš :time',
    'from_now' => ':time nuo dabar',
    'after' => 'po :time',
    'before' => 'už :time',

    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'diff_now' => 'ką tik',
    'diff_today' => 'Šiandien',
    'diff_yesterday' => 'vakar',
    'diff_yesterday_regexp' => 'Vakar',
    'diff_tomorrow' => 'rytoj',
    'diff_tomorrow_regexp' => 'Rytoj',
    'diff_before_yesterday' => 'užvakar',
    'diff_after_tomorrow' => 'poryt',

    'period_recurrences' => 'kartą|:count kartų',
    'period_interval' => 'kiekvieną :interval',
    'period_start_date' => 'nuo :date',
    'period_end_date' => 'iki :date',

    'months' => ['sausio', 'vasario', 'kovo', 'balandžio', 'gegužės', 'birželio', 'liepos', 'rugpjūčio', 'rugsėjo', 'spalio', 'lapkričio', 'gruodžio'],
    'months_standalone' => ['sausis', 'vasaris', 'kovas', 'balandis', 'gegužė', 'birželis', 'liepa', 'rugpjūtis', 'rugsėjis', 'spalis', 'lapkritis', 'gruodis'],
    'months_regexp' => '/(L{2,4}|D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?)/',
    'months_short' => ['sau', 'vas', 'kov', 'bal', 'geg', 'bir', 'lie', 'rgp', 'rgs', 'spa', 'lap', 'gru'],
    'weekdays' => ['sekmadienį', 'pirmadienį', 'antradienį', 'trečiadienį', 'ketvirtadienį', 'penktadienį', 'šeštadienį'],
    'weekdays_standalone' => ['sekmadienis', 'pirmadienis', 'antradienis', 'trečiadienis', 'ketvirtadienis', 'penktadienis', 'šeštadienis'],
    'weekdays_short' => ['sek', 'pir', 'ant', 'tre', 'ket', 'pen', 'šeš'],
    'weekdays_min' => ['se', 'pi', 'an', 'tr', 'ke', 'pe', 'še'],
    'list' => [', ', ' ir '],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'MMMM DD, YYYY',
        'LLL' => 'DD MMM HH:mm',
        'LLLL' => 'MMMM DD, YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Šiandien] LT',
        'nextDay' => '[Rytoj] LT',
        'nextWeek' => 'dddd LT',
        'lastDay' => '[Vakar] LT',
        'lastWeek' => '[Paskutinį] dddd LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        return match ($number) {
            0 => '0-is',
            3 => '3-ias',
            default => "$number-as",
        };
    },
    'meridiem' => ['priešpiet', 'popiet'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Jor Teron    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['Arkoi', 'Thangthang', 'There', 'Jangmi', 'Aru', 'Vosik', 'Jakhong', 'Paipai', 'Chiti', 'Phere', 'Phaikuni', 'Matijong'],
    'months_short' => ['Ark', 'Thang', 'The', 'Jang', 'Aru', 'Vos', 'Jak', 'Pai', 'Chi', 'Phe', 'Phai', 'Mati'],
    'weekdays' => ['Bhomkuru', 'Urmi', 'Durmi', 'Thelang', 'Theman', 'Bhomta', 'Bhomti'],
    'weekdays_short' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'],
    'weekdays_min' => ['Bhom', 'Ur', 'Dur', 'Tkel', 'Tkem', 'Bhta', 'Bhti'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Gastaldi    alessio.gastaldi@libero.it
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['zenâ', 'fevrâ', 'marzo', 'avrî', 'mazzo', 'zûgno', 'lûggio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dixembre'],
    'months_short' => ['zen', 'fev', 'mar', 'arv', 'maz', 'zûg', 'lûg', 'ago', 'set', 'ött', 'nov', 'dix'],
    'weekdays' => ['domenega', 'lûnedì', 'martedì', 'mercUrdì', 'zêggia', 'venardì', 'sabbo'],
    'weekdays_short' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'],
    'weekdays_min' => ['dom', 'lûn', 'mar', 'mer', 'zêu', 'ven', 'sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count etæ', // less reliable
    'y' => ':count etæ', // less reliable
    'a_year' => ':count etæ', // less reliable

    'month' => ':count meize',
    'm' => ':count meize',
    'a_month' => ':count meize',

    'week' => ':count settemannha',
    'w' => ':count settemannha',
    'a_week' => ':count settemannha',

    'day' => ':count giorno',
    'd' => ':count giorno',
    'a_day' => ':count giorno',

    'hour' => ':count reléuio', // less reliable
    'h' => ':count reléuio', // less reliable
    'a_hour' => ':count reléuio', // less reliable

    'minute' => ':count menûo',
    'min' => ':count menûo',
    'a_minute' => ':count menûo',

    'second' => ':count segondo',
    's' => ':count segondo',
    'a_second' => ':count segondo',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kunal Marwaha
 * - François B
 * - Mayank Badola
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm A',
        'LLLL' => 'dddd, D MMMM YYYY h:mm A',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - meghrajsuthar03@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'],
    'months_short' => ['जन', 'फर', 'मार्च', 'अप्रै', 'मई', 'जून', 'जुल', 'अग', 'सित', 'अक्टू', 'नव', 'दिस'],
    'weekdays' => ['रविवार', 'सोमवार', 'मंगल्लवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'],
    'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
    'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],

    'year' => ':count आंहू', // less reliable
    'y' => ':count आंहू', // less reliable
    'a_year' => ':count आंहू', // less reliable

    'month' => ':count सूरज', // less reliable
    'm' => ':count सूरज', // less reliable
    'a_month' => ':count सूरज', // less reliable

    'week' => ':count निवाज', // less reliable
    'w' => ':count निवाज', // less reliable
    'a_week' => ':count निवाज', // less reliable

    'day' => ':count अेक', // less reliable
    'd' => ':count अेक', // less reliable
    'a_day' => ':count अेक', // less reliable

    'hour' => ':count दुनियांण', // less reliable
    'h' => ':count दुनियांण', // less reliable
    'a_hour' => ':count दुनियांण', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/unm_US.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'],
    'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'],
    'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'],
    'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
    'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ru.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Amitakhya Phukan, Red Hat    bug-glibc@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D-MM-YYYY',
    ],
    'months' => ['জানুৱাৰী', 'ফেব্ৰুৱাৰী', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগষ্ট', 'ছেপ্তেম্বৰ', 'অক্টোবৰ', 'নৱেম্বৰ', 'ডিচেম্বৰ'],
    'months_short' => ['জানু', 'ফেব্ৰু', 'মাৰ্চ', 'এপ্ৰিল', 'মে', 'জুন', 'জুলাই', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
    'weekdays' => ['দেওবাৰ', 'সোমবাৰ', 'মঙ্গলবাৰ', 'বুধবাৰ', 'বৃহষ্পতিবাৰ', 'শুক্ৰবাৰ', 'শনিবাৰ'],
    'weekdays_short' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
    'weekdays_min' => ['দেও', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহষ্পতি', 'শুক্ৰ', 'শনি'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['পূৰ্ব্বাহ্ন', 'অপৰাহ্ন'],

    'year' => ':count বছৰ',
    'y' => ':count বছৰ',
    'a_year' => ':count বছৰ',

    'month' => ':count মাহ',
    'm' => ':count মাহ',
    'a_month' => ':count মাহ',

    'week' => ':count সপ্তাহ',
    'w' => ':count সপ্তাহ',
    'a_week' => ':count সপ্তাহ',

    'day' => ':count বাৰ',
    'd' => ':count বাৰ',
    'a_day' => ':count বাৰ',

    'hour' => ':count ঘণ্টা',
    'h' => ':count ঘণ্টা',
    'a_hour' => ':count ঘণ্টা',

    'minute' => ':count মিনিট',
    'min' => ':count মিনিট',
    'a_minute' => ':count মিনিট',

    'second' => ':count দ্বিতীয়',
    's' => ':count দ্বিতীয়',
    'a_second' => ':count দ্বিতীয়',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['Sande', 'Orwokubanza', 'Orwakabiri', 'Orwakashatu', 'Orwakana', 'Orwakataano', 'Orwamukaaga'],
    'weekdays_short' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    'weekdays_min' => ['SAN', 'ORK', 'OKB', 'OKS', 'OKN', 'OKT', 'OMK'],
    'months' => ['Okwokubanza', 'Okwakabiri', 'Okwakashatu', 'Okwakana', 'Okwakataana', 'Okwamukaaga', 'Okwamushanju', 'Okwamunaana', 'Okwamwenda', 'Okwaikumi', 'Okwaikumi na kumwe', 'Okwaikumi na ibiri'],
    'months_short' => ['KBZ', 'KBR', 'KST', 'KKN', 'KTN', 'KMK', 'KMS', 'KMN', 'KMW', 'KKM', 'KNK', 'KNB'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'day' => ':count ruhanga', // less reliable
    'd' => ':count ruhanga', // less reliable
    'a_day' => ':count ruhanga', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['RŨ', 'ŨG'],
    'weekdays' => ['Kiumia', 'Muramuko', 'Wairi', 'Wethatu', 'Wena', 'Wetano', 'Jumamosi'],
    'weekdays_short' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
    'weekdays_min' => ['KIU', 'MRA', 'WAI', 'WET', 'WEN', 'WTN', 'JUM'],
    'months' => ['Januarĩ', 'Feburuarĩ', 'Machi', 'Ĩpurũ', 'Mĩĩ', 'Njuni', 'Njuraĩ', 'Agasti', 'Septemba', 'Oktũba', 'Novemba', 'Dicemba'],
    'months_short' => ['JAN', 'FEB', 'MAC', 'ĨPU', 'MĨĨ', 'NJU', 'NJR', 'AGA', 'SPT', 'OKT', 'NOV', 'DEC'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'year' => ':count murume', // less reliable
    'y' => ':count murume', // less reliable
    'a_year' => ':count murume', // less reliable

    'month' => ':count muchaara', // less reliable
    'm' => ':count muchaara', // less reliable
    'a_month' => ':count muchaara', // less reliable

    'minute' => ':count monto', // less reliable
    'min' => ':count monto', // less reliable
    'a_minute' => ':count monto', // less reliable

    'second' => ':count gikeno', // less reliable
    's' => ':count gikeno', // less reliable
    'a_second' => ':count gikeno', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hant_TW.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - NehaGautam
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD-MM-YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/sw.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - mhamlet
 */
return [
    'year' => ':count տարի',
    'a_year' => 'տարի|:count տարի',
    'y' => ':countտ',
    'month' => ':count ամիս',
    'a_month' => 'ամիս|:count ամիս',
    'm' => ':countամ',
    'week' => ':count շաբաթ',
    'a_week' => 'շաբաթ|:count շաբաթ',
    'w' => ':countշ',
    'day' => ':count օր',
    'a_day' => 'օր|:count օր',
    'd' => ':countօր',
    'hour' => ':count ժամ',
    'a_hour' => 'ժամ|:count ժամ',
    'h' => ':countժ',
    'minute' => ':count րոպե',
    'a_minute' => 'րոպե|:count րոպե',
    'min' => ':countր',
    'second' => ':count վայրկյան',
    'a_second' => 'մի քանի վայրկյան|:count վայրկյան',
    's' => ':countվրկ',
    'ago' => ':time առաջ',
    'from_now' => ':timeից',
    'after' => ':time հետո',
    'before' => ':time առաջ',
    'diff_now' => 'հիմա',
    'diff_today' => 'այսօր',
    'diff_yesterday' => 'երեկ',
    'diff_tomorrow' => 'վաղը',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY թ.',
        'LLL' => 'D MMMM YYYY թ., HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY թ., HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[այսօր] LT',
        'nextDay' => '[վաղը] LT',
        'nextWeek' => 'dddd [օրը ժամը] LT',
        'lastDay' => '[երեկ] LT',
        'lastWeek' => '[անցած] dddd [օրը ժամը] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'DDD', 'w', 'W', 'DDDo' => $number.($number === 1 ? '-ին' : '-րդ'),
            default => $number,
        };
    },
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'գիշերվա';
        }
        if ($hour < 12) {
            return 'առավոտվա';
        }
        if ($hour < 17) {
            return 'ցերեկվա';
        }

        return 'երեկոյան';
    },
    'months' => ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի', 'մայիսի', 'հունիսի', 'հուլիսի', 'օգոստոսի', 'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի', 'դեկտեմբերի'],
    'months_standalone' => ['հունվար', 'փետրվար', 'մարտ', 'ապրիլ', 'մայիս', 'հունիս', 'հուլիս', 'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր', 'նոյեմբեր', 'դեկտեմբեր'],
    'months_short' => ['հնվ', 'փտր', 'մրտ', 'ապր', 'մյս', 'հնս', 'հլս', 'օգս', 'սպտ', 'հկտ', 'նմբ', 'դկտ'],
    'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['կիրակի', 'երկուշաբթի', 'երեքշաբթի', 'չորեքշաբթի', 'հինգշաբթի', 'ուրբաթ', 'շաբաթ'],
    'weekdays_short' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'],
    'weekdays_min' => ['կրկ', 'երկ', 'երք', 'չրք', 'հնգ', 'ուրբ', 'շբթ'],
    'list' => [', ', ' եւ '],
    'first_day_of_week' => 1,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['ip.', 'ep.'],
    'weekdays' => ['pasepeeivi', 'vuossaargâ', 'majebaargâ', 'koskoho', 'tuorâstuv', 'vástuppeeivi', 'lávurduv'],
    'weekdays_short' => ['pas', 'vuo', 'maj', 'kos', 'tuo', 'vás', 'láv'],
    'weekdays_min' => ['pa', 'vu', 'ma', 'ko', 'tu', 'vá', 'lá'],
    'weekdays_standalone' => ['pasepeivi', 'vuossargâ', 'majebargâ', 'koskokko', 'tuorâstâh', 'vástuppeivi', 'lávurdâh'],
    'months' => ['uđđâivemáánu', 'kuovâmáánu', 'njuhčâmáánu', 'cuáŋuimáánu', 'vyesimáánu', 'kesimáánu', 'syeinimáánu', 'porgemáánu', 'čohčâmáánu', 'roovvâdmáánu', 'skammâmáánu', 'juovlâmáánu'],
    'months_short' => ['uđiv', 'kuovâ', 'njuhčâ', 'cuáŋui', 'vyesi', 'kesi', 'syeini', 'porge', 'čohčâ', 'roovvâd', 'skammâ', 'juovlâ'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'H.mm',
        'LTS' => 'H.mm.ss',
        'L' => 'D.M.YYYY',
        'LL' => 'MMM D. YYYY',
        'LLL' => 'MMMM D. YYYY H.mm',
        'LLLL' => 'dddd, MMMM D. YYYY H.mm',
    ],

    'hour' => ':count äigi', // less reliable
    'h' => ':count äigi', // less reliable
    'a_hour' => ':count äigi', // less reliable

    'year' => ':count ihe',
    'y' => ':count ihe',
    'a_year' => ':count ihe',

    'month' => ':count mánuppaje',
    'm' => ':count mánuppaje',
    'a_month' => ':count mánuppaje',

    'week' => ':count okko',
    'w' => ':count okko',
    'a_week' => ':count okko',

    'day' => ':count peivi',
    'd' => ':count peivi',
    'a_day' => ':count peivi',

    'minute' => ':count miinut',
    'min' => ':count miinut',
    'a_minute' => ':count miinut',

    'second' => ':count nubbe',
    's' => ':count nubbe',
    'a_second' => ':count nubbe',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/yo.php', [
    'meridiem' => ['Àárɔ̀', 'Ɔ̀sán'],
    'weekdays' => ['Ɔjɔ́ Àìkú', 'Ɔjɔ́ Ajé', 'Ɔjɔ́ Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɔjɔ́ Ɛtì', 'Ɔjɔ́ Àbámɛ́ta'],
    'weekdays_short' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
    'weekdays_min' => ['Àìkú', 'Ajé', 'Ìsɛ́gun', 'Ɔjɔ́rú', 'Ɔjɔ́bɔ', 'Ɛtì', 'Àbámɛ́ta'],
    'months' => ['Oshù Shɛ́rɛ́', 'Oshù Èrèlè', 'Oshù Ɛrɛ̀nà', 'Oshù Ìgbé', 'Oshù Ɛ̀bibi', 'Oshù Òkúdu', 'Oshù Agɛmɔ', 'Oshù Ògún', 'Oshù Owewe', 'Oshù Ɔ̀wàrà', 'Oshù Bélú', 'Oshù Ɔ̀pɛ̀'],
    'months_short' => ['Shɛ́rɛ́', 'Èrèlè', 'Ɛrɛ̀nà', 'Ìgbé', 'Ɛ̀bibi', 'Òkúdu', 'Agɛmɔ', 'Ògún', 'Owewe', 'Ɔ̀wàrà', 'Bélú', 'Ɔ̀pɛ̀'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'],
    'weekdays_short' => ['Aneg 1', 'Aneg 2', 'Aneg 3', 'Aneg 4', 'Aneg 5', 'Aneg 6', 'Aneg 7'],
    'weekdays_min' => ['1', '2', '3', '4', '5', '6', '7'],
    'months' => ['iməg mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'],
    'months_short' => ['mbegtug', 'imeg àbùbì', 'imeg mbəŋchubi', 'iməg ngwə̀t', 'iməg fog', 'iməg ichiibɔd', 'iməg àdùmbə̀ŋ', 'iməg ichika', 'iməg kud', 'iməg tèsiʼe', 'iməg zò', 'iməg krizmed'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'dddd, YYYY MMMM DD HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Jakub Tesinsky
 * - Martin Suja
 * - Nikos Timiopulos
 * - Bohuslav Blín
 * - Tsutomu Kuroda
 * - tjku
 * - Lukas Svoboda
 * - Max Melentiev
 * - Juanito Fatas
 * - Akira Matsuda
 * - Christopher Dell
 * - Václav Pávek
 * - CodeSkills
 * - Tlapi
 * - newman101
 * - Petr Kadlec
 * - tommaskraus
 * - Karel Sommer (calvera)
 */
$za = function ($time) {
    return 'za '.strtr($time, [
        'hodina' => 'hodinu',
        'minuta' => 'minutu',
        'sekunda' => 'sekundu',
    ]);
};

$pred = function ($time) {
    $time = strtr($time, [
        'hodina' => 'hodinou',
        'minuta' => 'minutou',
        'sekunda' => 'sekundou',
    ]);
    $time = preg_replace('/hodiny?(?!\w)/', 'hodinami', $time);
    $time = preg_replace('/minuty?(?!\w)/', 'minutami', $time);
    $time = preg_replace('/sekundy?(?!\w)/', 'sekundami', $time);

    return "před $time";
};

return [
    'year' => ':count rok|:count roky|:count let',
    'y' => ':count rok|:count roky|:count let',
    'a_year' => 'rok|:count roky|:count let',
    'month' => ':count měsíc|:count měsíce|:count měsíců',
    'm' => ':count měs.',
    'a_month' => 'měsíc|:count měsíce|:count měsíců',
    'week' => ':count týden|:count týdny|:count týdnů',
    'w' => ':count týd.',
    'a_week' => 'týden|:count týdny|:count týdnů',
    'day' => ':count den|:count dny|:count dní',
    'd' => ':count den|:count dny|:count dní',
    'a_day' => 'den|:count dny|:count dní',
    'hour' => ':count hodina|:count hodiny|:count hodin',
    'h' => ':count hod.',
    'a_hour' => 'hodina|:count hodiny|:count hodin',
    'minute' => ':count minuta|:count minuty|:count minut',
    'min' => ':count min.',
    'a_minute' => 'minuta|:count minuty|:count minut',
    'second' => ':count sekunda|:count sekundy|:count sekund',
    's' => ':count sek.',
    'a_second' => 'pár sekund|:count sekundy|:count sekund',

    'month_ago' => ':count měsícem|:count měsíci|:count měsíci',
    'a_month_ago' => 'měsícem|:count měsíci|:count měsíci',
    'day_ago' => ':count dnem|:count dny|:count dny',
    'a_day_ago' => 'dnem|:count dny|:count dny',
    'week_ago' => ':count týdnem|:count týdny|:count týdny',
    'a_week_ago' => 'týdnem|:count týdny|:count týdny',
    'year_ago' => ':count rokem|:count roky|:count lety',
    'y_ago' => ':count rok.|:count rok.|:count let.',
    'a_year_ago' => 'rokem|:count roky|:count lety',

    'month_before' => ':count měsícem|:count měsíci|:count měsíci',
    'a_month_before' => 'měsícem|:count měsíci|:count měsíci',
    'day_before' => ':count dnem|:count dny|:count dny',
    'a_day_before' => 'dnem|:count dny|:count dny',
    'week_before' => ':count týdnem|:count týdny|:count týdny',
    'a_week_before' => 'týdnem|:count týdny|:count týdny',
    'year_before' => ':count rokem|:count roky|:count lety',
    'y_before' => ':count rok.|:count rok.|:count let.',
    'a_year_before' => 'rokem|:count roky|:count lety',

    'ago' => $pred,
    'from_now' => $za,
    'before' => $pred,
    'after' => $za,
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'months' => ['ledna', 'února', 'března', 'dubna', 'května', 'června', 'července', 'srpna', 'září', 'října', 'listopadu', 'prosince'],
    'months_standalone' => ['leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'],
    'months_short' => ['led', 'úno', 'bře', 'dub', 'kvě', 'čvn', 'čvc', 'srp', 'zář', 'říj', 'lis', 'pro'],
    'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
    'weekdays_short' => ['ned', 'pon', 'úte', 'stř', 'čtv', 'pát', 'sob'],
    'weekdays_min' => ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
    'list' => [', ', ' a '],
    'diff_now' => 'nyní',
    'diff_yesterday' => 'včera',
    'diff_tomorrow' => 'zítra',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD. MM. YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd D. MMMM YYYY HH:mm',
    ],
    'meridiem' => ['dopoledne', 'odpoledne'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/kab_DZ.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - JD Isaacks
 */
return [
    'year' => 'urte bat|:count urte',
    'y' => 'Urte 1|:count urte',
    'month' => 'hilabete bat|:count hilabete',
    'm' => 'Hile 1|:count hile',
    'week' => 'Aste 1|:count aste',
    'w' => 'Aste 1|:count aste',
    'day' => 'egun bat|:count egun',
    'd' => 'Egun 1|:count egun',
    'hour' => 'ordu bat|:count ordu',
    'h' => 'Ordu 1|:count ordu',
    'minute' => 'minutu bat|:count minutu',
    'min' => 'Minutu 1|:count minutu',
    'second' => 'segundo batzuk|:count segundo',
    's' => 'Segundu 1|:count segundu',
    'ago' => 'duela :time',
    'from_now' => ':time barru',
    'after' => ':time geroago',
    'before' => ':time lehenago',
    'diff_now' => 'orain',
    'diff_today' => 'gaur',
    'diff_yesterday' => 'atzo',
    'diff_tomorrow' => 'bihar',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'YYYY[ko] MMMM[ren] D[a]',
        'LLL' => 'YYYY[ko] MMMM[ren] D[a] HH:mm',
        'LLLL' => 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[gaur] LT[etan]',
        'nextDay' => '[bihar] LT[etan]',
        'nextWeek' => 'dddd LT[etan]',
        'lastDay' => '[atzo] LT[etan]',
        'lastWeek' => '[aurreko] dddd LT[etan]',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['urtarrila', 'otsaila', 'martxoa', 'apirila', 'maiatza', 'ekaina', 'uztaila', 'abuztua', 'iraila', 'urria', 'azaroa', 'abendua'],
    'months_short' => ['urt.', 'ots.', 'mar.', 'api.', 'mai.', 'eka.', 'uzt.', 'abu.', 'ira.', 'urr.', 'aza.', 'abe.'],
    'weekdays' => ['igandea', 'astelehena', 'asteartea', 'asteazkena', 'osteguna', 'ostirala', 'larunbata'],
    'weekdays_short' => ['ig.', 'al.', 'ar.', 'az.', 'og.', 'ol.', 'lr.'],
    'weekdays_min' => ['ig', 'al', 'ar', 'az', 'og', 'ol', 'lr'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' eta '],
    'meridiem' => ['g', 'a'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/nl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Authors:
 * - JD Isaacks
 * - Atef Ben Ali (atefBB)
 * - Mohamed Sabil (mohamedsabil83)
 */
$months = [
    'جانفي',
    'فيفري',
    'مارس',
    'أفريل',
    'ماي',
    'جوان',
    'جويلية',
    'أوت',
    'سبتمبر',
    'أكتوبر',
    'نوفمبر',
    'ديسمبر',
];

return [
    'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => 'في :time',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم على الساعة] LT',
        'nextDay' => '[غدا على الساعة] LT',
        'nextWeek' => 'dddd [على الساعة] LT',
        'lastDay' => '[أمس على الساعة] LT',
        'lastWeek' => 'dddd [على الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/yo.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Softaragones Jordi Mallach Pérez, Juan Pablo Martínez bug-glibc-locales@gnu.org, softaragones@softaragones.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['chinero', 'febrero', 'marzo', 'abril', 'mayo', 'chunyo', 'chuliol', 'agosto', 'setiembre', 'octubre', 'noviembre', 'aviento'],
    'months_short' => ['chi', 'feb', 'mar', 'abr', 'may', 'chn', 'chl', 'ago', 'set', 'oct', 'nov', 'avi'],
    'weekdays' => ['domingo', 'luns', 'martes', 'mierques', 'chueves', 'viernes', 'sabado'],
    'weekdays_short' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'],
    'weekdays_min' => ['dom', 'lun', 'mar', 'mie', 'chu', 'vie', 'sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count año',
    'y' => ':count año',
    'a_year' => ':count año',

    'month' => ':count mes',
    'm' => ':count mes',
    'a_month' => ':count mes',

    'week' => ':count semana',
    'w' => ':count semana',
    'a_week' => ':count semana',

    'day' => ':count día',
    'd' => ':count día',
    'a_day' => ':count día',

    'hour' => ':count reloch', // less reliable
    'h' => ':count reloch', // less reliable
    'a_hour' => ':count reloch', // less reliable

    'minute' => ':count minuto',
    'min' => ':count minuto',
    'a_minute' => ':count minuto',

    'second' => ':count segundo',
    's' => ':count segundo',
    'a_second' => ':count segundo',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/quz_PE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ro.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/kn.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return [
    'year' => '[0,1]:count ar|:count ars',
    'y' => '[0,1]:count ar|:count ars',
    'month' => '[0,1]:count mes|:count mesen',
    'm' => '[0,1]:count mes|:count mesen',
    'week' => '[0,1]:count seifetziua|:count seifetziuas',
    'w' => '[0,1]:count seifetziua|:count seifetziuas',
    'day' => '[0,1]:count ziua|:count ziuas',
    'd' => '[0,1]:count ziua|:count ziuas',
    'hour' => '[0,1]:count þora|:count þoras',
    'h' => '[0,1]:count þora|:count þoras',
    'minute' => '[0,1]:count míut|:count míuts',
    'min' => '[0,1]:count míut|:count míuts',
    'second' => ':count secunds',
    's' => ':count secunds',

    'ago' => 'ja :time',
    'from_now' => 'osprei :time',

    'diff_yesterday' => 'ieiri',
    'diff_yesterday_regexp' => 'ieiri(?:\\s+à)?',
    'diff_today' => 'oxhi',
    'diff_today_regexp' => 'oxhi(?:\\s+à)?',
    'diff_tomorrow' => 'demà',
    'diff_tomorrow_regexp' => 'demà(?:\\s+à)?',

    'formats' => [
        'LT' => 'HH.mm',
        'LTS' => 'HH.mm.ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM [dallas] YYYY',
        'LLL' => 'D. MMMM [dallas] YYYY HH.mm',
        'LLLL' => 'dddd, [li] D. MMMM [dallas] YYYY HH.mm',
    ],

    'calendar' => [
        'sameDay' => '[oxhi à] LT',
        'nextDay' => '[demà à] LT',
        'nextWeek' => 'dddd [à] LT',
        'lastDay' => '[ieiri à] LT',
        'lastWeek' => '[sür el] dddd [lasteu à] LT',
        'sameElse' => 'L',
    ],

    'meridiem' => ["D'A", "D'O"],
    'months' => ['Januar', 'Fevraglh', 'Març', 'Avrïu', 'Mai', 'Gün', 'Julia', 'Guscht', 'Setemvar', 'Listopäts', 'Noemvar', 'Zecemvar'],
    'months_short' => ['Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Gün', 'Jul', 'Gus', 'Set', 'Lis', 'Noe', 'Zec'],
    'weekdays' => ['Súladi', 'Lúneçi', 'Maitzi', 'Márcuri', 'Xhúadi', 'Viénerçi', 'Sáturi'],
    'weekdays_short' => ['Súl', 'Lún', 'Mai', 'Már', 'Xhú', 'Vié', 'Sát'],
    'weekdays_min' => ['Sú', 'Lú', 'Ma', 'Má', 'Xh', 'Vi', 'Sá'],
    'ordinal' => ':number.',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'M/D/YY',
    ],
    'months' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एफ्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'],
    'months_short' => ['जानुवारी', 'फेब्रुवारी', 'मार्स', 'एप्रिल', 'मे', 'जुन', 'जुलाइ', 'आगस्थ', 'सेबथेज्ब़र', 'अखथबर', 'नबेज्ब़र', 'दिसेज्ब़र'],
    'weekdays' => ['रबिबार', 'सोबार', 'मंगलबार', 'बुदबार', 'बिसथिबार', 'सुखुरबार', 'सुनिबार'],
    'weekdays_short' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'],
    'weekdays_min' => ['रबि', 'सम', 'मंगल', 'बुद', 'बिसथि', 'सुखुर', 'सुनि'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['फुं.', 'बेलासे.'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Danish Standards Association    bug-glibc-locales@gnu.org
 * - John Eyðstein Johannesen (mashema)
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd [d.] D. MMMM YYYY [kl.] HH:mm',
    ],
    'months' => ['januaarip', 'februaarip', 'marsip', 'apriilip', 'maajip', 'juunip', 'juulip', 'aggustip', 'septembarip', 'oktobarip', 'novembarip', 'decembarip'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
    'weekdays' => ['sapaat', 'ataasinngorneq', 'marlunngorneq', 'pingasunngorneq', 'sisamanngorneq', 'tallimanngorneq', 'arfininngorneq'],
    'weekdays_short' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
    'weekdays_min' => ['sap', 'ata', 'mar', 'pin', 'sis', 'tal', 'arf'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => '{1}ukioq :count|{0}:count ukiut|[-Inf,Inf]ukiut :count',
    'a_year' => '{1}ukioq|{0}:count ukiut|[-Inf,Inf]ukiut :count',
    'y' => '{1}:countyr|{0}:countyrs|[-Inf,Inf]:countyrs',

    'month' => '{1}qaammat :count|{0}:count qaammatit|[-Inf,Inf]qaammatit :count',
    'a_month' => '{1}qaammat|{0}:count qaammatit|[-Inf,Inf]qaammatit :count',
    'm' => '{1}:countmo|{0}:countmos|[-Inf,Inf]:countmos',

    'week' => '{1}:count sap. ak.|{0}:count sap. ak.|[-Inf,Inf]:count sap. ak.',
    'a_week' => '{1}a sap. ak.|{0}:count sap. ak.|[-Inf,Inf]:count sap. ak.',
    'w' => ':countw',

    'day' => '{1}:count ulloq|{0}:count ullut|[-Inf,Inf]:count ullut',
    'a_day' => '{1}a ulloq|{0}:count ullut|[-Inf,Inf]:count ullut',
    'd' => ':countd',

    'hour' => '{1}:count tiimi|{0}:count tiimit|[-Inf,Inf]:count tiimit',
    'a_hour' => '{1}tiimi|{0}:count tiimit|[-Inf,Inf]:count tiimit',
    'h' => ':counth',

    'minute' => '{1}:count minutsi|{0}:count minutsit|[-Inf,Inf]:count minutsit',
    'a_minute' => '{1}a minutsi|{0}:count minutsit|[-Inf,Inf]:count minutsit',
    'min' => ':countm',

    'second' => '{1}:count sikunti|{0}:count sikuntit|[-Inf,Inf]:count sikuntit',
    'a_second' => '{1}sikunti|{0}:count sikuntit|[-Inf,Inf]:count sikuntit',
    's' => ':counts',

    'ago' => ':time matuma siorna',

]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'sr');
    }, 'sr_Cyrl_XK');
}
// @codeCoverageIgnoreEnd

return array_replace_recursive(require __DIR__.'/sr_Cyrl_BA.php', [
    'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return require __DIR__.'/so.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat, Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'M/D/YY',
    ],
    'months' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنؤری', 'فرؤری', 'مارٕچ', 'اپریل', 'میٔ', 'جوٗن', 'جوٗلایی', 'اگست', 'ستمبر', 'اکتوٗبر', 'نومبر', 'دسمبر'],
    'weekdays' => ['آتهوار', 'ژءندروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
    'weekdays_short' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
    'weekdays_min' => ['آتهوار', 'ژءنتروار', 'بوءںوار', 'بودهوار', 'برىسوار', 'جمع', 'بٹوار'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['دوپھربرونھ', 'دوپھرپتھ'],

    'year' => ':count آب', // less reliable
    'y' => ':count آب', // less reliable
    'a_year' => ':count آب', // less reliable

    'month' => ':count रान्', // less reliable
    'm' => ':count रान्', // less reliable
    'a_month' => ':count रान्', // less reliable

    'week' => ':count آتھٕوار', // less reliable
    'w' => ':count آتھٕوار', // less reliable
    'a_week' => ':count آتھٕوار', // less reliable

    'hour' => ':count سۄن', // less reliable
    'h' => ':count سۄن', // less reliable
    'a_hour' => ':count سۄن', // less reliable

    'minute' => ':count فَن', // less reliable
    'min' => ':count فَن', // less reliable
    'a_minute' => ':count فَن', // less reliable

    'second' => ':count दोʼयुम', // less reliable
    's' => ':count दोʼयुम', // less reliable
    'a_second' => ':count दोʼयुम', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Roy
 * - Stephan
 * - François B
 * - Tim Fish
 * - Kevin Huang
 * - Jacob Middag
 * - JD Isaacks
 * - Propaganistas
 */
return array_replace_recursive(require __DIR__.'/nl.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Authors:
 * - Josh Soref
 * - Nusret Parlak
 * - JD Isaacks
 * - Atef Ben Ali (atefBB)
 * - Mohamed Sabil (mohamedsabil83)
 * - Abdullah-Alhariri
 */
$months = [
    'يناير',
    'فبراير',
    'مارس',
    'أبريل',
    'ماي',
    'يونيو',
    'يوليوز',
    'غشت',
    'شتنبر',
    'أكتوبر',
    'نونبر',
    'دجنبر',
];

return [
    'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => 'في :time',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم على الساعة] LT',
        'nextDay' => '[غدا على الساعة] LT',
        'nextWeek' => 'dddd [على الساعة] LT',
        'lastDay' => '[أمس على الساعة] LT',
        'lastWeek' => 'dddd [على الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['maná', 'kugú'],
    'weekdays' => ['sɔ́ndɔ', 'mɔ́ndɔ', 'sɔ́ndɔ mafú mába', 'sɔ́ndɔ mafú málal', 'sɔ́ndɔ mafú mána', 'mabágá má sukul', 'sásadi'],
    'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
    'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'mbs', 'sas'],
    'months' => ['ngwɛn matáhra', 'ngwɛn ńmba', 'ngwɛn ńlal', 'ngwɛn ńna', 'ngwɛn ńtan', 'ngwɛn ńtuó', 'ngwɛn hɛmbuɛrí', 'ngwɛn lɔmbi', 'ngwɛn rɛbvuâ', 'ngwɛn wum', 'ngwɛn wum navǔr', 'krísimin'],
    'months_short' => ['ng1', 'ng2', 'ng3', 'ng4', 'ng5', 'ng6', 'ng7', 'ng8', 'ng9', 'ng10', 'ng11', 'kris'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['krn', 'koosk'],
    'weekdays' => ['Kotisap', 'Kotaai', 'Koaeng’', 'Kosomok', 'Koang’wan', 'Komuut', 'Kolo'],
    'weekdays_short' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'],
    'weekdays_min' => ['Kts', 'Kot', 'Koo', 'Kos', 'Koa', 'Kom', 'Kol'],
    'months' => ['Mulgul', 'Ng’atyaato', 'Kiptaamo', 'Iwootkuut', 'Mamuut', 'Paagi', 'Ng’eiyeet', 'Rooptui', 'Bureet', 'Epeeso', 'Kipsuunde ne taai', 'Kipsuunde nebo aeng’'],
    'months_short' => ['Mul', 'Ngat', 'Taa', 'Iwo', 'Mam', 'Paa', 'Nge', 'Roo', 'Bur', 'Epe', 'Kpt', 'Kpa'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'year' => ':count maghatiat', // less reliable
    'y' => ':count maghatiat', // less reliable
    'a_year' => ':count maghatiat', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Valery Timiriliyev Valery Timiriliyev timiriliyev@gmail.com
 */
return array_replace_recursive(require __DIR__.'/ru.php', [
    'formats' => [
        'L' => 'YYYY.MM.DD',
    ],
    'months' => ['тохсунньу', 'олунньу', 'кулун тутар', 'муус устар', 'ыам ыйын', 'бэс ыйын', 'от ыйын', 'атырдьах ыйын', 'балаҕан ыйын', 'алтынньы', 'сэтинньи', 'ахсынньы'],
    'months_short' => ['тохс', 'олун', 'кул', 'муус', 'ыам', 'бэс', 'от', 'атыр', 'бал', 'алт', 'сэт', 'ахс'],
    'weekdays' => ['баскыһыанньа', 'бэнидиэнньик', 'оптуорунньук', 'сэрэдэ', 'чэппиэр', 'бээтинсэ', 'субуота'],
    'weekdays_short' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'],
    'weekdays_min' => ['бс', 'бн', 'оп', 'ср', 'чп', 'бт', 'сб'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/br.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['I bikɛ̂glà', 'I ɓugajɔp'],
    'weekdays' => ['ŋgwà nɔ̂y', 'ŋgwà njaŋgumba', 'ŋgwà ûm', 'ŋgwà ŋgê', 'ŋgwà mbɔk', 'ŋgwà kɔɔ', 'ŋgwà jôn'],
    'weekdays_short' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
    'weekdays_min' => ['nɔy', 'nja', 'uum', 'ŋge', 'mbɔ', 'kɔɔ', 'jon'],
    'months' => ['Kɔndɔŋ', 'Màcɛ̂l', 'Màtùmb', 'Màtop', 'M̀puyɛ', 'Hìlòndɛ̀', 'Njèbà', 'Hìkaŋ', 'Dìpɔ̀s', 'Bìòôm', 'Màyɛsèp', 'Lìbuy li ńyèe'],
    'months_short' => ['kɔn', 'mac', 'mat', 'mto', 'mpu', 'hil', 'nje', 'hik', 'dip', 'bio', 'may', 'liɓ'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'second' => ':count móndî', // less reliable
    's' => ':count móndî', // less reliable
    'a_second' => ':count móndî', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['pamilau', 'pamunyi'],
    'weekdays' => ['pa mulungu', 'pa shahuviluha', 'pa hivili', 'pa hidatu', 'pa hitayi', 'pa hihanu', 'pa shahulembela'],
    'weekdays_short' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
    'weekdays_min' => ['Mul', 'Vil', 'Hiv', 'Hid', 'Hit', 'Hih', 'Lem'],
    'months' => ['pa mwedzi gwa hutala', 'pa mwedzi gwa wuvili', 'pa mwedzi gwa wudatu', 'pa mwedzi gwa wutai', 'pa mwedzi gwa wuhanu', 'pa mwedzi gwa sita', 'pa mwedzi gwa saba', 'pa mwedzi gwa nane', 'pa mwedzi gwa tisa', 'pa mwedzi gwa kumi', 'pa mwedzi gwa kumi na moja', 'pa mwedzi gwa kumi na mbili'],
    'months_short' => ['Hut', 'Vil', 'Dat', 'Tai', 'Han', 'Sit', 'Sab', 'Nan', 'Tis', 'Kum', 'Kmj', 'Kmb'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Samsung Electronics Co., Ltd.    alexey.merzlyakov@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    'weekdays' => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    'weekdays_short' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    'weekdays_min' => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Abdellah Chadidi
 * - Atef Ben Ali (atefBB)
 * - Mohamed Sabil (mohamedsabil83)
 */
// Same for long and short
$months = [
    // @TODO add shakl to months
    'يناير',
    'فبراير',
    'مارس',
    'أبريل',
    'مايو',
    'يونيو',
    'يوليو',
    'أغسطس',
    'سبتمبر',
    'أكتوبر',
    'نوفمبر',
    'ديسمبر',
];

return [
    'year' => implode('|', ['{0}:count سَنَة', '{1}سَنَة', '{2}سَنَتَيْن', ']2,11[:count سَنَوَات', ']10,Inf[:count سَنَة']),
    'a_year' => implode('|', ['{0}:count سَنَة', '{1}سَنَة', '{2}سَنَتَيْن', ']2,11[:count سَنَوَات', ']10,Inf[:count سَنَة']),
    'month' => implode('|', ['{0}:count شَهْرَ', '{1}شَهْرَ', '{2}شَهْرَيْن', ']2,11[:count أَشْهُر', ']10,Inf[:count شَهْرَ']),
    'a_month' => implode('|', ['{0}:count شَهْرَ', '{1}شَهْرَ', '{2}شَهْرَيْن', ']2,11[:count أَشْهُر', ']10,Inf[:count شَهْرَ']),
    'week' => implode('|', ['{0}:count أُسْبُوع', '{1}أُسْبُوع', '{2}أُسْبُوعَيْن', ']2,11[:count أَسَابِيع', ']10,Inf[:count أُسْبُوع']),
    'a_week' => implode('|', ['{0}:count أُسْبُوع', '{1}أُسْبُوع', '{2}أُسْبُوعَيْن', ']2,11[:count أَسَابِيع', ']10,Inf[:count أُسْبُوع']),
    'day' => implode('|', ['{0}:count يَوْم', '{1}يَوْم', '{2}يَوْمَيْن', ']2,11[:count أَيَّام', ']10,Inf[:count يَوْم']),
    'a_day' => implode('|', ['{0}:count يَوْم', '{1}يَوْم', '{2}يَوْمَيْن', ']2,11[:count أَيَّام', ']10,Inf[:count يَوْم']),
    'hour' => implode('|', ['{0}:count سَاعَة', '{1}سَاعَة', '{2}سَاعَتَيْن', ']2,11[:count سَاعَات', ']10,Inf[:count سَاعَة']),
    'a_hour' => implode('|', ['{0}:count سَاعَة', '{1}سَاعَة', '{2}سَاعَتَيْن', ']2,11[:count سَاعَات', ']10,Inf[:count سَاعَة']),
    'minute' => implode('|', ['{0}:count دَقِيقَة', '{1}دَقِيقَة', '{2}دَقِيقَتَيْن', ']2,11[:count دَقَائِق', ']10,Inf[:count دَقِيقَة']),
    'a_minute' => implode('|', ['{0}:count دَقِيقَة', '{1}دَقِيقَة', '{2}دَقِيقَتَيْن', ']2,11[:count دَقَائِق', ']10,Inf[:count دَقِيقَة']),
    'second' => implode('|', ['{0}:count ثَانِيَة', '{1}ثَانِيَة', '{2}ثَانِيَتَيْن', ']2,11[:count ثَوَان', ']10,Inf[:count ثَانِيَة']),
    'a_second' => implode('|', ['{0}:count ثَانِيَة', '{1}ثَانِيَة', '{2}ثَانِيَتَيْن', ']2,11[:count ثَوَان', ']10,Inf[:count ثَانِيَة']),
    'ago' => 'مُنْذُ :time',
    'from_now' => 'مِنَ الْآن :time',
    'after' => 'بَعْدَ :time',
    'before' => 'قَبْلَ :time',

    // @TODO add shakl to translations below
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم عند الساعة] LT',
        'nextDay' => '[غدًا عند الساعة] LT',
        'nextWeek' => 'dddd [عند الساعة] LT',
        'lastDay' => '[أمس عند الساعة] LT',
        'lastWeek' => 'dddd [عند الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/gu.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - Azri Jamil
 * - JD Isaacks
 */
return require __DIR__.'/ms.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/tr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/af.php', [
    'meridiem' => ['v', 'n'],
    'weekdays' => ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
    'weekdays_short' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'],
    'weekdays_min' => ['So.', 'Ma.', 'Di.', 'Wo.', 'Do.', 'Vr.', 'Sa.'],
    'months' => ['Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember'],
    'months_short' => ['Jan.', 'Feb.', 'Mrt.', 'Apr.', 'Mei', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Des.'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'DD MMM YYYY',
        'LLL' => 'DD MMMM YYYY HH:mm',
        'LLLL' => 'dddd, DD MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Janabari', 'uFeberbari', 'uMatjhi', 'u-Apreli', 'Meyi', 'Juni', 'Julayi', 'Arhostosi', 'Septemba', 'Oktoba', 'Usinyikhaba', 'Disemba'],
    'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mey', 'Jun', 'Jul', 'Arh', 'Sep', 'Okt', 'Usi', 'Dis'],
    'weekdays' => ['uSonto', 'uMvulo', 'uLesibili', 'lesithathu', 'uLesine', 'ngoLesihlanu', 'umGqibelo'],
    'weekdays_short' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
    'weekdays_min' => ['Son', 'Mvu', 'Bil', 'Tha', 'Ne', 'Hla', 'Gqi'],
    'day_of_first_week_of_year' => 1,
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'months' => ['sánzá ya yambo', 'sánzá ya míbalé', 'sánzá ya mísáto', 'sánzá ya mínei', 'sánzá ya mítáno', 'sánzá ya motóbá', 'sánzá ya nsambo', 'sánzá ya mwambe', 'sánzá ya libwa', 'sánzá ya zómi', 'sánzá ya zómi na mɔ̌kɔ́', 'sánzá ya zómi na míbalé'],
    'months_short' => ['yan', 'fbl', 'msi', 'apl', 'mai', 'yun', 'yul', 'agt', 'stb', 'ɔtb', 'nvb', 'dsb'],
    'weekdays' => ['Lomíngo', 'Mosálá mɔ̌kɔ́', 'Misálá míbalé', 'Misálá mísáto', 'Misálá mínei', 'Misálá mítáno', 'Mpɔ́sɔ'],
    'weekdays_short' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'],
    'weekdays_min' => ['m1.', 'm2.', 'm3.', 'm4.', 'm5.', 'm6.', 'm7.'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => 'mbula :count',
    'y' => 'mbula :count',
    'a_year' => 'mbula :count',

    'month' => 'sánzá :count',
    'm' => 'sánzá :count',
    'a_month' => 'sánzá :count',

    'week' => 'mpɔ́sɔ :count',
    'w' => 'mpɔ́sɔ :count',
    'a_week' => 'mpɔ́sɔ :count',

    'day' => 'mokɔlɔ :count',
    'd' => 'mokɔlɔ :count',
    'a_day' => 'mokɔlɔ :count',

    'hour' => 'ngonga :count',
    'h' => 'ngonga :count',
    'a_hour' => 'ngonga :count',

    'minute' => 'miniti :count',
    'min' => 'miniti :count',
    'a_minute' => 'miniti :count',

    'second' => 'segɔnde :count',
    's' => 'segɔnde :count',
    'a_second' => 'segɔnde :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sv.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - shaishavgandhi05
 * - Serhan Apaydın
 * - JD Isaacks
 * - Glavić
 * - Milos Sakovic
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count godina|:count godine|:count godina',
    'y' => ':count g.',
    'month' => ':count mesec|:count meseca|:count meseci',
    'm' => ':count mes.',
    'week' => ':count nedelja|:count nedelje|:count nedelja',
    'w' => ':count ned.',
    'day' => ':count dan|:count dana|:count dana',
    'd' => ':count d.',
    'hour' => ':count sat|:count sata|:count sati',
    'h' => ':count č.',
    'minute' => ':count minut|:count minuta|:count minuta',
    'min' => ':count min.',
    'second' => ':count sekundu|:count sekunde|:count sekundi',
    's' => ':count sek.',

    'ago' => 'pre :time',
    'from_now' => 'za :time',
    'after' => 'nakon :time',
    'before' => 'pre :time',

    'year_ago' => ':count godinu|:count godine|:count godina',
    'year_from_now' => ':count godinu|:count godine|:count godina',
    'week_ago' => ':count nedelju|:count nedelje|:count nedelja',
    'week_from_now' => ':count nedelju|:count nedelje|:count nedelja',

    'diff_now' => 'upravo sada',
    'diff_today' => 'danas',
    'diff_today_regexp' => 'danas(?:\\s+u)?',
    'diff_yesterday' => 'juče',
    'diff_yesterday_regexp' => 'juče(?:\\s+u)?',
    'diff_tomorrow' => 'sutra',
    'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?',
    'diff_before_yesterday' => 'prekjuče',
    'diff_after_tomorrow' => 'preksutra',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY H:mm',
        'LLLL' => 'dddd, D. MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[danas u] LT',
        'nextDay' => '[sutra u] LT',
        'nextWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[u nedelju u] LT',
            3 => '[u sredu u] LT',
            6 => '[u subotu u] LT',
            default => '[u] dddd [u] LT',
        },
        'lastDay' => '[juče u] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[prošle nedelje u] LT',
            1 => '[prošlog ponedeljka u] LT',
            2 => '[prošlog utorka u] LT',
            3 => '[prošle srede u] LT',
            4 => '[prošlog četvrtka u] LT',
            5 => '[prošlog petka u] LT',
            default => '[prošle subote u] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'],
    'months_short' => ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'],
    'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
    'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'],
    'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' i '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/qu.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - BAKTETE Miloud
 */
return [
    'year' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
    'a_year' => 'ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
    'y' => ':count ⵓⵙⴳⴳⵯⴰⵙ|:count ⵉⵙⴳⴳⵓⵙⴰ',
    'month' => ':count ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ',
    'a_month' => 'ⵉⴷⵊ ⵡⴰⵢⵢⵓⵔ|:count ⴰⵢⵢⵓⵔⵏ',
    'm' => ':count ⴰⵢⵢⵓⵔⵏ',
    'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ',
    'a_week' => 'ⵉⵛⵜ ⵉⵎⴰⵍⴰⵙⵙ|:count ⵉⵎⴰⵍⴰⵙⵙⵏ',
    'w' => ':count ⵉⵎⴰⵍⴰⵙⵙ.',
    'day' => ':count ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ',
    'a_day' => 'ⵉⴷⵊ ⵡⴰⵙⵙ|:count ⵓⵙⵙⴰⵏ',
    'd' => ':count ⵓ',
    'hour' => ':count ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ',
    'a_hour' => 'ⵉⵛⵜ ⵜⵙⵔⴰⴳⵜ|:count ⵜⵉⵙⵔⴰⴳⵉⵏ',
    'h' => ':count ⵜ',
    'minute' => ':count ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ',
    'a_minute' => 'ⵉⵛⵜ ⵜⵓⵙⴷⵉⴷⵜ|:count ⵜⵓⵙⴷⵉⴷⵉⵏ',
    'min' => ':count ⵜⵓⵙ',
    'second' => ':count ⵜⵙⵉⵏⵜ|:count ⵜⵉⵙⵉⵏⴰ',
    'a_second' => 'ⴽⵔⴰ ⵜⵉⵙⵉⵏⴰ|:count ⵜⵉⵙⵉⵏⴰ',
    's' => ':count ⵜ',
    'ago' => 'ⵣⴳ :time',
    'from_now' => 'ⴷⴳ :time',
    'after' => ':time ⴰⵡⴰⵔ',
    'before' => ':time ⴷⴰⵜ',
    'diff_now' => 'ⴰⴷⵡⴰⵍⵉ',
    'diff_today' => 'ⴰⵙⵙ',
    'diff_today_regexp' => 'ⴰⵙⵙ(?:\\s+ⴰ/ⴰⴷ)?(?:\\s+ⴳ)?',
    'diff_yesterday' => 'ⴰⵙⵙⵏⵏⴰⵟ',
    'diff_yesterday_regexp' => 'ⴰⵙⵙⵏⵏⴰⵟ(?:\\s+ⴳ)?',
    'diff_tomorrow' => 'ⴰⵙⴽⴽⴰ',
    'diff_tomorrow_regexp' => 'ⴰⵙⴽⴽⴰ(?:\\s+ⴳ)?',
    'diff_before_yesterday' => 'ⴼⵔ ⵉⴹⵏⵏⴰⵟ',
    'diff_after_tomorrow' => 'ⵏⴰⴼ ⵓⵙⴽⴽⴰ',
    'period_recurrences' => ':count ⵜⵉⴽⴽⴰⵍ',
    'period_interval' => 'ⴽⵓ :interval',
    'period_start_date' => 'ⴳ :date',
    'period_end_date' => 'ⵉ :date',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[ⴰⵙⵙ ⴰ/ⴰⴷ ⴳ] LT',
        'nextDay' => '[ⴰⵙⴽⴽⴰ ⴳ] LT',
        'nextWeek' => 'dddd [ⴳ] LT',
        'lastDay' => '[ⴰⵙⵙⵏⵏⴰⵟ ⴳ] LT',
        'lastWeek' => 'dddd [ⴰⵎⴳⴳⴰⵔⵓ ⴳ] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ⵜⵉⴼⴰⵡⵜ', 'ⵜⴰⴷⴳⴳⵯⴰⵜ'],
    'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⴰⵏⴱⵉⵔ'],
    'months_short' => ['ⵉⵏⵏ', 'ⴱⵕⴰ', 'ⵎⴰⵕ', 'ⵉⴱⵔ', 'ⵎⴰⵢ', 'ⵢⵓⵏ', 'ⵢⵓⵍ', 'ⵖⵓⵛ', 'ⵛⵓⵜ', 'ⴽⵟⵓ', 'ⵏⵓⵡ', 'ⴷⵓⵊ'],
    'weekdays' => ['ⵓⵙⴰⵎⴰⵙ', 'ⵡⴰⵢⵏⴰⵙ', 'ⵓⵙⵉⵏⴰⵙ', 'ⵡⴰⴽⵕⴰⵙ', 'ⵓⴽⵡⴰⵙ', 'ⵓⵙⵉⵎⵡⴰⵙ', 'ⵓⵙⵉⴹⵢⴰⵙ'],
    'weekdays_short' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'],
    'weekdays_min' => ['ⵓⵙⴰ', 'ⵡⴰⵢ', 'ⵓⵙⵉ', 'ⵡⴰⴽ', 'ⵓⴽⵡ', 'ⵓⵙⵉⵎ', 'ⵓⵙⵉⴹ'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' ⴷ '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - runasimipi.org    libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['inïru', 'phiwriru', 'marsu', 'awrila', 'mayu', 'junyu', 'julyu', 'awustu', 'sitimri', 'uktuwri', 'nuwimri', 'risimri'],
    'months_short' => ['ini', 'phi', 'mar', 'awr', 'may', 'jun', 'jul', 'awu', 'sit', 'ukt', 'nuw', 'ris'],
    'weekdays' => ['tuminku', 'lunisa', 'martisa', 'mirkulisa', 'juywisa', 'wirnisa', 'sawäru'],
    'weekdays_short' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'],
    'weekdays_min' => ['tum', 'lun', 'mar', 'mir', 'juy', 'wir', 'saw'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['VM', 'NM'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fo.php', [
    'formats' => [
        'L' => 'DD.MM.yy',
        'LL' => 'DD.MM.YYYY',
        'LLL' => 'D. MMMM YYYY, HH:mm',
        'LLLL' => 'dddd, D. MMMM YYYY, HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 * - Atef Ben Ali (atefBB)
 * - Mohamed Sabil (mohamedsabil83)
 * - Abdullah-Alhariri
 */
$months = [
    'يناير',
    'فبراير',
    'مارس',
    'أبريل',
    'مايو',
    'يونيو',
    'يوليو',
    'أغسطس',
    'سبتمبر',
    'أكتوبر',
    'نوفمبر',
    'ديسمبر',
];

return [
    'year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'a_year' => implode('|', ['{0}:count سنة', '{1}سنة', '{2}سنتين', ']2,11[:count سنوات', ']10,Inf[:count سنة']),
    'month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'a_month' => implode('|', ['{0}:count شهر', '{1}شهر', '{2}شهرين', ']2,11[:count أشهر', ']10,Inf[:count شهر']),
    'week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'a_week' => implode('|', ['{0}:count أسبوع', '{1}أسبوع', '{2}أسبوعين', ']2,11[:count أسابيع', ']10,Inf[:count أسبوع']),
    'day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'a_day' => implode('|', ['{0}:count يوم', '{1}يوم', '{2}يومين', ']2,11[:count أيام', ']10,Inf[:count يوم']),
    'hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'a_hour' => implode('|', ['{0}:count ساعة', '{1}ساعة', '{2}ساعتين', ']2,11[:count ساعات', ']10,Inf[:count ساعة']),
    'minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'a_minute' => implode('|', ['{0}:count دقيقة', '{1}دقيقة', '{2}دقيقتين', ']2,11[:count دقائق', ']10,Inf[:count دقيقة']),
    'second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'a_second' => implode('|', ['{0}:count ثانية', '{1}ثانية', '{2}ثانيتين', ']2,11[:count ثواني', ']10,Inf[:count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => 'في :time',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدا(?:\\s+على)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['{0}مرة', '{1}مرة', '{2}:count مرتين', ']2,11[:count مرات', ']10,Inf[:count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم على الساعة] LT',
        'nextDay' => '[غدا على الساعة] LT',
        'nextWeek' => 'dddd [على الساعة] LT',
        'lastDay' => '[أمس على الساعة] LT',
        'lastWeek' => 'dddd [على الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/gl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Swara Mohammed
 * - Kawan Pshtiwan
 */
$months = [
    'کانونی دووەم',
    'شوبات',
    'ئازار',
    'نیسان',
    'ئایار',
    'حوزەیران',
    'تەمموز',
    'ئاب',
    'ئەیلوول',
    'تشرینی یەکەم',
    'تشرینی دووەم',
    'کانونی یەکەم',
];

return [
    'year' => implode('|', ['{0}:count ساڵێک', '{1}ساڵێک', '{2}دوو ساڵ', ']2,11[:count ساڵ', ']10,Inf[:count ساڵ']),
    'a_year' => implode('|', ['{0}:count ساڵێک', '{1}ساڵێک', '{2}دوو ساڵ', ']2,11[:count ساڵ', ']10,Inf[:count ساڵ']),
    'month' => implode('|', ['{0}:count مانگێک', '{1}مانگێک', '{2}دوو مانگ', ']2,11[:count مانگ', ']10,Inf[:count مانگ']),
    'a_month' => implode('|', ['{0}:count مانگێک', '{1}مانگێک', '{2}دوو مانگ', ']2,11[:count مانگ', ']10,Inf[:count مانگ']),
    'week' => implode('|', ['{0}:count هەفتەیەک', '{1}هەفتەیەک', '{2}دوو هەفتە', ']2,11[:count هەفتە', ']10,Inf[:count هەفتە']),
    'a_week' => implode('|', ['{0}:count هەفتەیەک', '{1}هەفتەیەک', '{2}دوو هەفتە', ']2,11[:count هەفتە', ']10,Inf[:count هەفتە']),
    'day' => implode('|', ['{0}:count ڕۆژێک', '{1}ڕۆژێک', '{2}دوو ڕۆژ', ']2,11[:count ڕۆژ', ']10,Inf[:count ڕۆژ']),
    'a_day' => implode('|', ['{0}:count ڕۆژێک', '{1}ڕۆژێک', '{2}دوو ڕۆژ', ']2,11[:count ڕۆژ', ']10,Inf[:count ڕۆژ']),
    'hour' => implode('|', ['{0}:count کاتژمێرێک', '{1}کاتژمێرێک', '{2}دوو کاتژمێر', ']2,11[:count کاتژمێر', ']10,Inf[:count کاتژمێر']),
    'a_hour' => implode('|', ['{0}:count کاتژمێرێک', '{1}کاتژمێرێک', '{2}دوو کاتژمێر', ']2,11[:count کاتژمێر', ']10,Inf[:count کاتژمێر']),
    'minute' => implode('|', ['{0}:count خولەکێک', '{1}خولەکێک', '{2}دوو خولەک', ']2,11[:count خولەک', ']10,Inf[:count خولەک']),
    'a_minute' => implode('|', ['{0}:count خولەکێک', '{1}خولەکێک', '{2}دوو خولەک', ']2,11[:count خولەک', ']10,Inf[:count خولەک']),
    'second' => implode('|', ['{0}:count چرکەیەک', '{1}چرکەیەک', '{2}دوو چرکە', ']2,11[:count چرکە', ']10,Inf[:count چرکە']),
    'a_second' => implode('|', ['{0}:count چرکەیەک', '{1}چرکەیەک', '{2}دوو چرکە', ']2,11[:count چرکە', ']10,Inf[:count چرکە']),
    'ago' => 'پێش :time',
    'from_now' => ':time لە ئێستاوە',
    'after' => 'دوای :time',
    'before' => 'پێش :time',
    'diff_now' => 'ئێستا',
    'diff_today' => 'ئەمڕۆ',
    'diff_today_regexp' => 'ڕۆژ(?:\\s+لە)?(?:\\s+کاتژمێر)?',
    'diff_yesterday' => 'دوێنێ',
    'diff_yesterday_regexp' => 'دوێنێ(?:\\s+لە)?(?:\\s+کاتژمێر)?',
    'diff_tomorrow' => 'سبەینێ',
    'diff_tomorrow_regexp' => 'سبەینێ(?:\\s+لە)?(?:\\s+کاتژمێر)?',
    'diff_before_yesterday' => 'پێش دوێنێ',
    'diff_after_tomorrow' => 'دوای سبەینێ',
    'period_recurrences' => implode('|', ['{0}جار', '{1}جار', '{2}:count دووجار', ']2,11[:count جار', ']10,Inf[:count جار']),
    'period_interval' => 'هەموو :interval',
    'period_start_date' => 'لە :date',
    'period_end_date' => 'بۆ :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['یەکشەممە', 'دووشەممە', 'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'هەینی', 'شەممە'],
    'weekdays_short' => ['یەکشەممە', 'دووشەممە', 'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'هەینی', 'شەممە'],
    'weekdays_min' => ['یەکشەممە', 'دووشەممە', 'سێشەممە', 'چوارشەممە', 'پێنجشەممە', 'هەینی', 'شەممە'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[ئەمڕۆ لە کاتژمێر] LT',
        'nextDay' => '[سبەینێ لە کاتژمێر] LT',
        'nextWeek' => 'dddd [لە کاتژمێر] LT',
        'lastDay' => '[دوێنێ لە کاتژمێر] LT',
        'lastWeek' => 'dddd [لە کاتژمێر] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['پ.ن', 'د.ن'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Reshat Sabiq tatar.iqtelif.i18n@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Ğınwar', 'Fiwral\'', 'Mart', 'April', 'May', 'Yün', 'Yül', 'Awgust', 'Sintebír', 'Üktebír', 'Noyebír', 'Dikebír'],
    'months_short' => ['Ğın', 'Fiw', 'Mar', 'Apr', 'May', 'Yün', 'Yül', 'Awg', 'Sin', 'Ükt', 'Noy', 'Dik'],
    'weekdays' => ['Yekşembí', 'Düşembí', 'Sişembí', 'Çerşembí', 'Pencíşembí', 'Comğa', 'Şimbe'],
    'weekdays_short' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'],
    'weekdays_min' => ['Yek', 'Düş', 'Siş', 'Çer', 'Pen', 'Com', 'Şim'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ÖA', 'ÖS'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['comme', 'lilli'],
    'weekdays' => ['Com’yakke', 'Comlaaɗii', 'Comzyiiɗii', 'Comkolle', 'Comkaldǝɓlii', 'Comgaisuu', 'Comzyeɓsuu'],
    'weekdays_short' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
    'weekdays_min' => ['Cya', 'Cla', 'Czi', 'Cko', 'Cka', 'Cga', 'Cze'],
    'months' => ['Fĩi Loo', 'Cokcwaklaŋne', 'Cokcwaklii', 'Fĩi Marfoo', 'Madǝǝuutǝbijaŋ', 'Mamǝŋgwãafahbii', 'Mamǝŋgwãalii', 'Madǝmbii', 'Fĩi Dǝɓlii', 'Fĩi Mundaŋ', 'Fĩi Gwahlle', 'Fĩi Yuru'],
    'months_short' => ['FLO', 'CLA', 'CKI', 'FMF', 'MAD', 'MBI', 'MLI', 'MAM', 'FDE', 'FMU', 'FGW', 'FYU'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 * - Nay Lin Aung
 */
return [
    'year' => ':count နှစ်',
    'a_year' => '{1}တစ်နှစ်|[-Inf,Inf]:count နှစ်',
    'y' => ':count နှစ်',
    'month' => ':count လ',
    'a_month' => '{1}တစ်လ|[-Inf,Inf]:count လ',
    'm' => ':count လ',
    'week' => ':count ပတ်',
    'w' => ':count ပတ်',
    'day' => ':count ရက်',
    'a_day' => '{1}တစ်ရက်|[-Inf,Inf]:count ရက်',
    'd' => ':count ရက်',
    'hour' => ':count နာရီ',
    'a_hour' => '{1}တစ်နာရီ|[-Inf,Inf]:count နာရီ',
    'h' => ':count နာရီ',
    'minute' => ':count မိနစ်',
    'a_minute' => '{1}တစ်မိနစ်|[-Inf,Inf]:count မိနစ်',
    'min' => ':count မိနစ်',
    'second' => ':count စက္ကန့်',
    'a_second' => '{0,1}စက္ကန်.အနည်းငယ်|[-Inf,Inf]:count စက္ကန့်',
    's' => ':count စက္ကန့်',
    'ago' => 'လွန်ခဲ့သော :time က',
    'from_now' => 'လာမည့် :time မှာ',
    'after' => ':time ကြာပြီးနောက်',
    'before' => ':time မတိုင်ခင်',
    'diff_now' => 'အခုလေးတင်',
    'diff_today' => 'ယနေ.',
    'diff_yesterday' => 'မနေ့က',
    'diff_yesterday_regexp' => 'မနေ.က',
    'diff_tomorrow' => 'မနက်ဖြန်',
    'diff_before_yesterday' => 'တမြန်နေ့က',
    'diff_after_tomorrow' => 'တဘက်ခါ',
    'period_recurrences' => ':count ကြိမ်',
    'formats' => [
        'LT' => 'Oh:Om A',
        'LTS' => 'Oh:Om:Os A',
        'L' => 'OD/OM/OY',
        'LL' => 'OD MMMM OY',
        'LLL' => 'OD MMMM OY Oh:Om A',
        'LLLL' => 'dddd OD MMMM OY Oh:Om A',
    ],
    'calendar' => [
        'sameDay' => '[ယနေ.] LT [မှာ]',
        'nextDay' => '[မနက်ဖြန်] LT [မှာ]',
        'nextWeek' => 'dddd LT [မှာ]',
        'lastDay' => '[မနေ.က] LT [မှာ]',
        'lastWeek' => '[ပြီးခဲ့သော] dddd LT [မှာ]',
        'sameElse' => 'L',
    ],
    'months' => ['ဇန်နဝါရီ', 'ဖေဖော်ဝါရီ', 'မတ်', 'ဧပြီ', 'မေ', 'ဇွန်', 'ဇူလိုင်', 'သြဂုတ်', 'စက်တင်ဘာ', 'အောက်တိုဘာ', 'နိုဝင်ဘာ', 'ဒီဇင်ဘာ'],
    'months_short' => ['ဇန်', 'ဖေ', 'မတ်', 'ပြီ', 'မေ', 'ဇွန်', 'လိုင်', 'သြ', 'စက်', 'အောက်', 'နို', 'ဒီ'],
    'weekdays' => ['တနင်္ဂနွေ', 'တနင်္လာ', 'အင်္ဂါ', 'ဗုဒ္ဓဟူး', 'ကြာသပတေး', 'သောကြာ', 'စနေ'],
    'weekdays_short' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'],
    'weekdays_min' => ['နွေ', 'လာ', 'ဂါ', 'ဟူး', 'ကြာ', 'သော', 'နေ'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'alt_numbers' => ['၀၀', '၀၁', '၀၂', '၀၃', '၀၄', '၀၅', '၀၆', '၀၇', '၀၈', '၀၉', '၁၀', '၁၁', '၁၂', '၁၃', '၁၄', '၁၅', '၁၆', '၁၇', '၁၈', '၁၉', '၂၀', '၂၁', '၂၂', '၂၃', '၂၄', '၂၅', '၂၆', '၂၇', '၂၈', '၂၉', '၃၀', '၃၁', '၃၂', '၃၃', '၃၄', '၃၅', '၃၆', '၃၇', '၃၈', '၃၉', '၄၀', '၄၁', '၄၂', '၄၃', '၄၄', '၄၅', '၄၆', '၄၇', '၄၈', '၄၉', '၅၀', '၅၁', '၅၂', '၅၃', '၅၄', '၅၅', '၅၆', '၅၇', '၅၈', '၅၉', '၆၀', '၆၁', '၆၂', '၆၃', '၆၄', '၆၅', '၆၆', '၆၇', '၆၈', '၆၉', '၇၀', '၇၁', '၇၂', '၇၃', '၇၄', '၇၅', '၇၆', '၇၇', '၇၈', '၇၉', '၈၀', '၈၁', '၈၂', '၈၃', '၈၄', '၈၅', '၈၆', '၈၇', '၈၈', '၈၉', '၉၀', '၉၁', '၉၂', '၉၃', '၉၄', '၉၅', '၉၆', '၉၇', '၉၈', '၉၉'],
    'meridiem' => ['နံနက်', 'ညနေ'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ha.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'],
    'months_short' => ['siakwa kati', 'kuswa kati', 'kakamuk kati', 'lî wainhka kati', 'lih mairin kati', 'lî kati', 'pastara kati', 'sikla kati', 'wîs kati', 'waupasa kati', 'yahbra kati', 'trisu kati'],
    'weekdays' => ['sandi', 'mundi', 'tiusdi', 'wensde', 'tausde', 'praidi', 'satadi'],
    'weekdays_short' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'],
    'weekdays_min' => ['san', 'mun', 'tius', 'wens', 'taus', 'prai', 'sat'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 7,
    'meridiem' => ['VM', 'NM'],

    'month' => ':count kati', // less reliable
    'm' => ':count kati', // less reliable
    'a_month' => ':count kati', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['Luma lwa K', 'luma lwa p'],
    'weekdays' => ['Ituku ja jumwa', 'Kuramuka jimweri', 'Kuramuka kawi', 'Kuramuka kadadu', 'Kuramuka kana', 'Kuramuka kasanu', 'Kifula nguwo'],
    'weekdays_short' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
    'weekdays_min' => ['Jum', 'Jim', 'Kaw', 'Kad', 'Kan', 'Kas', 'Ngu'],
    'months' => ['Mori ghwa imbiri', 'Mori ghwa kawi', 'Mori ghwa kadadu', 'Mori ghwa kana', 'Mori ghwa kasanu', 'Mori ghwa karandadu', 'Mori ghwa mfungade', 'Mori ghwa wunyanya', 'Mori ghwa ikenda', 'Mori ghwa ikumi', 'Mori ghwa ikumi na imweri', 'Mori ghwa ikumi na iwi'],
    'months_short' => ['Imb', 'Kaw', 'Kad', 'Kan', 'Kas', 'Kar', 'Mfu', 'Wun', 'Ike', 'Iku', 'Imw', 'Iwi'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - John Corrigan
 * - François B
 */
return [
    'year' => ':count tau',
    'a_year' => '{1}he tau|:count tau',
    'month' => ':count marama',
    'a_month' => '{1}he marama|:count marama',
    'week' => ':count wiki',
    'a_week' => '{1}he wiki|:count wiki',
    'day' => ':count ra',
    'a_day' => '{1}he ra|:count ra',
    'hour' => ':count haora',
    'a_hour' => '{1}te haora|:count haora',
    'minute' => ':count meneti',
    'a_minute' => '{1}he meneti|:count meneti',
    'second' => ':count hēkona',
    'a_second' => '{1}te hēkona ruarua|:count hēkona',
    'ago' => ':time i mua',
    'from_now' => 'i roto i :time',
    'diff_yesterday' => 'inanahi',
    'diff_yesterday_regexp' => 'inanahi(?:\\s+i)?',
    'diff_today' => 'i teie',
    'diff_today_regexp' => 'i teie(?:\\s+mahana,)?(?:\\s+i)?',
    'diff_tomorrow' => 'apopo',
    'diff_tomorrow_regexp' => 'apopo(?:\\s+i)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY [i] HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY [i] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[i teie mahana, i] LT',
        'nextDay' => '[apopo i] LT',
        'nextWeek' => 'dddd [i] LT',
        'lastDay' => '[inanahi i] LT',
        'lastWeek' => 'dddd [whakamutunga i] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberº',
    'months' => ['Kohi-tāte', 'Hui-tanguru', 'Poutū-te-rangi', 'Paenga-whāwhā', 'Haratua', 'Pipiri', 'Hōngoingoi', 'Here-turi-kōkā', 'Mahuru', 'Whiringa-ā-nuku', 'Whiringa-ā-rangi', 'Hakihea'],
    'months_short' => ['Kohi', 'Hui', 'Pou', 'Pae', 'Hara', 'Pipi', 'Hōngoi', 'Here', 'Mahu', 'Whi-nu', 'Whi-ra', 'Haki'],
    'weekdays' => ['Rātapu', 'Mane', 'Tūrei', 'Wenerei', 'Tāite', 'Paraire', 'Hātarei'],
    'weekdays_short' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'],
    'weekdays_min' => ['Ta', 'Ma', 'Tū', 'We', 'Tāi', 'Pa', 'Hā'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' me te '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'months' => ['Ianuali', 'Pepeluali', 'Malaki', 'ʻApelila', 'Mei', 'Iune', 'Iulai', 'ʻAukake', 'Kepakemapa', 'ʻOkakopa', 'Nowemapa', 'Kekemapa'],
    'months_short' => ['Ian.', 'Pep.', 'Mal.', 'ʻAp.', 'Mei', 'Iun.', 'Iul.', 'ʻAu.', 'Kep.', 'ʻOk.', 'Now.', 'Kek.'],
    'weekdays' => ['Lāpule', 'Poʻakahi', 'Poʻalua', 'Poʻakolu', 'Poʻahā', 'Poʻalima', 'Poʻaono'],
    'weekdays_short' => ['LP', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6'],
    'weekdays_min' => ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd, D MMMM YYYY h:mm a',
    ],

    'year' => ':count makahiki',
    'y' => ':count makahiki',
    'a_year' => ':count makahiki',

    'month' => ':count mahina',
    'm' => ':count mahina',
    'a_month' => ':count mahina',

    'week' => ':count pule',
    'w' => ':count pule',
    'a_week' => ':count pule',

    'day' => ':count lā',
    'd' => ':count lā',
    'a_day' => ':count lā',

    'hour' => ':count hola',
    'h' => ':count hola',
    'a_hour' => ':count hola',

    'minute' => ':count minuke',
    'min' => ':count minuke',
    'a_minute' => ':count minuke',

    'second' => ':count lua',
    's' => ':count lua',
    'a_second' => ':count lua',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['RW', 'TŊ'],
    'weekdays' => ['Cäŋ kuɔth', 'Jiec la̱t', 'Rɛw lätni', 'Diɔ̱k lätni', 'Ŋuaan lätni', 'Dhieec lätni', 'Bäkɛl lätni'],
    'weekdays_short' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'],
    'weekdays_min' => ['Cäŋ', 'Jiec', 'Rɛw', 'Diɔ̱k', 'Ŋuaan', 'Dhieec', 'Bäkɛl'],
    'months' => ['Tiop thar pɛt', 'Pɛt', 'Duɔ̱ɔ̱ŋ', 'Guak', 'Duät', 'Kornyoot', 'Pay yie̱tni', 'Tho̱o̱r', 'Tɛɛr', 'Laath', 'Kur', 'Tio̱p in di̱i̱t'],
    'months_short' => ['Tiop', 'Pɛt', 'Duɔ̱ɔ̱', 'Guak', 'Duä', 'Kor', 'Pay', 'Thoo', 'Tɛɛ', 'Laa', 'Kur', 'Tid'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],

    'year' => ':count jiök', // less reliable
    'y' => ':count jiök', // less reliable
    'a_year' => ':count jiök', // less reliable

    'month' => ':count pay', // less reliable
    'm' => ':count pay', // less reliable
    'a_month' => ':count pay', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - Kunal Marwaha
 * - François B
 * - JD Isaacks
 * - Orxan
 * - Şəhriyar İmanov
 * - Baran Şengül
 * - Novruz Rahimov
 */
return [
    'year' => ':count il',
    'a_year' => '{1}bir il|[-Inf,Inf]:count il',
    'y' => ':count il',
    'month' => ':count ay',
    'a_month' => '{1}bir ay|[-Inf,Inf]:count ay',
    'm' => ':count ay',
    'week' => ':count həftə',
    'a_week' => '{1}bir həftə|[-Inf,Inf]:count həftə',
    'w' => ':count h.',
    'day' => ':count gün',
    'a_day' => '{1}bir gün|[-Inf,Inf]:count gün',
    'd' => ':count g.',
    'hour' => ':count saat',
    'a_hour' => '{1}bir saat|[-Inf,Inf]:count saat',
    'h' => ':count s.',
    'minute' => ':count dəqiqə',
    'a_minute' => '{1}bir dəqiqə|[-Inf,Inf]:count dəqiqə',
    'min' => ':count d.',
    'second' => ':count saniyə',
    'a_second' => '{1}birneçə saniyə|[-Inf,Inf]:count saniyə',
    's' => ':count san.',
    'ago' => ':time əvvəl',
    'from_now' => ':time sonra',
    'after' => ':time sonra',
    'before' => ':time əvvəl',
    'diff_now' => 'indi',
    'diff_today' => 'bugün',
    'diff_today_regexp' => 'bugün(?:\\s+saat)?',
    'diff_yesterday' => 'dünən',
    'diff_tomorrow' => 'sabah',
    'diff_tomorrow_regexp' => 'sabah(?:\\s+saat)?',
    'diff_before_yesterday' => 'srağagün',
    'diff_after_tomorrow' => 'birisi gün',
    'period_recurrences' => ':count dəfədən bir',
    'period_interval' => 'hər :interval',
    'period_start_date' => ':date tarixindən başlayaraq',
    'period_end_date' => ':date tarixinədək',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[bugün saat] LT',
        'nextDay' => '[sabah saat] LT',
        'nextWeek' => '[gələn həftə] dddd [saat] LT',
        'lastDay' => '[dünən] LT',
        'lastWeek' => '[keçən həftə] dddd [saat] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        if ($number === 0) { // special case for zero
            return "$number-ıncı";
        }

        static $suffixes = [
            1 => '-inci',
            5 => '-inci',
            8 => '-inci',
            70 => '-inci',
            80 => '-inci',
            2 => '-nci',
            7 => '-nci',
            20 => '-nci',
            50 => '-nci',
            3 => '-üncü',
            4 => '-üncü',
            100 => '-üncü',
            6 => '-ncı',
            9 => '-uncu',
            10 => '-uncu',
            30 => '-uncu',
            60 => '-ıncı',
            90 => '-ıncı',
        ];

        $lastDigit = $number % 10;

        return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
    },
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'gecə';
        }
        if ($hour < 12) {
            return 'səhər';
        }
        if ($hour < 17) {
            return 'gündüz';
        }

        return 'axşam';
    },
    'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
    'months_short' => ['yan', 'fev', 'mar', 'apr', 'may', 'iyn', 'iyl', 'avq', 'sen', 'okt', 'noy', 'dek'],
    'weekdays' => ['bazar', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    'weekdays_short' => ['baz', 'bze', 'çax', 'çər', 'cax', 'cüm', 'şən'],
    'weekdays_min' => ['bz', 'be', 'ça', 'çə', 'ca', 'cü', 'şə'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' və '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fa.php', [
    'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    'weekdays_short' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
    'weekdays_min' => ['ی.', 'د.', 'س.', 'چ.', 'پ.', 'ج.', 'ش.'],
    'months' => ['جنوری', 'فبروری', 'مارچ', 'اپریل', 'می', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنو', 'فبر', 'مار', 'اپر', 'می', 'جون', 'جول', 'اگس', 'سپت', 'اکت', 'نوم', 'دسم'],
    'first_day_of_week' => 6,
    'weekend' => [4, 5],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'YYYY MMMM D, dddd HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/gsw.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['utuko', 'kyiukonyi'],
    'weekdays' => ['Jumapilyi', 'Jumatatuu', 'Jumanne', 'Jumatanu', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'weekdays_min' => ['Jpi', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprilyi', 'Mei', 'Junyi', 'Julyai', 'Agusti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['ǁgoagas', 'ǃuias'],
    'weekdays' => ['Sontaxtsees', 'Mantaxtsees', 'Denstaxtsees', 'Wunstaxtsees', 'Dondertaxtsees', 'Fraitaxtsees', 'Satertaxtsees'],
    'weekdays_short' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
    'weekdays_min' => ['Son', 'Ma', 'De', 'Wu', 'Do', 'Fr', 'Sat'],
    'months' => ['ǃKhanni', 'ǃKhanǀgôab', 'ǀKhuuǁkhâb', 'ǃHôaǂkhaib', 'ǃKhaitsâb', 'Gamaǀaeb', 'ǂKhoesaob', 'Aoǁkhuumûǁkhâb', 'Taraǀkhuumûǁkhâb', 'ǂNûǁnâiseb', 'ǀHooǂgaeb', 'Hôasoreǁkhâb'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd, D MMMM YYYY h:mm a',
    ],

    'year' => ':count kurigu',
    'y' => ':count kurigu',
    'a_year' => ':count kurigu',

    'month' => ':count ǁaub', // less reliable
    'm' => ':count ǁaub', // less reliable
    'a_month' => ':count ǁaub', // less reliable

    'week' => ':count hû', // less reliable
    'w' => ':count hû', // less reliable
    'a_week' => ':count hû', // less reliable

    'day' => ':count ǀhobas', // less reliable
    'd' => ':count ǀhobas', // less reliable
    'a_day' => ':count ǀhobas', // less reliable

    'hour' => ':count ǂgaes', // less reliable
    'h' => ':count ǂgaes', // less reliable
    'a_hour' => ':count ǂgaes', // less reliable

    'minute' => ':count minutga', // less reliable
    'min' => ':count minutga', // less reliable
    'a_minute' => ':count minutga', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - leyluj
 * - Josh Soref
 * - ryanhart2
 */
return [
    'year' => 'mwaka :count|miaka :count',
    'a_year' => 'mwaka mmoja|miaka :count',
    'y' => 'mwaka :count|miaka :count',
    'month' => 'mwezi :count|miezi :count',
    'a_month' => 'mwezi mmoja|miezi :count',
    'm' => 'mwezi :count|miezi :count',
    'week' => 'wiki :count',
    'a_week' => 'wiki mmoja|wiki :count',
    'w' => 'w. :count',
    'day' => 'siku :count',
    'a_day' => 'siku moja|masiku :count',
    'd' => 'si. :count',
    'hour' => 'saa :count|masaa :count',
    'a_hour' => 'saa limoja|masaa :count',
    'h' => 'saa :count|masaa :count',
    'minute' => 'dakika :count',
    'a_minute' => 'dakika moja|dakika :count',
    'min' => 'd. :count',
    'second' => 'sekunde :count',
    'a_second' => 'hivi punde|sekunde :count',
    's' => 'se. :count',
    'ago' => 'tokea :time',
    'from_now' => ':time baadaye',
    'after' => ':time baada',
    'before' => ':time kabla',
    'diff_now' => 'sasa hivi',
    'diff_today' => 'leo',
    'diff_today_regexp' => 'leo(?:\\s+saa)?',
    'diff_yesterday' => 'jana',
    'diff_tomorrow' => 'kesho',
    'diff_tomorrow_regexp' => 'kesho(?:\\s+saa)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[leo saa] LT',
        'nextDay' => '[kesho saa] LT',
        'nextWeek' => '[wiki ijayo] dddd [saat] LT',
        'lastDay' => '[jana] LT',
        'lastWeek' => '[wiki iliyopita] dddd [saat] LT',
        'sameElse' => 'L',
    ],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Jpl', 'Jtat', 'Jnne', 'Jtan', 'Alh', 'Ijm', 'Jmos'],
    'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' na '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/vai.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IndLinux.org, Samsung Electronics Co., Ltd.    alexey.merzlyakov@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['ಜನವರಿ', 'ಫೆಬ್ರುವರಿ', 'ಮಾರ್ಚ್', 'ಏಪ್ರಿಲ್‌‌', 'ಮೇ', 'ಜೂನ್', 'ಜುಲೈ', 'ಆಗಸ್ಟ್', 'ಸೆಪ್ಟೆಂಬರ್‌', 'ಅಕ್ಟೋಬರ್', 'ನವೆಂಬರ್', 'ಡಿಸೆಂಬರ್'],
    'months_short' => ['ಜ', 'ಫೆ', 'ಮಾ', 'ಏ', 'ಮೇ', 'ಜೂ', 'ಜು', 'ಆ', 'ಸೆ', 'ಅ', 'ನ', 'ಡಿ'],
    'weekdays' => ['ಐಥಾರ', 'ಸೋಮಾರ', 'ಅಂಗರೆ', 'ಬುಧಾರ', 'ಗುರುವಾರ', 'ಶುಕ್ರರ', 'ಶನಿವಾರ'],
    'weekdays_short' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
    'weekdays_min' => ['ಐ', 'ಸೋ', 'ಅಂ', 'ಬು', 'ಗು', 'ಶು', 'ಶ'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ಕಾಂಡೆ', 'ಬಯ್ಯ'],

    'year' => ':count ನೀರ್', // less reliable
    'y' => ':count ನೀರ್', // less reliable
    'a_year' => ':count ನೀರ್', // less reliable

    'month' => ':count ಮೀನ್', // less reliable
    'm' => ':count ಮೀನ್', // less reliable
    'a_month' => ':count ಮೀನ್', // less reliable

    'day' => ':count ಸುಗ್ಗಿ', // less reliable
    'd' => ':count ಸುಗ್ಗಿ', // less reliable
    'a_day' => ':count ಸುಗ್ಗಿ', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ss.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Wacław Jacek
 * - François B
 * - Tim Fish
 * - Serhan Apaydın
 * - Massimiliano Caniparoli
 * - JD Isaacks
 * - Jakub Szwacz
 * - Jan
 * - Paul
 * - damlys
 * - Marek (marast78)
 * - Peter (UnrulyNatives)
 * - Qrzysio
 * - Jan (aso824)
 * - diverpl
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count rok|:count lata|:count lat',
    'a_year' => 'rok|:count lata|:count lat',
    'y' => ':count r|:count l|:count l',
    'month' => ':count miesiąc|:count miesiące|:count miesięcy',
    'a_month' => 'miesiąc|:count miesiące|:count miesięcy',
    'm' => ':count mies.',
    'week' => ':count tydzień|:count tygodnie|:count tygodni',
    'a_week' => 'tydzień|:count tygodnie|:count tygodni',
    'w' => ':count tyg.',
    'day' => ':count dzień|:count dni|:count dni',
    'a_day' => 'dzień|:count dni|:count dni',
    'd' => ':count d',
    'hour' => ':count godzina|:count godziny|:count godzin',
    'a_hour' => 'godzina|:count godziny|:count godzin',
    'h' => ':count godz.',
    'minute' => ':count minuta|:count minuty|:count minut',
    'a_minute' => 'minuta|:count minuty|:count minut',
    'min' => ':count min',
    'second' => ':count sekunda|:count sekundy|:count sekund',
    'a_second' => '{1}kilka sekund|:count sekunda|:count sekundy|:count sekund',
    's' => ':count sek.',
    'ago' => ':time temu',
    'from_now' => static function ($time) {
        return 'za '.strtr($time, [
            'godzina' => 'godzinę',
            'minuta' => 'minutę',
            'sekunda' => 'sekundę',
        ]);
    },
    'after' => ':time po',
    'before' => ':time przed',
    'diff_now' => 'teraz',
    'diff_today' => 'Dziś',
    'diff_today_regexp' => 'Dziś(?:\\s+o)?',
    'diff_yesterday' => 'wczoraj',
    'diff_yesterday_regexp' => 'Wczoraj(?:\\s+o)?',
    'diff_tomorrow' => 'jutro',
    'diff_tomorrow_regexp' => 'Jutro(?:\\s+o)?',
    'diff_before_yesterday' => 'przedwczoraj',
    'diff_after_tomorrow' => 'pojutrze',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Dziś o] LT',
        'nextDay' => '[Jutro o] LT',
        'nextWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[W niedzielę o] LT',
            2 => '[We wtorek o] LT',
            3 => '[W środę o] LT',
            6 => '[W sobotę o] LT',
            default => '[W] dddd [o] LT',
        },
        'lastDay' => '[Wczoraj o] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[W zeszłą niedzielę o] LT',
            3 => '[W zeszłą środę o] LT',
            6 => '[W zeszłą sobotę o] LT',
            default => '[W zeszły] dddd [o] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca', 'lipca', 'sierpnia', 'września', 'października', 'listopada', 'grudnia'],
    'months_standalone' => ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec', 'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień'],
    'months_short' => ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru'],
    'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['niedziela', 'poniedziałek', 'wtorek', 'środa', 'czwartek', 'piątek', 'sobota'],
    'weekdays_short' => ['ndz', 'pon', 'wt', 'śr', 'czw', 'pt', 'sob'],
    'weekdays_min' => ['Nd', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' i '],
    'meridiem' => ['przed południem', 'po południu'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/se.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ff.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory  bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YY',
        'LL' => 'MMMM DD, YYYY',
        'LLL' => 'DD MMM HH:mm',
        'LLLL' => 'MMMM DD, YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - pablo@mandriva.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Siqiññaatchiaq', 'Siqiññaasrugruk', 'Paniqsiqsiivik', 'Qilġich Tatqiat', 'Suppivik', 'Iġñivik', 'Itchavik', 'Tiññivik', 'Amiġaiqsivik', 'Sikkuvik', 'Nippivik', 'Siqiñġiḷaq'],
    'months_short' => ['Sñt', 'Sñs', 'Pan', 'Qil', 'Sup', 'Iġñ', 'Itc', 'Tiñ', 'Ami', 'Sik', 'Nip', 'Siq'],
    'weekdays' => ['Minġuiqsioiq', 'Savałłiq', 'Ilaqtchiioiq', 'Qitchiioiq', 'Sisamiioiq', 'Tallimmiioiq', 'Maqinġuoiq'],
    'weekdays_short' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'],
    'weekdays_min' => ['Min', 'Sav', 'Ila', 'Qit', 'Sis', 'Tal', 'Maq'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => ':count ukiuq',
    'y' => ':count ukiuq',
    'a_year' => ':count ukiuq',

    'month' => ':count Tatqiat',
    'm' => ':count Tatqiat',
    'a_month' => ':count Tatqiat',

    'week' => ':count tatqiat', // less reliable
    'w' => ':count tatqiat', // less reliable
    'a_week' => ':count tatqiat', // less reliable

    'day' => ':count siqiñiq', // less reliable
    'd' => ':count siqiñiq', // less reliable
    'a_day' => ':count siqiñiq', // less reliable

    'hour' => ':count Siḷa', // less reliable
    'h' => ':count Siḷa', // less reliable
    'a_hour' => ':count Siḷa', // less reliable

    'second' => ':count iġñiq', // less reliable
    's' => ':count iġñiq', // less reliable
    'a_second' => ':count iġñiq', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - tjku
 * - Max Melentiev
 * - Juanito Fatas
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Nicolás Hock Isaza
 * - Miha Rebernik
 * - Gal Jakič (morpheus7CS)
 * - Glavić
 * - Anže Časar
 * - Lovro Tramšek (Lovro1107)
 * - burut13
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count leto|:count leti|:count leta|:count let',
    'y' => ':count leto|:count leti|:count leta|:count let',
    'month' => ':count mesec|:count meseca|:count mesece|:count mesecev',
    'm' => ':count mes.',
    'week' => ':count teden|:count tedna|:count tedne|:count tednov',
    'w' => ':count ted.',
    'day' => ':count dan|:count dni|:count dni|:count dni',
    'd' => ':count dan|:count dni|:count dni|:count dni',
    'hour' => ':count ura|:count uri|:count ure|:count ur',
    'h' => ':count h',
    'minute' => ':count minuta|:count minuti|:count minute|:count minut',
    'min' => ':count min.',
    'second' => ':count sekunda|:count sekundi|:count sekunde|:count sekund',
    'a_second' => '{1}nekaj sekund|:count sekunda|:count sekundi|:count sekunde|:count sekund',
    's' => ':count s',

    'year_ago' => ':count letom|:count letoma|:count leti|:count leti',
    'y_ago' => ':count letom|:count letoma|:count leti|:count leti',
    'month_ago' => ':count mesecem|:count mesecema|:count meseci|:count meseci',
    'week_ago' => ':count tednom|:count tednoma|:count tedni|:count tedni',
    'day_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi',
    'd_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi',
    'hour_ago' => ':count uro|:count urama|:count urami|:count urami',
    'minute_ago' => ':count minuto|:count minutama|:count minutami|:count minutami',
    'second_ago' => ':count sekundo|:count sekundama|:count sekundami|:count sekundami',

    'day_from_now' => ':count dan|:count dneva|:count dni|:count dni',
    'd_from_now' => ':count dan|:count dneva|:count dni|:count dni',
    'hour_from_now' => ':count uro|:count uri|:count ure|:count ur',
    'minute_from_now' => ':count minuto|:count minuti|:count minute|:count minut',
    'second_from_now' => ':count sekundo|:count sekundi|:count sekunde|:count sekund',

    'ago' => 'pred :time',
    'from_now' => 'čez :time',
    'after' => ':time kasneje',
    'before' => ':time prej',

    'diff_now' => 'ravnokar',
    'diff_today' => 'danes',
    'diff_today_regexp' => 'danes(?:\\s+ob)?',
    'diff_yesterday' => 'včeraj',
    'diff_yesterday_regexp' => 'včeraj(?:\\s+ob)?',
    'diff_tomorrow' => 'jutri',
    'diff_tomorrow_regexp' => 'jutri(?:\\s+ob)?',
    'diff_before_yesterday' => 'predvčerajšnjim',
    'diff_after_tomorrow' => 'pojutrišnjem',

    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'period_start_date' => 'od :date',
    'period_end_date' => 'do :date',

    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY H:mm',
        'LLLL' => 'dddd, D. MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[danes ob] LT',
        'nextDay' => '[jutri ob] LT',
        'nextWeek' => 'dddd [ob] LT',
        'lastDay' => '[včeraj ob] LT',
        'lastWeek' => static function (CarbonInterface $date) {
            switch ($date->dayOfWeek) {
                case 0:
                    return '[preteklo] [nedeljo] [ob] LT';
                case 1:
                    return '[pretekli] [ponedeljek] [ob] LT';
                case 2:
                    return '[pretekli] [torek] [ob] LT';
                case 3:
                    return '[preteklo] [sredo] [ob] LT';
                case 4:
                    return '[pretekli] [četrtek] [ob] LT';
                case 5:
                    return '[pretekli] [petek] [ob] LT';
                case 6:
                    return '[preteklo] [soboto] [ob] LT';
            }
        },
        'sameElse' => 'L',
    ],
    'months' => ['januarja', 'februarja', 'marca', 'aprila', 'maja', 'junija', 'julija', 'avgusta', 'septembra', 'oktobra', 'novembra', 'decembra'],
    'months_standalone' => ['januar', 'februar', 'marec', 'april', 'maj', 'junij', 'julij', 'avgust', 'september', 'oktober', 'november', 'december'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'avg', 'sep', 'okt', 'nov', 'dec'],
    'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['nedelja', 'ponedeljek', 'torek', 'sreda', 'četrtek', 'petek', 'sobota'],
    'weekdays_short' => ['ned', 'pon', 'tor', 'sre', 'čet', 'pet', 'sob'],
    'weekdays_min' => ['ne', 'po', 'to', 'sr', 'če', 'pe', 'so'],
    'list' => [', ', ' in '],
    'meridiem' => ['dopoldan', 'popoldan'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kunal Marwaha
 * - FourwingsY
 * - François B
 * - Jason Katz-Brown
 * - Seokjun Kim
 * - Junho Kim
 * - JD Isaacks
 * - Juwon Kim
 */
return [
    'year' => ':count년',
    'a_year' => '{1}일년|[-Inf,Inf]:count년',
    'y' => ':count년',
    'month' => ':count개월',
    'a_month' => '{1}한달|[-Inf,Inf]:count개월',
    'm' => ':count개월',
    'week' => ':count주',
    'a_week' => '{1}일주일|[-Inf,Inf]:count 주',
    'w' => ':count주일',
    'day' => ':count일',
    'a_day' => '{1}하루|[-Inf,Inf]:count일',
    'd' => ':count일',
    'hour' => ':count시간',
    'a_hour' => '{1}한시간|[-Inf,Inf]:count시간',
    'h' => ':count시간',
    'minute' => ':count분',
    'a_minute' => '{1}일분|[-Inf,Inf]:count분',
    'min' => ':count분',
    'second' => ':count초',
    'a_second' => '{1}몇초|[-Inf,Inf]:count초',
    's' => ':count초',
    'ago' => ':time 전',
    'from_now' => ':time 후',
    'after' => ':time 후',
    'before' => ':time 전',
    'diff_now' => '지금',
    'diff_today' => '오늘',
    'diff_yesterday' => '어제',
    'diff_tomorrow' => '내일',
    'formats' => [
        'LT' => 'A h:mm',
        'LTS' => 'A h:mm:ss',
        'L' => 'YYYY.MM.DD.',
        'LL' => 'YYYY년 MMMM D일',
        'LLL' => 'YYYY년 MMMM D일 A h:mm',
        'LLLL' => 'YYYY년 MMMM D일 dddd A h:mm',
    ],
    'calendar' => [
        'sameDay' => '오늘 LT',
        'nextDay' => '내일 LT',
        'nextWeek' => 'dddd LT',
        'lastDay' => '어제 LT',
        'lastWeek' => '지난주 dddd LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'd', 'D', 'DDD' => $number.'일',
            'M' => $number.'월',
            'w', 'W' => $number.'주',
            default => $number,
        };
    },
    'meridiem' => ['오전', '오후'],
    'months' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
    'months_short' => ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
    'weekdays' => ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일'],
    'weekdays_short' => ['일', '월', '화', '수', '목', '금', '토'],
    'weekdays_min' => ['일', '월', '화', '수', '목', '금', '토'],
    'list' => ' ',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Sunguti', 'Nyenyenyani', 'Nyenyankulu', 'Dzivamisoko', 'Mudyaxihi', 'Khotavuxika', 'Mawuwani', 'Mhawuri', 'Ndzhati', 'Nhlangula', 'Hukuri', 'N\'wendzamhala'],
    'months_short' => ['Sun', 'Yan', 'Kul', 'Dzi', 'Mud', 'Kho', 'Maw', 'Mha', 'Ndz', 'Nhl', 'Huk', 'N\'w'],
    'weekdays' => ['Sonto', 'Musumbhunuku', 'Ravumbirhi', 'Ravunharhu', 'Ravumune', 'Ravuntlhanu', 'Mugqivela'],
    'weekdays_short' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
    'weekdays_min' => ['Son', 'Mus', 'Bir', 'Har', 'Ne', 'Tlh', 'Mug'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => 'malembe ya :count',
    'y' => 'malembe ya :count',
    'a_year' => 'malembe ya :count',

    'month' => 'tin’hweti ta :count',
    'm' => 'tin’hweti ta :count',
    'a_month' => 'tin’hweti ta :count',

    'week' => 'mavhiki ya :count',
    'w' => 'mavhiki ya :count',
    'a_week' => 'mavhiki ya :count',

    'day' => 'masiku :count',
    'd' => 'masiku :count',
    'a_day' => 'masiku :count',

    'hour' => 'tiawara ta :count',
    'h' => 'tiawara ta :count',
    'a_hour' => 'tiawara ta :count',

    'minute' => 'timinete ta :count',
    'min' => 'timinete ta :count',
    'a_minute' => 'timinete ta :count',

    'second' => 'tisekoni ta :count',
    's' => 'tisekoni ta :count',
    'a_second' => 'tisekoni ta :count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Daniel Cohen Gindi
 * - JD Isaacks
 * - Itai Nathaniel
 * - GabMic
 * - Yaakov Dahan (yakidahan)
 */
return [
    'year' => 'שנה|{2}שנתיים|:count שנים',
    'y' => 'שנה|:count שנ׳',
    'month' => 'חודש|{2}חודשיים|:count חודשים',
    'm' => 'חודש|:count חו׳',
    'week' => 'שבוע|{2}שבועיים|:count שבועות',
    'w' => 'שבוע|:count שב׳',
    'day' => 'יום|{2}יומיים|:count ימים',
    'd' => 'יום|:count ימ׳',
    'hour' => 'שעה|{2}שעתיים|:count שעות',
    'h' => 'שעה|:count שע׳',
    'minute' => 'דקה|{2}שתי דקות|:count דקות',
    'min' => 'דקה|:count דק׳',
    'second' => 'שנייה|:count שניות',
    'a_second' => 'כמה שניות|:count שניות',
    's' => 'שניה|:count שנ׳',
    'ago' => 'לפני :time',
    'from_now' => 'בעוד :time מעכשיו',
    'after' => 'אחרי :time',
    'before' => 'לפני :time',
    'diff_now' => 'עכשיו',
    'diff_today' => 'היום',
    'diff_today_regexp' => 'היום(?:\\s+ב־)?',
    'diff_yesterday' => 'אתמול',
    'diff_yesterday_regexp' => 'אתמול(?:\\s+ב־)?',
    'diff_tomorrow' => 'מחר',
    'diff_tomorrow_regexp' => 'מחר(?:\\s+ב־)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D [ב]MMMM YYYY',
        'LLL' => 'D [ב]MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D [ב]MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[היום ב־]LT',
        'nextDay' => '[מחר ב־]LT',
        'nextWeek' => 'dddd [בשעה] LT',
        'lastDay' => '[אתמול ב־]LT',
        'lastWeek' => '[ביום] dddd [האחרון בשעה] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour, $minute, $isLower) {
        if ($hour < 5) {
            return 'לפנות בוקר';
        }
        if ($hour < 10) {
            return 'בבוקר';
        }
        if ($hour < 12) {
            return $isLower ? 'לפנה"צ' : 'לפני הצהריים';
        }
        if ($hour < 18) {
            return $isLower ? 'אחה"צ' : 'אחרי הצהריים';
        }

        return 'בערב';
    },
    'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],
    'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],
    'weekdays' => ['ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'],
    'weekdays_short' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
    'weekdays_min' => ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ש'],
    'list' => [', ', ' ו -'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['TOO', 'MUU'],
    'weekdays' => ['Jumapíiri', 'Jumatátu', 'Jumaíne', 'Jumatáano', 'Alamíisi', 'Ijumáa', 'Jumamóosi'],
    'weekdays_short' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
    'weekdays_min' => ['Píili', 'Táatu', 'Íne', 'Táano', 'Alh', 'Ijm', 'Móosi'],
    'months' => ['Kʉfúngatɨ', 'Kʉnaanɨ', 'Kʉkeenda', 'Kwiikumi', 'Kwiinyambála', 'Kwiidwaata', 'Kʉmʉʉnchɨ', 'Kʉvɨɨrɨ', 'Kʉsaatʉ', 'Kwiinyi', 'Kʉsaano', 'Kʉsasatʉ'],
    'months_short' => ['Fúngatɨ', 'Naanɨ', 'Keenda', 'Ikúmi', 'Inyambala', 'Idwaata', 'Mʉʉnchɨ', 'Vɨɨrɨ', 'Saatʉ', 'Inyi', 'Saano', 'Sasatʉ'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - monkeycon
 * - François B
 * - Jason Katz-Brown
 * - Konstantin Konev
 * - Chris Lam
 * - Serhan Apaydın
 * - Gary Lo
 * - JD Isaacks
 * - Chris Hemp
 * - shankesgk2
 * - Daniel Cheung (danvim)
 */
return [
    'year' => ':count:optional-space年',
    'y' => ':count:optional-space年',
    'month' => ':count:optional-space个月',
    'm' => ':count:optional-space个月',
    'week' => ':count:optional-space周',
    'w' => ':count:optional-space周',
    'day' => ':count:optional-space天',
    'd' => ':count:optional-space天',
    'hour' => ':count:optional-space小时',
    'h' => ':count:optional-space小时',
    'minute' => ':count:optional-space分钟',
    'min' => ':count:optional-space分钟',
    'second' => ':count:optional-space秒',
    'a_second' => '{1}几秒|[-Inf,Inf]:count:optional-space秒',
    's' => ':count:optional-space秒',
    'ago' => ':time前',
    'from_now' => ':time后',
    'after' => ':time后',
    'before' => ':time前',
    'diff_now' => '现在',
    'diff_today' => '今天',
    'diff_yesterday' => '昨天',
    'diff_tomorrow' => '明天',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY/MM/DD',
        'LL' => 'YYYY年M月D日',
        'LLL' => 'YYYY年M月D日 HH:mm',
        'LLLL' => 'YYYY年M月D日dddd HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[今天]LT',
        'nextDay' => '[明天]LT',
        'nextWeek' => '[下]ddddLT',
        'lastDay' => '[昨天]LT',
        'lastWeek' => '[上]ddddLT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'd', 'D', 'DDD' => $number.'日',
            'M' => $number.'月',
            'w', 'W' => $number.'周',
            default => $number,
        };
    },
    'meridiem' => static function ($hour, $minute) {
        $time = $hour * 100 + $minute;
        if ($time < 600) {
            return '凌晨';
        }
        if ($time < 900) {
            return '早上';
        }
        if ($time < 1130) {
            return '上午';
        }
        if ($time < 1230) {
            return '中午';
        }
        if ($time < 1800) {
            return '下午';
        }

        return '晚上';
    },
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    'weekdays_short' => ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => '',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

$bengaliNumbers = ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯'];

/*
 * Authors:
 * - Josh Soref
 * - Shakib Hossain
 * - Raju
 * - Aniruddha Adhikary
 * - JD Isaacks
 * - Saiful Islam
 * - Faisal Islam
 * - Hayatunnabi Nabil
 */
return [
    'year' => ':count বছর',
    'a_year' => 'এক বছর|:count বছর',
    'y' => '১ বছর|:count বছর',
    'month' => ':count মাস',
    'a_month' => 'এক মাস|:count মাস',
    'm' => '১ মাস|:count মাস',
    'week' => ':count সপ্তাহ',
    'a_week' => '১ সপ্তাহ|:count সপ্তাহ',
    'w' => '১ সপ্তাহ|:count সপ্তাহ',
    'day' => ':count দিন',
    'a_day' => 'এক দিন|:count দিন',
    'd' => '১ দিন|:count দিন',
    'hour' => ':count ঘন্টা',
    'a_hour' => 'এক ঘন্টা|:count ঘন্টা',
    'h' => '১ ঘন্টা|:count ঘন্টা',
    'minute' => ':count মিনিট',
    'a_minute' => 'এক মিনিট|:count মিনিট',
    'min' => '১ মিনিট|:count মিনিট',
    'second' => ':count সেকেন্ড',
    'a_second' => 'কয়েক সেকেন্ড|:count সেকেন্ড',
    's' => '১ সেকেন্ড|:count সেকেন্ড',
    'millisecond' => ':count মিলিসেকেন্ড',
    'a_millisecond' => 'এক মিলিসেকেন্ড|:count মিলিসেকেন্ড',
    'ms' => '১ মিলিসেকেন্ড|:count মিলিসেকেন্ড',
    'microsecond' => ':count মাইক্রোসেকেন্ড',
    'a_microsecond' => 'এক মাইক্রোসেকেন্ড|:count মাইক্রোসেকেন্ড',
    'µs' => '১ মাইক্রোসেকেন্ড|:count মাইক্রোসেকেন্ড',
    'ago' => ':time আগে',
    'from_now' => ':time পরে',
    'after' => ':time পরে',
    'before' => ':time আগে',
    'diff_now' => 'এখন',
    'diff_today' => 'আজ',
    'diff_yesterday' => 'গতকাল',
    'diff_tomorrow' => 'আগামীকাল',
    'diff_before_yesterday' => 'গত পরশু',
    'diff_after_tomorrow' => 'আগামী পরশু',
    'period_recurrences' => ':count বার|:count বার',
    'period_interval' => 'প্রতি :interval',
    'period_start_date' => ':date থেকে',
    'period_end_date' => ':date পর্যন্ত',
    'formats' => [
        'LT' => 'A Oh:Om সময়',
        'LTS' => 'A Oh:Om:Os সময়',
        'L' => 'OD/OM/OY',
        'LL' => 'OD MMMM OY',
        'LLL' => 'OD MMMM OY, A Oh:Om সময়',
        'LLLL' => 'dddd, OD MMMM OY, A Oh:Om সময়',
    ],
    'calendar' => [
        'sameDay' => '[আজ] LT',
        'nextDay' => '[আগামীকাল] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[গতকাল] LT',
        'lastWeek' => '[গত] dddd, LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'রাত';
        }
        if ($hour < 10) {
            return 'সকাল';
        }
        if ($hour < 17) {
            return 'দুপুর';
        }
        if ($hour < 20) {
            return 'বিকাল';
        }

        return 'রাত';
    },
    'months' => ['জানুয়ারী', 'ফেব্রুয়ারি', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
    'months_short' => ['জানু', 'ফেব', 'মার্চ', 'এপ্র', 'মে', 'জুন', 'জুল', 'আগ', 'সেপ্ট', 'অক্টো', 'নভে', 'ডিসে'],
    'weekdays' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহস্পতিবার', 'শুক্রবার', 'শনিবার'],
    'weekdays_short' => ['রবি', 'সোম', 'মঙ্গল', 'বুধ', 'বৃহস্পতি', 'শুক্র', 'শনি'],
    'weekdays_min' => ['রবি', 'সোম', 'মঙ্গ', 'বুধ', 'বৃহঃ', 'শুক্র', 'শনি'],
    'ordinal' => static function ($number) use ($bengaliNumbers) {
        // Convert to Bengali numerals
        $bengaliNumber = str_replace(
            ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
            $bengaliNumbers,
            (string) $number
        );

        // Apply Bengali ordinal rules
        $lastDigit = $number % 10;
        $lastTwoDigits = $number % 100;

        // Special cases for teens (11-19) always use তম
        if ($lastTwoDigits >= 11 && $lastTwoDigits <= 19) {
            return $bengaliNumber.'তম';
        }

        // For numbers 1-10, use specific rules
        if ($number <= 10) {
            switch ($number) {
                case 1:
                case 5:
                case 7:
                case 8:
                case 9:
                case 10:
                    return $bengaliNumber.'ম';
                case 2:
                case 3:
                    return $bengaliNumber.'য়';
                case 4:
                    return $bengaliNumber.'র্থ';
                case 6:
                    return $bengaliNumber.'ষ্ঠ';
                default:
                    return $bengaliNumber.'তম';
            }
        }

        // For numbers > 20, all use তম
        return $bengaliNumber.'তম';
    },
    'list' => [', ', ' এবং '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'weekdays_standalone' => ['রবিবার', 'সোমবার', 'মঙ্গলবার', 'বুধবার', 'বৃহষ্পতিবার', 'শুক্রবার', 'শনিবার'],
    'weekdays_min_standalone' => ['রঃ', 'সোঃ', 'মঃ', 'বুঃ', 'বৃঃ', 'শুঃ', 'শনি'],
    'months_short_standalone' => ['জানুয়ারী', 'ফেব্রুয়ারী', 'মার্চ', 'এপ্রিল', 'মে', 'জুন', 'জুলাই', 'আগস্ট', 'সেপ্টেম্বর', 'অক্টোবর', 'নভেম্বর', 'ডিসেম্বর'],
    'alt_numbers' => $bengaliNumbers,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/yuw_PG.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - szl_PL locale Przemyslaw Buczkowski libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['styczyń', 'luty', 'merc', 'kwjeciyń', 'moj', 'czyrwjyń', 'lipjyń', 'siyrpjyń', 'wrzesiyń', 'październik', 'listopad', 'grudziyń'],
    'months_short' => ['sty', 'lut', 'mer', 'kwj', 'moj', 'czy', 'lip', 'siy', 'wrz', 'paź', 'lis', 'gru'],
    'weekdays' => ['niydziela', 'pyńdziŏek', 'wtŏrek', 'strzŏda', 'sztwortek', 'pjōntek', 'sobŏta'],
    'weekdays_short' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'],
    'weekdays_min' => ['niy', 'pyń', 'wtŏ', 'str', 'szt', 'pjō', 'sob'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count rok',
    'y' => ':count rok',
    'a_year' => ':count rok',

    'month' => ':count mjeśůnc',
    'm' => ':count mjeśůnc',
    'a_month' => ':count mjeśůnc',

    'week' => ':count tydźyń',
    'w' => ':count tydźyń',
    'a_week' => ':count tydźyń',

    'day' => ':count dźyń',
    'd' => ':count dźyń',
    'a_day' => ':count dźyń',

    'hour' => ':count godzina',
    'h' => ':count godzina',
    'a_hour' => ':count godzina',

    'minute' => ':count minuta',
    'min' => ':count minuta',
    'a_minute' => ':count minuta',

    'second' => ':count sekůnda',
    's' => ':count sekůnda',
    'a_second' => ':count sekůnda',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
    'weekdays_short' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
    'weekdays_min' => ['lahadi', 'tɛɛnɛɛ', 'talata', 'alaba', 'aimisa', 'aijima', 'siɓiti'],
    'months' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
    'months_short' => ['luukao kemã', 'ɓandaɓu', 'vɔɔ', 'fulu', 'goo', '6', '7', 'kɔnde', 'saah', 'galo', 'kenpkato ɓololɔ', 'luukao lɔma'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd, D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - JD Isaacks
 * - Fadion Dashi
 */
return [
    'year' => ':count vit|:count vjet',
    'a_year' => 'një vit|:count vite',
    'y' => ':count v.',
    'month' => ':count muaj',
    'a_month' => 'një muaj|:count muaj',
    'm' => ':count muaj',
    'week' => ':count javë',
    'a_week' => ':count javë|:count javë',
    'w' => ':count j.',
    'day' => ':count ditë',
    'a_day' => 'një ditë|:count ditë',
    'd' => ':count d.',
    'hour' => ':count orë',
    'a_hour' => 'një orë|:count orë',
    'h' => ':count o.',
    'minute' => ':count minutë|:count minuta',
    'a_minute' => 'një minutë|:count minuta',
    'min' => ':count min.',
    'second' => ':count sekondë|:count sekonda',
    'a_second' => 'disa sekonda|:count sekonda',
    's' => ':count s.',
    'ago' => ':time më parë',
    'from_now' => 'në :time',
    'after' => ':time pas',
    'before' => ':time para',
    'diff_now' => 'tani',
    'diff_today' => 'Sot',
    'diff_today_regexp' => 'Sot(?:\\s+në)?',
    'diff_yesterday' => 'dje',
    'diff_yesterday_regexp' => 'Dje(?:\\s+në)?',
    'diff_tomorrow' => 'nesër',
    'diff_tomorrow_regexp' => 'Nesër(?:\\s+në)?',
    'diff_before_yesterday' => 'pardje',
    'diff_after_tomorrow' => 'pasnesër',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Sot në] LT',
        'nextDay' => '[Nesër në] LT',
        'nextWeek' => 'dddd [në] LT',
        'lastDay' => '[Dje në] LT',
        'lastWeek' => 'dddd [e kaluar në] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'meridiem' => ['PD', 'MD'],
    'months' => ['janar', 'shkurt', 'mars', 'prill', 'maj', 'qershor', 'korrik', 'gusht', 'shtator', 'tetor', 'nëntor', 'dhjetor'],
    'months_short' => ['jan', 'shk', 'mar', 'pri', 'maj', 'qer', 'kor', 'gus', 'sht', 'tet', 'nën', 'dhj'],
    'weekdays' => ['e diel', 'e hënë', 'e martë', 'e mërkurë', 'e enjte', 'e premte', 'e shtunë'],
    'weekdays_short' => ['die', 'hën', 'mar', 'mër', 'enj', 'pre', 'sht'],
    'weekdays_min' => ['d', 'h', 'ma', 'më', 'e', 'p', 'sh'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' dhe '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Samsung Electronics Co., Ltd.    akhilesh.k@samsung.com & maninder1.s@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'dddd DD MMM YYYY',
    ],
    'months' => ['jenuware', 'febwari', 'maj', 'epril', 'mei', 'jun', 'julae', 'ogis', 'septemba', 'oktoba', 'novemba', 'disemba'],
    'months_short' => ['jen', 'feb', 'maj', 'epr', 'mei', 'jun', 'jul', 'ogi', 'sep', 'okt', 'nov', 'dis'],
    'weekdays' => ['sande', 'mande', 'maj', 'wota', 'fraede', 'sarede'],
    'weekdays_short' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'],
    'weekdays_min' => ['san', 'man', 'maj', 'wot', 'fra', 'sar'],

    'year' => ':count seven', // less reliable
    'y' => ':count seven', // less reliable
    'a_year' => ':count seven', // less reliable

    'month' => ':count mi', // less reliable
    'm' => ':count mi', // less reliable
    'a_month' => ':count mi', // less reliable

    'week' => ':count sarede', // less reliable
    'w' => ':count sarede', // less reliable
    'a_week' => ':count sarede', // less reliable

    'day' => ':count betde', // less reliable
    'd' => ':count betde', // less reliable
    'a_day' => ':count betde', // less reliable

    'hour' => ':count klok', // less reliable
    'h' => ':count klok', // less reliable
    'a_hour' => ':count klok', // less reliable

    'minute' => ':count smol', // less reliable
    'min' => ':count smol', // less reliable
    'a_minute' => ':count smol', // less reliable

    'second' => ':count tu', // less reliable
    's' => ':count tu', // less reliable
    'a_second' => ':count tu', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - sr_YU, sr_CS locale Danilo Segan bug-glibc-locales@gnu.org
 */
return require __DIR__.'/sr_Cyrl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Takuya Sawada
 * - Atsushi Tanaka
 * - François B
 * - Jason Katz-Brown
 * - Serhan Apaydın
 * - XueWei
 * - JD Isaacks
 * - toyama satoshi
 * - atakigawa
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count年',
    'y' => ':count年',
    'month' => ':countヶ月',
    'm' => ':countヶ月',
    'week' => ':count週間',
    'w' => ':count週間',
    'day' => ':count日',
    'd' => ':count日',
    'hour' => ':count時間',
    'h' => ':count時間',
    'minute' => ':count分',
    'min' => ':count分',
    'second' => ':count秒',
    'a_second' => '{1}数秒|[-Inf,Inf]:count秒',
    's' => ':count秒',
    'ago' => ':time前',
    'from_now' => ':time後',
    'after' => ':time後',
    'before' => ':time前',
    'diff_now' => '今',
    'diff_today' => '今日',
    'diff_yesterday' => '昨日',
    'diff_tomorrow' => '明日',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY/MM/DD',
        'LL' => 'YYYY年M月D日',
        'LLL' => 'YYYY年M月D日 HH:mm',
        'LLLL' => 'YYYY年M月D日 dddd HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[今日] LT',
        'nextDay' => '[明日] LT',
        'nextWeek' => static function (CarbonInterface $current, \Carbon\CarbonInterface $other) {
            if ($other->week !== $current->week) {
                return '[来週]dddd LT';
            }

            return 'dddd LT';
        },
        'lastDay' => '[昨日] LT',
        'lastWeek' => static function (CarbonInterface $current, \Carbon\CarbonInterface $other) {
            if ($other->week !== $current->week) {
                return '[先週]dddd LT';
            }

            return 'dddd LT';
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'd', 'D', 'DDD' => $number.'日',
            default => $number,
        };
    },
    'meridiem' => ['午前', '午後'],
    'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    'weekdays' => ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
    'weekdays_short' => ['日', '月', '火', '水', '木', '金', '土'],
    'weekdays_min' => ['日', '月', '火', '水', '木', '金', '土'],
    'list' => '、',
    'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', '二十一', '二十二', '二十三', '二十四', '二十五', '二十六', '二十七', '二十八', '二十九', '三十', '三十一', '三十二', '三十三', '三十四', '三十五', '三十六', '三十七', '三十八', '三十九', '四十', '四十一', '四十二', '四十三', '四十四', '四十五', '四十六', '四十七', '四十八', '四十九', '五十', '五十一', '五十二', '五十三', '五十四', '五十五', '五十六', '五十七', '五十八', '五十九', '六十', '六十一', '六十二', '六十三', '六十四', '六十五', '六十六', '六十七', '六十八', '六十九', '七十', '七十一', '七十二', '七十三', '七十四', '七十五', '七十六', '七十七', '七十八', '七十九', '八十', '八十一', '八十二', '八十三', '八十四', '八十五', '八十六', '八十七', '八十八', '八十九', '九十', '九十一', '九十二', '九十三', '九十四', '九十五', '九十六', '九十七', '九十八', '九十九'],
    'alt_numbers_pow' => [
        10000 => '万',
        1000 => '千',
        100 => '百',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Lwamilawu', 'Pashamihe'],
    'weekdays' => ['Mulungu', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alahamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'weekdays_min' => ['Mul', 'Jtt', 'Jnn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'months' => ['Mupalangulwa', 'Mwitope', 'Mushende', 'Munyi', 'Mushende Magali', 'Mujimbi', 'Mushipepo', 'Mupuguto', 'Munyense', 'Mokhu', 'Musongandembwe', 'Muhaano'],
    'months_short' => ['Mup', 'Mwi', 'Msh', 'Mun', 'Mag', 'Muj', 'Msp', 'Mpg', 'Mye', 'Mok', 'Mus', 'Muh'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'ca');
    }, 'ca_ES_Valencia');
}
// @codeCoverageIgnoreEnd

return array_replace_recursive(require __DIR__.'/ca.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hans.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - The Debian project Christian Perrier bubulle@debian.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D-MM-YY',
    ],
    'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'weekdays' => ['रविवासर:', 'सोमवासर:', 'मंगलवासर:', 'बुधवासर:', 'बृहस्पतिवासरः', 'शुक्रवासर', 'शनिवासर:'],
    'weekdays_short' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'],
    'weekdays_min' => ['रविः', 'सोम:', 'मंगल:', 'बुध:', 'बृहस्पतिः', 'शुक्र', 'शनि:'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],

    'minute' => ':count होरा', // less reliable
    'min' => ':count होरा', // less reliable
    'a_minute' => ':count होरा', // less reliable

    'year' => ':count वर्ष',
    'y' => ':count वर्ष',
    'a_year' => ':count वर्ष',

    'month' => ':count मास',
    'm' => ':count मास',
    'a_month' => ':count मास',

    'week' => ':count सप्ताहः saptahaĥ',
    'w' => ':count सप्ताहः saptahaĥ',
    'a_week' => ':count सप्ताहः saptahaĥ',

    'day' => ':count दिन',
    'd' => ':count दिन',
    'a_day' => ':count दिन',

    'hour' => ':count घण्टा',
    'h' => ':count घण्टा',
    'a_hour' => ':count घण्टा',

    'second' => ':count द्वितीयः',
    's' => ':count द्वितीयः',
    'a_second' => ':count द्वितीयः',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Alastair McKinstry    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Jerrey-geuree', 'Toshiaght-arree', 'Mayrnt', 'Averil', 'Boaldyn', 'Mean-souree', 'Jerrey-souree', 'Luanistyn', 'Mean-fouyir', 'Jerrey-fouyir', 'Mee Houney', 'Mee ny Nollick'],
    'months_short' => ['J-guer', 'T-arree', 'Mayrnt', 'Avrril', 'Boaldyn', 'M-souree', 'J-souree', 'Luanistyn', 'M-fouyir', 'J-fouyir', 'M.Houney', 'M.Nollick'],
    'weekdays' => ['Jedoonee', 'Jelhein', 'Jemayrt', 'Jercean', 'Jerdein', 'Jeheiney', 'Jesarn'],
    'weekdays_short' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
    'weekdays_min' => ['Jed', 'Jel', 'Jem', 'Jerc', 'Jerd', 'Jeh', 'Jes'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count blein',
    'y' => ':count blein',
    'a_year' => ':count blein',

    'month' => ':count mee',
    'm' => ':count mee',
    'a_month' => ':count mee',

    'week' => ':count shiaghtin',
    'w' => ':count shiaghtin',
    'a_week' => ':count shiaghtin',

    'day' => ':count laa',
    'd' => ':count laa',
    'a_day' => ':count laa',

    'hour' => ':count oor',
    'h' => ':count oor',
    'a_hour' => ':count oor',

    'minute' => ':count feer veg',
    'min' => ':count feer veg',
    'a_minute' => ':count feer veg',

    'second' => ':count derrey',
    's' => ':count derrey',
    'a_second' => ':count derrey',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,

    'minute' => ':count هنر', // less reliable
    'min' => ':count هنر', // less reliable
    'a_minute' => ':count هنر', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/szl_PL.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fa.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
    'months_short' => ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],
    'weekdays' => ['teoilhuitl', 'ceilhuitl', 'omeilhuitl', 'yeilhuitl', 'nahuilhuitl', 'macuililhuitl', 'chicuaceilhuitl'],
    'weekdays_short' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'],
    'weekdays_min' => ['teo', 'cei', 'ome', 'yei', 'nau', 'mac', 'chi'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'month' => ':count metztli', // less reliable
    'm' => ':count metztli', // less reliable
    'a_month' => ':count metztli', // less reliable

    'week' => ':count tonalli', // less reliable
    'w' => ':count tonalli', // less reliable
    'a_week' => ':count tonalli', // less reliable

    'day' => ':count tonatih', // less reliable
    'd' => ':count tonatih', // less reliable
    'a_day' => ':count tonatih', // less reliable

    'minute' => ':count toltecayotl', // less reliable
    'min' => ':count toltecayotl', // less reliable
    'a_minute' => ':count toltecayotl', // less reliable

    'second' => ':count ome', // less reliable
    's' => ':count ome', // less reliable
    'a_second' => ':count ome', // less reliable

    'year' => ':count xihuitl',
    'y' => ':count xihuitl',
    'a_year' => ':count xihuitl',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['Kiroko', 'Hwaĩ-inĩ'],
    'weekdays' => ['Kiumia', 'Njumatatũ', 'Njumaine', 'Njumatana', 'Aramithi', 'Njumaa', 'Njumamothi'],
    'weekdays_short' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
    'weekdays_min' => ['KMA', 'NTT', 'NMN', 'NMT', 'ART', 'NMA', 'NMM'],
    'months' => ['Njenuarĩ', 'Mwere wa kerĩ', 'Mwere wa gatatũ', 'Mwere wa kana', 'Mwere wa gatano', 'Mwere wa gatandatũ', 'Mwere wa mũgwanja', 'Mwere wa kanana', 'Mwere wa kenda', 'Mwere wa ikũmi', 'Mwere wa ikũmi na ũmwe', 'Ndithemba'],
    'months_short' => ['JEN', 'WKR', 'WGT', 'WKN', 'WTN', 'WTD', 'WMJ', 'WNN', 'WKD', 'WIK', 'WMW', 'DIT'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    'year' => ':count mĩaka', // less reliable
    'y' => ':count mĩaka', // less reliable
    'a_year' => ':count mĩaka', // less reliable

    'month' => ':count mweri', // less reliable
    'm' => ':count mweri', // less reliable
    'a_month' => ':count mweri', // less reliable

    'week' => ':count kiumia', // less reliable
    'w' => ':count kiumia', // less reliable
    'a_week' => ':count kiumia', // less reliable

    'day' => ':count mũthenya', // less reliable
    'd' => ':count mũthenya', // less reliable
    'a_day' => ':count mũthenya', // less reliable

    'hour' => ':count thaa', // less reliable
    'h' => ':count thaa', // less reliable
    'a_hour' => ':count thaa', // less reliable

    'minute' => ':count mundu', // less reliable
    'min' => ':count mundu', // less reliable
    'a_minute' => ':count mundu', // less reliable

    'second' => ':count igego', // less reliable
    's' => ':count igego', // less reliable
    'a_second' => ':count igego', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/se.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
    'months_short' => ['ođđj', 'guov', 'njuk', 'cuoŋ', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
    'weekdays' => ['sotnabeaivi', 'mánnodat', 'disdat', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvordat'],
    'weekdays_short' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'],
    'weekdays_min' => ['so', 'má', 'di', 'ga', 'du', 'be', 'lá'],
    'meridiem' => ['i', 'e'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bhashaghar@googlegroups.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर"'],
    'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितंबर', 'अक्टूबर', 'नवंबर', 'दिसंबर'],
    'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'बृहस्पतिवार', 'शुक्रवार', 'शनिवार'],
    'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
    'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पति', 'शुक्र', 'शनि'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'sr');
    }, 'sr_Latn_BA');
}
// @codeCoverageIgnoreEnd

return array_replace_recursive(require __DIR__.'/sr_Latn.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D.M.yy.',
        'LL' => 'DD.MM.YYYY.',
        'LLL' => 'DD. MMMM YYYY. HH:mm',
        'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
    ],
    'weekdays' => ['nedjelja', 'ponedeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
    'weekdays_short' => ['ned.', 'pon.', 'ut.', 'sr.', 'čet.', 'pet.', 'sub.'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/anp_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ig_NG.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mg_MG.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/uk.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/th.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ne.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'yy/M/d',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D, h:mm a',
        'LLLL' => 'YYYY MMMM D, dddd, h:mm a',
    ],
    'months' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
    'months_short' => ['जनवरी', 'फेब्रुअरी', 'मार्च', 'अप्रिल', 'मे', 'जुन', 'जुलाई', 'अगस्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
    'weekend' => [0, 0],
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ro.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sk.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Atolagbe Abisoye
 */
return [
    'year' => 'ọdún :count',
    'a_year' => '{1}ọdún kan|ọdún :count',
    'month' => 'osù :count',
    'a_month' => '{1}osù kan|osù :count',
    'week' => 'ọsẹ :count',
    'a_week' => '{1}ọsẹ kan|ọsẹ :count',
    'day' => 'ọjọ́ :count',
    'a_day' => '{1}ọjọ́ kan|ọjọ́ :count',
    'hour' => 'wákati :count',
    'a_hour' => '{1}wákati kan|wákati :count',
    'minute' => 'ìsẹjú :count',
    'a_minute' => '{1}ìsẹjú kan|ìsẹjú :count',
    'second' => 'iaayá :count',
    'a_second' => '{1}ìsẹjú aayá die|aayá :count',
    'ago' => ':time kọjá',
    'from_now' => 'ní :time',
    'diff_yesterday' => 'Àna',
    'diff_yesterday_regexp' => 'Àna(?:\\s+ni)?',
    'diff_today' => 'Ònì',
    'diff_today_regexp' => 'Ònì(?:\\s+ni)?',
    'diff_tomorrow' => 'Ọ̀la',
    'diff_tomorrow_regexp' => 'Ọ̀la(?:\\s+ni)?',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm A',
        'LLLL' => 'dddd, D MMMM YYYY h:mm A',
    ],
    'calendar' => [
        'sameDay' => '[Ònì ni] LT',
        'nextDay' => '[Ọ̀la ni] LT',
        'nextWeek' => 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT',
        'lastDay' => '[Àna ni] LT',
        'lastWeek' => 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => 'ọjọ́ :number',
    'months' => ['Sẹ́rẹ́', 'Èrèlè', 'Ẹrẹ̀nà', 'Ìgbé', 'Èbibi', 'Òkùdu', 'Agẹmo', 'Ògún', 'Owewe', 'Ọ̀wàrà', 'Bélú', 'Ọ̀pẹ̀̀'],
    'months_short' => ['Sẹ́r', 'Èrl', 'Ẹrn', 'Ìgb', 'Èbi', 'Òkù', 'Agẹ', 'Ògú', 'Owe', 'Ọ̀wà', 'Bél', 'Ọ̀pẹ̀̀'],
    'weekdays' => ['Àìkú', 'Ajé', 'Ìsẹ́gun', 'Ọjọ́rú', 'Ọjọ́bọ', 'Ẹtì', 'Àbámẹ́ta'],
    'weekdays_short' => ['Àìk', 'Ajé', 'Ìsẹ́', 'Ọjr', 'Ọjb', 'Ẹtì', 'Àbá'],
    'weekdays_min' => ['Àì', 'Aj', 'Ìs', 'Ọr', 'Ọb', 'Ẹt', 'Àb'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'meridiem' => ['Àárọ̀', 'Ọ̀sán'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ja.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ha.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat, Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D-M-YY',
    ],
    'months' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
    'months_short' => ['जानेवारी', 'फेब्रुवारी', 'मार्च', 'एप्रिल', 'मे', 'जून', 'जुलै', 'ओगस्ट', 'सेप्टेंबर', 'ओक्टोबर', 'नोव्हेंबर', 'डिसेंबर'],
    'weekdays' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
    'weekdays_short' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
    'weekdays_min' => ['आयतार', 'सोमार', 'मंगळवार', 'बुधवार', 'बेरेसतार', 'शुकरार', 'शेनवार'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['म.पू.', 'म.नं.'],

    'year' => ':count वैशाकु', // less reliable
    'y' => ':count वैशाकु', // less reliable
    'a_year' => ':count वैशाकु', // less reliable

    'week' => ':count आदित्यवार', // less reliable
    'w' => ':count आदित्यवार', // less reliable
    'a_week' => ':count आदित्यवार', // less reliable

    'minute' => ':count नोंद', // less reliable
    'min' => ':count नोंद', // less reliable
    'a_minute' => ':count नोंद', // less reliable

    'second' => ':count तेंको', // less reliable
    's' => ':count तेंको', // less reliable
    'a_second' => ':count तेंको', // less reliable

    'month' => ':count मैनो',
    'm' => ':count मैनो',
    'a_month' => ':count मैनो',

    'day' => ':count दिवसु',
    'd' => ':count दिवसु',
    'a_day' => ':count दिवसु',

    'hour' => ':count घंते',
    'h' => ':count घंते',
    'a_hour' => ':count घंते',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ubuntu René Manassé GALEKWA renemanasse@gmail.com
 */
return require __DIR__.'/ln.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/os_RU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Pular-Fulfulde.org Ibrahima Sarr admin@pulaar-fulfulde.org
 */
return require __DIR__.'/ff.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['𑄢𑄧𑄝𑄨𑄝𑄢𑄴', '𑄥𑄧𑄟𑄴𑄝𑄢𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴𑄝𑄢𑄴', '𑄝𑄪𑄖𑄴𑄝𑄢𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴𑄝𑄢𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴𑄝𑄢𑄴', '𑄥𑄧𑄚𑄨𑄝𑄢𑄴'],
    'weekdays_short' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'],
    'weekdays_min' => ['𑄢𑄧𑄝𑄨', '𑄥𑄧𑄟𑄴', '𑄟𑄧𑄁𑄉𑄧𑄣𑄴', '𑄝𑄪𑄖𑄴', '𑄝𑄳𑄢𑄨𑄥𑄪𑄛𑄴', '𑄥𑄪𑄇𑄴𑄇𑄮𑄢𑄴', '𑄥𑄧𑄚𑄨'],
    'months' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄬𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'],
    'months_short' => ['𑄎𑄚𑄪', '𑄜𑄬𑄛𑄴', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄢𑄴'],
    'months_short_standalone' => ['𑄎𑄚𑄪𑄠𑄢𑄨', '𑄜𑄬𑄛𑄴𑄝𑄳𑄢𑄪𑄠𑄢𑄨', '𑄟𑄢𑄴𑄌𑄧', '𑄃𑄬𑄛𑄳𑄢𑄨𑄣𑄴', '𑄟𑄬', '𑄎𑄪𑄚𑄴', '𑄎𑄪𑄣𑄭', '𑄃𑄉𑄧𑄌𑄴𑄑𑄴', '𑄥𑄬𑄛𑄴𑄑𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄃𑄧𑄇𑄴𑄑𑄮𑄝𑄧𑄢𑄴', '𑄚𑄧𑄞𑄬𑄟𑄴𑄝𑄧𑄢𑄴', '𑄓𑄨𑄥𑄬𑄟𑄴𑄝𑄧𑄢𑄴'],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM, YYYY h:mm a',
        'LLLL' => 'dddd, D MMMM, YYYY h:mm a',
    ],
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Carbon\CarbonInterface;

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - pirminis
 * - Tsutomu Kuroda
 * - tjku
 * - Andris Zāģeris
 * - Max Melentiev
 * - Edgars Beigarts
 * - Juanito Fatas
 * - Vitauts Stočka
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Kaspars Bankovskis
 * - Nicolás Hock Isaza
 * - Viesturs Kavacs (Kavacky)
 * - zakse
 * - Janis Eglitis (janiseglitis)
 * - Guntars
 * - Juris Sudmalis
 */
$daysOfWeek = ['svētdiena', 'pirmdiena', 'otrdiena', 'trešdiena', 'ceturtdiena', 'piektdiena', 'sestdiena'];
$daysOfWeekLocativum = ['svētdien', 'pirmdien', 'otrdien', 'trešdien', 'ceturtdien', 'piektdien', 'sestdien'];

$transformDiff = static fn (string $input) => strtr($input, [
    // Nominative => "pirms/pēc" Dative
    'gads' => 'gada',
    'gadi' => 'gadiem',
    'gadu' => 'gadiem',
    'mēnesis' => 'mēneša',
    'mēneši' => 'mēnešiem',
    'mēnešu' => 'mēnešiem',
    'nedēļa' => 'nedēļas',
    'nedēļas' => 'nedēļām',
    'nedēļu' => 'nedēļām',
    'diena' => 'dienas',
    'dienas' => 'dienām',
    'dienu' => 'dienām',
    'stunda' => 'stundas',
    'stundas' => 'stundām',
    'stundu' => 'stundām',
    'minūte' => 'minūtes',
    'minūtes' => 'minūtēm',
    'minūšu' => 'minūtēm',
    'sekunde' => 'sekundes',
    'sekundes' => 'sekundēm',
    'sekunžu' => 'sekundēm',
]);

return [
    'ago' => static fn (string $time) => 'pirms '.$transformDiff($time),
    'from_now' => static fn (string $time) => 'pēc '.$transformDiff($time),

    'year' => '0 gadu|:count gads|:count gadi',
    'y' => ':count g.',
    'a_year' => '{1}gads|0 gadu|:count gads|:count gadi',
    'month' => '0 mēnešu|:count mēnesis|:count mēneši',
    'm' => ':count mēn.',
    'a_month' => '{1}mēnesis|0 mēnešu|:count mēnesis|:count mēneši',
    'week' => '0 nedēļu|:count nedēļa|:count nedēļas',
    'w' => ':count ned.',
    'a_week' => '{1}nedēļa|0 nedēļu|:count nedēļa|:count nedēļas',
    'day' => '0 dienu|:count diena|:count dienas',
    'd' => ':count d.',
    'a_day' => '{1}diena|0 dienu|:count diena|:count dienas',
    'hour' => '0 stundu|:count stunda|:count stundas',
    'h' => ':count st.',
    'a_hour' => '{1}stunda|0 stundu|:count stunda|:count stundas',
    'minute' => '0 minūšu|:count minūte|:count minūtes',
    'min' => ':count min.',
    'a_minute' => '{1}minūte|0 minūšu|:count minūte|:count minūtes',
    'second' => '0 sekunžu|:count sekunde|:count sekundes',
    's' => ':count sek.',
    'a_second' => '{1}sekunde|0 sekunžu|:count sekunde|:count sekundes',

    'after' => ':time vēlāk',
    'year_after' => '0 gadus|:count gadu|:count gadus',
    'a_year_after' => '{1}gadu|0 gadus|:count gadu|:count gadus',
    'month_after' => '0 mēnešus|:count mēnesi|:count mēnešus',
    'a_month_after' => '{1}mēnesi|0 mēnešus|:count mēnesi|:count mēnešus',
    'week_after' => '0 nedēļas|:count nedēļu|:count nedēļas',
    'a_week_after' => '{1}nedēļu|0 nedēļas|:count nedēļu|:count nedēļas',
    'day_after' => '0 dienas|:count dienu|:count dienas',
    'a_day_after' => '{1}dienu|0 dienas|:count dienu|:count dienas',
    'hour_after' => '0 stundas|:count stundu|:count stundas',
    'a_hour_after' => '{1}stundu|0 stundas|:count stundu|:count stundas',
    'minute_after' => '0 minūtes|:count minūti|:count minūtes',
    'a_minute_after' => '{1}minūti|0 minūtes|:count minūti|:count minūtes',
    'second_after' => '0 sekundes|:count sekundi|:count sekundes',
    'a_second_after' => '{1}sekundi|0 sekundes|:count sekundi|:count sekundes',

    'before' => ':time agrāk',
    'year_before' => '0 gadus|:count gadu|:count gadus',
    'a_year_before' => '{1}gadu|0 gadus|:count gadu|:count gadus',
    'month_before' => '0 mēnešus|:count mēnesi|:count mēnešus',
    'a_month_before' => '{1}mēnesi|0 mēnešus|:count mēnesi|:count mēnešus',
    'week_before' => '0 nedēļas|:count nedēļu|:count nedēļas',
    'a_week_before' => '{1}nedēļu|0 nedēļas|:count nedēļu|:count nedēļas',
    'day_before' => '0 dienas|:count dienu|:count dienas',
    'a_day_before' => '{1}dienu|0 dienas|:count dienu|:count dienas',
    'hour_before' => '0 stundas|:count stundu|:count stundas',
    'a_hour_before' => '{1}stundu|0 stundas|:count stundu|:count stundas',
    'minute_before' => '0 minūtes|:count minūti|:count minūtes',
    'a_minute_before' => '{1}minūti|0 minūtes|:count minūti|:count minūtes',
    'second_before' => '0 sekundes|:count sekundi|:count sekundes',
    'a_second_before' => '{1}sekundi|0 sekundes|:count sekundi|:count sekundes',

    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' un '],

    'diff_now' => 'tagad',
    'diff_today' => 'šodien',
    'diff_yesterday' => 'vakar',
    'diff_before_yesterday' => 'aizvakar',
    'diff_tomorrow' => 'rīt',
    'diff_after_tomorrow' => 'parīt',

    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY.',
        'LL' => 'YYYY. [gada] D. MMMM',
        'LLL' => 'DD.MM.YYYY., HH:mm',
        'LLLL' => 'YYYY. [gada] D. MMMM, HH:mm',
    ],

    'calendar' => [
        'sameDay' => '[šodien] [plkst.] LT',
        'nextDay' => '[rīt] [plkst.] LT',
        'nextWeek' => static function (CarbonInterface $current, CarbonInterface $other) use ($daysOfWeekLocativum) {
            if ($current->week !== $other->week) {
                return '[nākošo] ['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT';
            }

            return '['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT';
        },
        'lastDay' => '[vakar] [plkst.] LT',
        'lastWeek' => static function (CarbonInterface $current) use ($daysOfWeekLocativum) {
            return '[pagājušo] ['.$daysOfWeekLocativum[$current->dayOfWeek].'] [plkst.] LT';
        },
        'sameElse' => 'L',
    ],

    'weekdays' => $daysOfWeek,
    'weekdays_short' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'],
    'weekdays_min' => ['Sv.', 'P.', 'O.', 'T.', 'C.', 'Pk.', 'S.'],
    'months' => ['janvāris', 'februāris', 'marts', 'aprīlis', 'maijs', 'jūnijs', 'jūlijs', 'augusts', 'septembris', 'oktobris', 'novembris', 'decembris'],
    'months_standalone' => ['janvārī', 'februārī', 'martā', 'aprīlī', 'maijā', 'jūnijā', 'jūlijā', 'augustā', 'septembrī', 'oktobrī', 'novembrī', 'decembrī'],
    'months_short' => ['janv.', 'febr.', 'martā', 'apr.', 'maijā', 'jūn.', 'jūl.', 'aug.', 'sept.', 'okt.', 'nov.', 'dec.'],
    'meridiem' => ['priekšpusdiena', 'pēcpusdiena'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/wa_BE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kamusi Project Martin Benjamin locales@kamusi.org
 */
return array_replace_recursive(require __DIR__.'/sw.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Jumapili', 'Jumatatu', 'Jumanne', 'Jumatano', 'Alhamisi', 'Ijumaa', 'Jumamosi'],
    'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
    'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Alh', 'Ij', 'J1'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['asubuhi', 'alasiri'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['kang’ama', 'kingoto'],
    'weekdays' => ['Ijumapili', 'Ijumatatu', 'Ijumanne', 'Ijumatano', 'Alhamisi', 'Ijumaa', 'Ijumamosi'],
    'weekdays_short' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
    'weekdays_min' => ['Ijp', 'Ijt', 'Ijn', 'Ijtn', 'Alh', 'Iju', 'Ijm'],
    'months' => ['Mweri wa kwanza', 'Mweri wa kaili', 'Mweri wa katatu', 'Mweri wa kaana', 'Mweri wa tanu', 'Mweri wa sita', 'Mweri wa saba', 'Mweri wa nane', 'Mweri wa tisa', 'Mweri wa ikumi', 'Mweri wa ikumi na moja', 'Mweri wa ikumi na mbili'],
    'months_short' => ['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'months' => ['ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'],
    'months_short' => ['ינו׳', 'פבר׳', 'מרץ', 'אפר׳', 'מאי', 'יוני', 'יולי', 'אוג׳', 'ספט׳', 'אוק׳', 'נוב׳', 'דצמ׳'],
    'weekdays' => ['יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'יום שבת'],
    'weekdays_short' => ['יום א׳', 'יום ב׳', 'יום ג׳', 'יום ד׳', 'יום ה׳', 'יום ו׳', 'שבת'],
    'weekdays_min' => ['א׳', 'ב׳', 'ג׳', 'ד׳', 'ה׳', 'ו׳', 'ש׳'],
    'meridiem' => ['לפנה״צ', 'אחה״צ'],
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'D.M.YYYY',
        'LL' => 'D בMMM YYYY',
        'LLL' => 'D בMMMM YYYY H:mm',
        'LLLL' => 'dddd, D בMMMM YYYY H:mm',
    ],

    'year' => ':count שנה',
    'y' => ':count שנה',
    'a_year' => ':count שנה',

    'month' => ':count חודש',
    'm' => ':count חודש',
    'a_month' => ':count חודש',

    'week' => ':count שבוע',
    'w' => ':count שבוע',
    'a_week' => ':count שבוע',

    'day' => ':count יום',
    'd' => ':count יום',
    'a_day' => ':count יום',

    'hour' => ':count שעה',
    'h' => ':count שעה',
    'a_hour' => ':count שעה',

    'minute' => ':count דקה',
    'min' => ':count דקה',
    'a_minute' => ':count דקה',

    'second' => ':count שניה',
    's' => ':count שניה',
    'a_second' => ':count שניה',

    'ago' => 'לפני :time',
    'from_now' => 'בעוד :time',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/se.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/chr_US.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ms.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/MM/yy',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY, h:mm a',
        'LLLL' => 'dddd, D MMMM YYYY, h:mm a',
    ],
    'meridiem' => ['a', 'p'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Bari Badamshin
 * - Jørn Ølmheim
 * - François B
 * - Tim Fish
 * - Коренберг Марк (imac)
 * - Serhan Apaydın
 * - RomeroMsk
 * - vsn4ik
 * - JD Isaacks
 * - Bari Badamshin
 * - Jørn Ølmheim
 * - François B
 * - Коренберг Марк (imac)
 * - Serhan Apaydın
 * - RomeroMsk
 * - vsn4ik
 * - JD Isaacks
 * - Fellzo
 * - andrey-helldar
 * - Pavel Skripkin (psxx)
 * - AlexWalkerson
 * - Vladislav UnsealedOne
 * - dima-bzz
 * - Sergey Danilchenko
 */

use Carbon\CarbonInterface;

$transformDiff = static fn (string $input) => strtr($input, [
    'неделя' => 'неделю',
    'секунда' => 'секунду',
    'минута' => 'минуту',
]);

return [
    'year' => ':count год|:count года|:count лет',
    'y' => ':count г.|:count г.|:count л.',
    'a_year' => '{1}год|:count год|:count года|:count лет',
    'month' => ':count месяц|:count месяца|:count месяцев',
    'm' => ':count мес.',
    'a_month' => '{1}месяц|:count месяц|:count месяца|:count месяцев',
    'week' => ':count неделя|:count недели|:count недель',
    'w' => ':count нед.',
    'a_week' => '{1}неделя|:count неделю|:count недели|:count недель',
    'day' => ':count день|:count дня|:count дней',
    'd' => ':count д.',
    'a_day' => '{1}день|:count день|:count дня|:count дней',
    'hour' => ':count час|:count часа|:count часов',
    'h' => ':count ч.',
    'a_hour' => '{1}час|:count час|:count часа|:count часов',
    'minute' => ':count минута|:count минуты|:count минут',
    'min' => ':count мин.',
    'a_minute' => '{1}минута|:count минута|:count минуты|:count минут',
    'second' => ':count секунда|:count секунды|:count секунд',
    's' => ':count сек.',
    'a_second' => '{1}несколько секунд|:count секунду|:count секунды|:count секунд',
    'millisecond' => '{1}:count миллисекунда|:count миллисекунды|:count миллисекунд',
    'a_millisecond' => '{1}миллисекунда|:count миллисекунда|:count миллисекунды|:count миллисекунд',
    'ms' => ':count мс',
    'microsecond' => '{1}:count микросекунда|:count микросекунды|:count микросекунд',
    'a_microsecond' => '{1}микросекунда|:count микросекунда|:count микросекунды|:count микросекунд',
    'ago' => static fn (string $time) => $transformDiff($time).' назад',
    'from_now' => static fn (string $time) => 'через '.$transformDiff($time),
    'after' => static fn (string $time) => $transformDiff($time).' после',
    'before' => static fn (string $time) => $transformDiff($time).' до',
    'diff_now' => 'только что',
    'diff_today' => 'Сегодня,',
    'diff_today_regexp' => 'Сегодня,?(?:\\s+в)?',
    'diff_yesterday' => 'вчера',
    'diff_yesterday_regexp' => 'Вчера,?(?:\\s+в)?',
    'diff_tomorrow' => 'завтра',
    'diff_tomorrow_regexp' => 'Завтра,?(?:\\s+в)?',
    'diff_before_yesterday' => 'позавчера',
    'diff_after_tomorrow' => 'послезавтра',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY г.',
        'LLL' => 'D MMMM YYYY г., H:mm',
        'LLLL' => 'dddd, D MMMM YYYY г., H:mm',
    ],
    'calendar' => [
        'sameDay' => '[Сегодня, в] LT',
        'nextDay' => '[Завтра, в] LT',
        'nextWeek' => static function (CarbonInterface $current, \Carbon\CarbonInterface $other) {
            if ($current->week !== $other->week) {
                switch ($current->dayOfWeek) {
                    case 0:
                        return '[В следующее] dddd, [в] LT';
                    case 1:
                    case 2:
                    case 4:
                        return '[В следующий] dddd, [в] LT';
                    case 3:
                    case 5:
                    case 6:
                        return '[В следующую] dddd, [в] LT';
                }
            }

            if ($current->dayOfWeek === 2) {
                return '[Во] dddd, [в] LT';
            }

            return '[В] dddd, [в] LT';
        },
        'lastDay' => '[Вчера, в] LT',
        'lastWeek' => static function (CarbonInterface $current, \Carbon\CarbonInterface $other) {
            if ($current->week !== $other->week) {
                switch ($current->dayOfWeek) {
                    case 0:
                        return '[В прошлое] dddd, [в] LT';
                    case 1:
                    case 2:
                    case 4:
                        return '[В прошлый] dddd, [в] LT';
                    case 3:
                    case 5:
                    case 6:
                        return '[В прошлую] dddd, [в] LT';
                }
            }

            if ($current->dayOfWeek === 2) {
                return '[Во] dddd, [в] LT';
            }

            return '[В] dddd, [в] LT';
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            'M', 'd', 'DDD' => $number.'-й',
            'D' => $number.'-го',
            'w', 'W' => $number.'-я',
            default => $number,
        };
    },
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'ночи';
        }
        if ($hour < 12) {
            return 'утра';
        }
        if ($hour < 17) {
            return 'дня';
        }

        return 'вечера';
    },
    'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
    'months_standalone' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    'months_short' => ['янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'months_short_standalone' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу'],
    'weekdays_standalone' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
    'weekdays_short' => ['вск', 'пнд', 'втр', 'срд', 'чтв', 'птн', 'сбт'],
    'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    'weekdays_regexp' => '/\[\s*(В|в)\s*((?:прошлую|следующую|эту)\s*)?\]\s*dddd/',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' и '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/om.php', [
    'day_of_first_week_of_year' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'weekdays' => ['Jumapiri', 'Jumatatu', 'Jumanne', 'Jumatano', 'Murwa wa Kanne', 'Murwa wa Katano', 'Jumamosi'],
    'weekdays_short' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
    'weekdays_min' => ['J2', 'J3', 'J4', 'J5', 'Al', 'Ij', 'J1'],
    'months' => ['Januari', 'Februari', 'Machi', 'Aprili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],

    // Too unreliable
    /*
    'year' => ':count liliino', // less reliable
    'y' => ':count liliino', // less reliable
    'a_year' => ':count liliino', // less reliable

    'month' => ':count kumwesi', // less reliable
    'm' => ':count kumwesi', // less reliable
    'a_month' => ':count kumwesi', // less reliable

    'week' => ':count olutambi', // less reliable
    'w' => ':count olutambi', // less reliable
    'a_week' => ':count olutambi', // less reliable

    'day' => ':count luno', // less reliable
    'd' => ':count luno', // less reliable
    'a_day' => ':count luno', // less reliable

    'hour' => ':count ekengele', // less reliable
    'h' => ':count ekengele', // less reliable
    'a_hour' => ':count ekengele', // less reliable

    'minute' => ':count omundu', // less reliable
    'min' => ':count omundu', // less reliable
    'a_minute' => ':count omundu', // less reliable

    'second' => ':count liliino', // less reliable
    's' => ':count liliino', // less reliable
    'a_second' => ':count liliino', // less reliable
    */
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Maithili Computing Research Center, Pune, India    rajeshkajha@yahoo.com,akhilesh.k@samusng.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'],
    'months_short' => ['बैसाख', 'जेठ', 'अषाढ़', 'सावोन', 'भादो', 'आसिन', 'कातिक', 'अगहन', 'पूस', 'माघ', 'फागुन', 'चैति'],
    'weekdays' => ['रविदिन', 'सोमदिन', 'मंगलदिन', 'बुधदिन', 'बृहस्पतीदिन', 'शुक्रदिन', 'शनीदिन'],
    'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'],
    'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'बृहस्पती', 'शुक्र', 'शनी'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],

    'year' => ':count ऋतु', // less reliable
    'y' => ':count ऋतु', // less reliable
    'a_year' => ':count ऋतु', // less reliable

    'month' => ':count महिना',
    'm' => ':count महिना',
    'a_month' => ':count महिना',

    'week' => ':count श्रेणी:क्यालेन्डर', // less reliable
    'w' => ':count श्रेणी:क्यालेन्डर', // less reliable
    'a_week' => ':count श्रेणी:क्यालेन्डर', // less reliable

    'day' => ':count दिन',
    'd' => ':count दिन',
    'a_day' => ':count दिन',

    'hour' => ':count घण्टा',
    'h' => ':count घण्टा',
    'a_hour' => ':count घण्टा',

    'minute' => ':count समय', // less reliable
    'min' => ':count समय', // less reliable
    'a_minute' => ':count समय', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'sr');
    }, 'sr_Cyrl_BA');
}
// @codeCoverageIgnoreEnd

return array_replace_recursive(require __DIR__.'/sr_Cyrl.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D.M.yy.',
        'LL' => 'DD.MM.YYYY.',
        'LLL' => 'DD. MMMM YYYY. HH:mm',
        'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
    ],
    'weekdays' => ['недјеља', 'понедељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
    'weekdays_short' => ['нед.', 'пон.', 'ут.', 'ср.', 'чет.', 'пет.', 'суб.'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Samsung Electronics Co., Ltd.    akhilesh.k@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Ianuari', 'Fepuari', 'Mati', 'Aperila', 'Me', 'Iuni', 'Iulai', 'Auguso', 'Setema', 'Oketopa', 'Novema', 'Tesema'],
    'months_short' => ['Ian', 'Fep', 'Mat', 'Ape', 'Me', 'Iun', 'Iul', 'Aug', 'Set', 'Oke', 'Nov', 'Tes'],
    'weekdays' => ['Aso Sa', 'Aso Gafua', 'Aso Lua', 'Aso Lulu', 'Aso Tofi', 'Aso Farail', 'Aso To\'ana\'i'],
    'weekdays_short' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''],
    'weekdays_min' => ['Aso Sa', 'Aso Gaf', 'Aso Lua', 'Aso Lul', 'Aso Tof', 'Aso Far', 'Aso To\''],

    'hour' => ':count uati', // less reliable
    'h' => ':count uati', // less reliable
    'a_hour' => ':count uati', // less reliable

    'minute' => ':count itiiti', // less reliable
    'min' => ':count itiiti', // less reliable
    'a_minute' => ':count itiiti', // less reliable

    'second' => ':count lua', // less reliable
    's' => ':count lua', // less reliable
    'a_second' => ':count lua', // less reliable

    'year' => ':count tausaga',
    'y' => ':count tausaga',
    'a_year' => ':count tausaga',

    'month' => ':count māsina',
    'm' => ':count māsina',
    'a_month' => ':count māsina',

    'week' => ':count vaiaso',
    'w' => ':count vaiaso',
    'a_week' => ':count vaiaso',

    'day' => ':count aso',
    'd' => ':count aso',
    'a_day' => ':count aso',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/lb.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/my.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - Alan Agius
 * - Erhan Gundogan
 * - François B
 * - JD Isaacks
 * - Murat Yüksel
 * - Baran Şengül
 * - Selami (selamialtin)
 * - TeomanBey
 */
return [
    'year' => ':count yıl',
    'a_year' => '{1}bir yıl|[-Inf,Inf]:count yıl',
    'y' => ':county',
    'month' => ':count ay',
    'a_month' => '{1}bir ay|[-Inf,Inf]:count ay',
    'm' => ':countay',
    'week' => ':count hafta',
    'a_week' => '{1}bir hafta|[-Inf,Inf]:count hafta',
    'w' => ':counth',
    'day' => ':count gün',
    'a_day' => '{1}bir gün|[-Inf,Inf]:count gün',
    'd' => ':countg',
    'hour' => ':count saat',
    'a_hour' => '{1}bir saat|[-Inf,Inf]:count saat',
    'h' => ':countsa',
    'minute' => ':count dakika',
    'a_minute' => '{1}bir dakika|[-Inf,Inf]:count dakika',
    'min' => ':countdk',
    'second' => ':count saniye',
    'a_second' => '{1}birkaç saniye|[-Inf,Inf]:count saniye',
    's' => ':countsn',
    'ago' => ':time önce',
    'from_now' => ':time sonra',
    'after' => ':time sonra',
    'before' => ':time önce',
    'diff_now' => 'şimdi',
    'diff_today' => 'bugün',
    'diff_today_regexp' => 'bugün(?:\\s+saat)?',
    'diff_yesterday' => 'dün',
    'diff_tomorrow' => 'yarın',
    'diff_tomorrow_regexp' => 'yarın(?:\\s+saat)?',
    'diff_before_yesterday' => 'evvelsi gün',
    'diff_after_tomorrow' => 'öbür gün',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[bugün saat] LT',
        'nextDay' => '[yarın saat] LT',
        'nextWeek' => '[gelecek] dddd [saat] LT',
        'lastDay' => '[dün] LT',
        'lastWeek' => '[geçen] dddd [saat] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number, $period) {
        switch ($period) {
            case 'd':
            case 'D':
            case 'Do':
            case 'DD':
                return $number;
            default:
                if ($number === 0) {  // special case for zero
                    return "$number'ıncı";
                }

                static $suffixes = [
                    1 => '\'inci',
                    5 => '\'inci',
                    8 => '\'inci',
                    70 => '\'inci',
                    80 => '\'inci',
                    2 => '\'nci',
                    7 => '\'nci',
                    20 => '\'nci',
                    50 => '\'nci',
                    3 => '\'üncü',
                    4 => '\'üncü',
                    100 => '\'üncü',
                    6 => '\'ncı',
                    9 => '\'uncu',
                    10 => '\'uncu',
                    30 => '\'uncu',
                    60 => '\'ıncı',
                    90 => '\'ıncı',
                ];

                $lastDigit = $number % 10;

                return $number.($suffixes[$lastDigit] ?? $suffixes[$number % 100 - $lastDigit] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
        }
    },
    'meridiem' => ['ÖÖ', 'ÖS', 'öö', 'ös'],
    'months' => ['Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık'],
    'months_short' => ['Oca', 'Şub', 'Mar', 'Nis', 'May', 'Haz', 'Tem', 'Ağu', 'Eyl', 'Eki', 'Kas', 'Ara'],
    'weekdays' => ['Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'],
    'weekdays_short' => ['Paz', 'Pts', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'],
    'weekdays_min' => ['Pz', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' ve '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - information from native speaker Pablo Saratxaga pablo@mandrakesoft.com
 */
return require __DIR__.'/pap.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Greek Debian Translation Team    bug-glibc@gnu.org
 */
return array_replace_recursive(require __DIR__.'/el.php', [
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/doi_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Akademe ya Luganda Kizito Birabwa kompyuta@kizito.uklinux.net
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
    'weekdays' => ['Sabiiti', 'Balaza', 'Lwakubiri', 'Lwakusatu', 'Lwakuna', 'Lwakutaano', 'Lwamukaaga'],
    'weekdays_short' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
    'weekdays_min' => ['Sab', 'Bal', 'Lw2', 'Lw3', 'Lw4', 'Lw5', 'Lw6'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'month' => ':count njuba', // less reliable
    'm' => ':count njuba', // less reliable
    'a_month' => ':count njuba', // less reliable

    'year' => ':count mwaaka',
    'y' => ':count mwaaka',
    'a_year' => ':count mwaaka',

    'week' => ':count sabbiiti',
    'w' => ':count sabbiiti',
    'a_week' => ':count sabbiiti',

    'day' => ':count lunaku',
    'd' => ':count lunaku',
    'a_day' => ':count lunaku',

    'hour' => 'saawa :count',
    'h' => 'saawa :count',
    'a_hour' => 'saawa :count',

    'minute' => 'ddakiika :count',
    'min' => 'ddakiika :count',
    'a_minute' => 'ddakiika :count',

    'second' => ':count kyʼokubiri',
    's' => ':count kyʼokubiri',
    'a_second' => ':count kyʼokubiri',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sq.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Pablo Saratxaga pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/az.php', [
    'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
    'weekdays' => ['bazar günü', 'bazar ertəsi', 'çərşənbə axşamı', 'çərşənbə', 'cümə axşamı', 'cümə', 'şənbə'],
    'weekdays_short' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'],
    'weekdays_min' => ['baz', 'ber', 'çax', 'çər', 'cax', 'cüm', 'şnb'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Authors:
 * - Ghorban M. Tavakoly Pablo Saratxaga & Ghorban M. Tavakoly pablo@walon.org & gmt314@yahoo.com
 * - SuperManPHP
 * - Maksat Meredow (isadma)
 */
$transformDiff = static fn (string $input) => strtr($input, [
    'sekunt' => 'sekunt',
    'hepde' => 'hepde',
]);

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Ýanwar', 'Fewral', 'Mart', 'Aprel', 'Maý', 'Iýun', 'Iýul', 'Awgust', 'Sentýabr', 'Oktýabr', 'Noýabr', 'Dekabr'],
    'months_short' => ['Ýan', 'Few', 'Mar', 'Apr', 'Maý', 'Iýn', 'Iýl', 'Awg', 'Sen', 'Okt', 'Noý', 'Dek'],
    'weekdays' => ['Ýekşenbe', 'Duşenbe', 'Sişenbe', 'Çarşenbe', 'Penşenbe', 'Anna', 'Şenbe'],
    'weekdays_short' => ['Ýek', 'Duş', 'Siş', 'Çar', 'Pen', 'Ann', 'Şen'],
    'weekdays_min' => ['Ýe', 'Du', 'Si', 'Ça', 'Pe', 'An', 'Şe'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => ':count ýyl',
    'y' => ':count ýyl',
    'a_year' => ':count ýyl',

    'month' => ':count aý',
    'm' => ':count aý',
    'a_month' => ':count aý',

    'week' => ':count hepde',
    'w' => ':count hepde',
    'a_week' => ':count hepde',

    'day' => ':count gün',
    'd' => ':count gün',
    'a_day' => ':count gün',

    'hour' => ':count sagat',
    'h' => ':count sagat',
    'a_hour' => ':count sagat',

    'minute' => ':count minut',
    'min' => ':count minut',
    'a_minute' => ':count minut',

    'second' => ':count sekunt',
    's' => ':count sekunt',
    'a_second' => ':count sekunt',

    'ago' => static fn (string $time) => $transformDiff($time).' ozal',
    'from_now' => static fn (string $time) => $transformDiff($time).' soňra',
    'after' => static fn (string $time) => $transformDiff($time).' soň',
    'before' => static fn (string $time) => $transformDiff($time).' öň',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Andres Ivanov
 * - Tsutomu Kuroda
 * - tjku
 * - Max Melentiev
 * - Juanito Fatas
 * - RM87
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Esko Lehtme
 * - Mart Karu
 * - Nicolás Hock Isaza
 * - Kevin Valdek
 * - Zahhar Kirillov
 * - João Magalhães
 * - Ingmar
 * - Illimar Tambek
 * - Mihkel
 */
return [
    'year' => ':count aasta|:count aastat',
    'y' => ':count a',
    'month' => ':count kuu|:count kuud',
    'm' => ':count k',
    'week' => ':count nädal|:count nädalat',
    'w' => ':count näd',
    'day' => ':count päev|:count päeva',
    'd' => ':count p',
    'hour' => ':count tund|:count tundi',
    'h' => ':count t',
    'minute' => ':count minut|:count minutit',
    'min' => ':count min',
    'second' => ':count sekund|:count sekundit',
    's' => ':count s',
    'ago' => ':time tagasi',
    'from_now' => ':time pärast',
    'after' => ':time pärast',
    'before' => ':time enne',
    'year_from_now' => ':count aasta',
    'month_from_now' => ':count kuu',
    'week_from_now' => ':count nädala',
    'day_from_now' => ':count päeva',
    'hour_from_now' => ':count tunni',
    'minute_from_now' => ':count minuti',
    'second_from_now' => ':count sekundi',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'diff_now' => 'nüüd',
    'diff_today' => 'täna',
    'diff_yesterday' => 'eile',
    'diff_tomorrow' => 'homme',
    'diff_before_yesterday' => 'üleeile',
    'diff_after_tomorrow' => 'ülehomme',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D. MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[täna] LT',
        'nextDay' => '[homme] LT',
        'lastDay' => '[eile] LT',
        'nextWeek' => 'dddd LT',
        'lastWeek' => '[eelmine] dddd LT',
        'sameElse' => 'L',
    ],
    'months' => ['jaanuar', 'veebruar', 'märts', 'aprill', 'mai', 'juuni', 'juuli', 'august', 'september', 'oktoober', 'november', 'detsember'],
    'months_short' => ['jaan', 'veebr', 'märts', 'apr', 'mai', 'juuni', 'juuli', 'aug', 'sept', 'okt', 'nov', 'dets'],
    'weekdays' => ['pühapäev', 'esmaspäev', 'teisipäev', 'kolmapäev', 'neljapäev', 'reede', 'laupäev'],
    'weekdays_short' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    'weekdays_min' => ['P', 'E', 'T', 'K', 'N', 'R', 'L'],
    'list' => [', ', ' ja '],
    'meridiem' => ['enne lõunat', 'pärast lõunat'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/csb_PL.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sm_WS.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
    'months_short' => ['Qun', 'Kud', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
    'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
    'weekdays_short' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    'weekdays_min' => ['Aca', 'Etl', 'Tal', 'Arb', 'Kam', 'Gum', 'Sab'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['saaku', 'carra'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/el.php', [
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ku.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Atef Ben Ali (atefBB)
 * - Ibrahim AshShohail
 * - MLTDev
 */

$months = [
    'يناير',
    'فبراير',
    'مارس',
    'أبريل',
    'مايو',
    'يونيو',
    'يوليو',
    'أغسطس',
    'سبتمبر',
    'أكتوبر',
    'نوفمبر',
    'ديسمبر',
];

return [
    'year' => implode('|', [':count سنة', 'سنة', 'سنتين', ':count سنوات', ':count سنة']),
    'a_year' => implode('|', [':count سنة', 'سنة', 'سنتين', ':count سنوات', ':count سنة']),
    'month' => implode('|', [':count شهر', 'شهر', 'شهرين', ':count أشهر', ':count شهر']),
    'a_month' => implode('|', [':count شهر', 'شهر', 'شهرين', ':count أشهر', ':count شهر']),
    'week' => implode('|', [':count أسبوع', 'أسبوع', 'أسبوعين', ':count أسابيع', ':count أسبوع']),
    'a_week' => implode('|', [':count أسبوع', 'أسبوع', 'أسبوعين', ':count أسابيع', ':count أسبوع']),
    'day' => implode('|', [':count يوم', 'يوم', 'يومين', ':count أيام', ':count يوم']),
    'a_day' => implode('|', [':count يوم', 'يوم', 'يومين', ':count أيام', ':count يوم']),
    'hour' => implode('|', [':count ساعة', 'ساعة', 'ساعتين', ':count ساعات', ':count ساعة']),
    'a_hour' => implode('|', [':count ساعة', 'ساعة', 'ساعتين', ':count ساعات', ':count ساعة']),
    'minute' => implode('|', [':count دقيقة', 'دقيقة', 'دقيقتين', ':count دقائق', ':count دقيقة']),
    'a_minute' => implode('|', [':count دقيقة', 'دقيقة', 'دقيقتين', ':count دقائق', ':count دقيقة']),
    'second' => implode('|', [':count ثانية', 'ثانية', 'ثانيتين', ':count ثواني', ':count ثانية']),
    'a_second' => implode('|', [':count ثانية', 'ثانية', 'ثانيتين', ':count ثواني', ':count ثانية']),
    'ago' => 'منذ :time',
    'from_now' => ':time من الآن',
    'after' => 'بعد :time',
    'before' => 'قبل :time',
    'diff_now' => 'الآن',
    'diff_today' => 'اليوم',
    'diff_today_regexp' => 'اليوم(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_yesterday' => 'أمس',
    'diff_yesterday_regexp' => 'أمس(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_tomorrow' => 'غداً',
    'diff_tomorrow_regexp' => 'غدًا(?:\\s+عند)?(?:\\s+الساعة)?',
    'diff_before_yesterday' => 'قبل الأمس',
    'diff_after_tomorrow' => 'بعد غد',
    'period_recurrences' => implode('|', ['مرة', 'مرة', ':count مرتين', ':count مرات', ':count مرة']),
    'period_interval' => 'كل :interval',
    'period_start_date' => 'من :date',
    'period_end_date' => 'إلى :date',
    'months' => $months,
    'months_short' => $months,
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت'],
    'weekdays_min' => ['ح', 'اث', 'ثل', 'أر', 'خم', 'ج', 'س'],
    'list' => ['، ', ' و '],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[اليوم عند الساعة] LT',
        'nextDay' => '[غدًا عند الساعة] LT',
        'nextWeek' => 'dddd [عند الساعة] LT',
        'lastDay' => '[أمس عند الساعة] LT',
        'lastWeek' => 'dddd [عند الساعة] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ص', 'م'],
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/agr_PE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/zh_HK.php', [
    'formats' => [
        'L' => 'YYYY年MM月DD日 dddd',
    ],
    'months' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    'months_short' => ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['上午', '下午'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Alessandro Di Felice
 * - François B
 * - Tim Fish
 * - Gabriel Monteagudo
 * - JD Isaacks
 * - yiannisdesp
 * - Ilias Kasmeridis (iliaskasm)
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count χρόνος|:count χρόνια',
    'a_year' => 'ένας χρόνος|:count χρόνια',
    'y' => ':count χρ.',
    'month' => ':count μήνας|:count μήνες',
    'a_month' => 'ένας μήνας|:count μήνες',
    'm' => ':count μήν.',
    'week' => ':count εβδομάδα|:count εβδομάδες',
    'a_week' => 'μια εβδομάδα|:count εβδομάδες',
    'w' => ':count εβδ.',
    'day' => ':count μέρα|:count μέρες',
    'a_day' => 'μία μέρα|:count μέρες',
    'd' => ':count μέρ.',
    'hour' => ':count ώρα|:count ώρες',
    'a_hour' => 'μία ώρα|:count ώρες',
    'h' => ':count ώρα|:count ώρες',
    'minute' => ':count λεπτό|:count λεπτά',
    'a_minute' => 'ένα λεπτό|:count λεπτά',
    'min' => ':count λεπ.',
    'second' => ':count δευτερόλεπτο|:count δευτερόλεπτα',
    'a_second' => 'λίγα δευτερόλεπτα|:count δευτερόλεπτα',
    's' => ':count δευ.',

    'ago' => 'πριν :time',
    'from_now' => 'σε :time',
    'after' => ':time μετά',
    'before' => ':time πριν',

    'year_ago' => ':count χρόνο|:count χρόνια',
    'year_from_now' => ':count χρόνο|:count χρόνια',
    'month_ago' => ':count μήνα|:count μήνες',
    'month_from_now' => ':count μήνα|:count μήνες',

    'diff_now' => 'τώρα',
    'diff_today' => 'Σήμερα',
    'diff_today_regexp' => 'Σήμερα(?:\\s+{})?',
    'diff_yesterday' => 'χθες',
    'diff_yesterday_regexp' => 'Χθες(?:\\s+{})?',
    'diff_tomorrow' => 'αύριο',
    'diff_tomorrow_regexp' => 'Αύριο(?:\\s+{})?',

    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm A',
        'LLLL' => 'dddd, D MMMM YYYY h:mm A',
    ],
    'calendar' => [
        'sameDay' => '[Σήμερα {}] LT',
        'nextDay' => '[Αύριο {}] LT',
        'nextWeek' => 'dddd [{}] LT',
        'lastDay' => '[Χθες {}] LT',
        'lastWeek' => static fn (CarbonInterface $current) => match ($current->dayOfWeek) {
            6 => '[το προηγούμενο] dddd [{}] LT',
            default => '[την προηγούμενη] dddd [{}] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberη',
    'meridiem' => ['ΠΜ', 'ΜΜ', 'πμ', 'μμ'],
    'months' => ['Ιανουαρίου', 'Φεβρουαρίου', 'Μαρτίου', 'Απριλίου', 'Μαΐου', 'Ιουνίου', 'Ιουλίου', 'Αυγούστου', 'Σεπτεμβρίου', 'Οκτωβρίου', 'Νοεμβρίου', 'Δεκεμβρίου'],
    'months_standalone' => ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'],
    'months_regexp' => '/(D[oD]?[\s,]+MMMM|L{2,4}|l{2,4})/',
    'months_short' => ['Ιαν', 'Φεβ', 'Μαρ', 'Απρ', 'Μαϊ', 'Ιουν', 'Ιουλ', 'Αυγ', 'Σεπ', 'Οκτ', 'Νοε', 'Δεκ'],
    'weekdays' => ['Κυριακή', 'Δευτέρα', 'Τρίτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σάββατο'],
    'weekdays_short' => ['Κυρ', 'Δευ', 'Τρι', 'Τετ', 'Πεμ', 'Παρ', 'Σαβ'],
    'weekdays_min' => ['Κυ', 'Δε', 'Τρ', 'Τε', 'Πε', 'Πα', 'Σα'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' και '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['a.g', 'a.k'],
    'weekdays' => ['tsuʔntsɨ', 'tsuʔukpà', 'tsuʔughɔe', 'tsuʔutɔ̀mlò', 'tsuʔumè', 'tsuʔughɨ̂m', 'tsuʔndzɨkɔʔɔ'],
    'weekdays_short' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
    'weekdays_min' => ['nts', 'kpa', 'ghɔ', 'tɔm', 'ume', 'ghɨ', 'dzk'],
    'months' => ['ndzɔ̀ŋɔ̀nùm', 'ndzɔ̀ŋɔ̀kƗ̀zùʔ', 'ndzɔ̀ŋɔ̀tƗ̀dʉ̀ghà', 'ndzɔ̀ŋɔ̀tǎafʉ̄ghā', 'ndzɔ̀ŋèsèe', 'ndzɔ̀ŋɔ̀nzùghò', 'ndzɔ̀ŋɔ̀dùmlo', 'ndzɔ̀ŋɔ̀kwîfɔ̀e', 'ndzɔ̀ŋɔ̀tƗ̀fʉ̀ghàdzughù', 'ndzɔ̀ŋɔ̀ghǔuwelɔ̀m', 'ndzɔ̀ŋɔ̀chwaʔàkaa wo', 'ndzɔ̀ŋèfwòo'],
    'months_short' => ['nùm', 'kɨz', 'tɨd', 'taa', 'see', 'nzu', 'dum', 'fɔe', 'dzu', 'lɔm', 'kaa', 'fwo'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/nan_TW.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - Kaushik Thanki
 * - Josh Soref
 */
return [
    'year' => 'એક વર્ષ|:count વર્ષ',
    'y' => ':countવર્ષ|:countવર્ષો',
    'month' => 'એક મહિનો|:count મહિના',
    'm' => ':countમહિનો|:countમહિના',
    'week' => ':count અઠવાડિયું|:count અઠવાડિયા',
    'w' => ':countઅઠ.|:countઅઠ.',
    'day' => 'એક દિવસ|:count દિવસ',
    'd' => ':countદિ.|:countદિ.',
    'hour' => 'એક કલાક|:count કલાક',
    'h' => ':countક.|:countક.',
    'minute' => 'એક મિનિટ|:count મિનિટ',
    'min' => ':countમિ.|:countમિ.',
    'second' => 'અમુક પળો|:count સેકંડ',
    's' => ':countસે.|:countસે.',
    'ago' => ':time પેહલા',
    'from_now' => ':time મા',
    'after' => ':time પછી',
    'before' => ':time પહેલા',
    'diff_now' => 'હમણાં',
    'diff_today' => 'આજ',
    'diff_yesterday' => 'ગઇકાલે',
    'diff_tomorrow' => 'કાલે',
    'formats' => [
        'LT' => 'A h:mm વાગ્યે',
        'LTS' => 'A h:mm:ss વાગ્યે',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm વાગ્યે',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm વાગ્યે',
    ],
    'calendar' => [
        'sameDay' => '[આજ] LT',
        'nextDay' => '[કાલે] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[ગઇકાલે] LT',
        'lastWeek' => '[પાછલા] dddd, LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'રાત';
        }
        if ($hour < 10) {
            return 'સવાર';
        }
        if ($hour < 17) {
            return 'બપોર';
        }
        if ($hour < 20) {
            return 'સાંજ';
        }

        return 'રાત';
    },
    'months' => ['જાન્યુઆરી', 'ફેબ્રુઆરી', 'માર્ચ', 'એપ્રિલ', 'મે', 'જૂન', 'જુલાઈ', 'ઑગસ્ટ', 'સપ્ટેમ્બર', 'ઑક્ટ્બર', 'નવેમ્બર', 'ડિસેમ્બર'],
    'months_short' => ['જાન્યુ.', 'ફેબ્રુ.', 'માર્ચ', 'એપ્રિ.', 'મે', 'જૂન', 'જુલા.', 'ઑગ.', 'સપ્ટે.', 'ઑક્ટ્.', 'નવે.', 'ડિસે.'],
    'weekdays' => ['રવિવાર', 'સોમવાર', 'મંગળવાર', 'બુધ્વાર', 'ગુરુવાર', 'શુક્રવાર', 'શનિવાર'],
    'weekdays_short' => ['રવિ', 'સોમ', 'મંગળ', 'બુધ્', 'ગુરુ', 'શુક્ર', 'શનિ'],
    'weekdays_min' => ['ર', 'સો', 'મં', 'બુ', 'ગુ', 'શુ', 'શ'],
    'list' => [', ', ' અને '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - Punjab
 */
return [
    'year' => 'ਇੱਕ ਸਾਲ|:count ਸਾਲ',
    'month' => 'ਇੱਕ ਮਹੀਨਾ|:count ਮਹੀਨੇ',
    'week' => 'ਹਫਤਾ|:count ਹਫ਼ਤੇ',
    'day' => 'ਇੱਕ ਦਿਨ|:count ਦਿਨ',
    'hour' => 'ਇੱਕ ਘੰਟਾ|:count ਘੰਟੇ',
    'minute' => 'ਇਕ ਮਿੰਟ|:count ਮਿੰਟ',
    'second' => 'ਕੁਝ ਸਕਿੰਟ|:count ਸਕਿੰਟ',
    'ago' => ':time ਪਹਿਲਾਂ',
    'from_now' => ':time ਵਿੱਚ',
    'before' => ':time ਤੋਂ ਪਹਿਲਾਂ',
    'after' => ':time ਤੋਂ ਬਾਅਦ',
    'diff_now' => 'ਹੁਣ',
    'diff_today' => 'ਅਜ',
    'diff_yesterday' => 'ਕਲ',
    'diff_tomorrow' => 'ਕਲ',
    'formats' => [
        'LT' => 'A h:mm ਵਜੇ',
        'LTS' => 'A h:mm:ss ਵਜੇ',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm ਵਜੇ',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm ਵਜੇ',
    ],
    'calendar' => [
        'sameDay' => '[ਅਜ] LT',
        'nextDay' => '[ਕਲ] LT',
        'nextWeek' => '[ਅਗਲਾ] dddd, LT',
        'lastDay' => '[ਕਲ] LT',
        'lastWeek' => '[ਪਿਛਲੇ] dddd, LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'ਰਾਤ';
        }
        if ($hour < 10) {
            return 'ਸਵੇਰ';
        }
        if ($hour < 17) {
            return 'ਦੁਪਹਿਰ';
        }
        if ($hour < 20) {
            return 'ਸ਼ਾਮ';
        }

        return 'ਰਾਤ';
    },
    'months' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
    'months_short' => ['ਜਨਵਰੀ', 'ਫ਼ਰਵਰੀ', 'ਮਾਰਚ', 'ਅਪ੍ਰੈਲ', 'ਮਈ', 'ਜੂਨ', 'ਜੁਲਾਈ', 'ਅਗਸਤ', 'ਸਤੰਬਰ', 'ਅਕਤੂਬਰ', 'ਨਵੰਬਰ', 'ਦਸੰਬਰ'],
    'weekdays' => ['ਐਤਵਾਰ', 'ਸੋਮਵਾਰ', 'ਮੰਗਲਵਾਰ', 'ਬੁਧਵਾਰ', 'ਵੀਰਵਾਰ', 'ਸ਼ੁੱਕਰਵਾਰ', 'ਸ਼ਨੀਚਰਵਾਰ'],
    'weekdays_short' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'],
    'weekdays_min' => ['ਐਤ', 'ਸੋਮ', 'ਮੰਗਲ', 'ਬੁਧ', 'ਵੀਰ', 'ਸ਼ੁਕਰ', 'ਸ਼ਨੀ'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' ਅਤੇ '],
    'weekend' => [0, 0],
    'alt_numbers' => ['੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/bs.php', [
    'meridiem' => ['пре подне', 'поподне'],
    'weekdays' => ['недјеља', 'понедјељак', 'уторак', 'сриједа', 'четвртак', 'петак', 'субота'],
    'weekdays_short' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
    'weekdays_min' => ['нед', 'пон', 'уто', 'сри', 'чет', 'пет', 'суб'],
    'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јуни', 'јули', 'аугуст', 'септембар', 'октобар', 'новембар', 'децембар'],
    'months_short' => ['јан', 'феб', 'мар', 'апр', 'мај', 'јун', 'јул', 'ауг', 'сеп', 'окт', 'нов', 'дец'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D.M.YYYY.',
        'LL' => 'DD.MM.YYYY.',
        'LLL' => 'DD. MMMM YYYY. HH:mm',
        'LLLL' => 'dddd, DD. MMMM YYYY. HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Djan SACRE Pablo Saratxaga pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['di djanvî', 'di fevrî', 'di måss', 'd’ avri', 'di may', 'di djun', 'di djulete', 'd’ awousse', 'di setimbe', 'd’ octôbe', 'di nôvimbe', 'di decimbe'],
    'months_short' => ['dja', 'fev', 'mås', 'avr', 'may', 'djn', 'djl', 'awo', 'set', 'oct', 'nôv', 'dec'],
    'weekdays' => ['dimegne', 'londi', 'mårdi', 'mierkidi', 'djudi', 'vénrdi', 'semdi'],
    'weekdays_short' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'],
    'weekdays_min' => ['dim', 'lon', 'mår', 'mie', 'dju', 'vén', 'sem'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count anêye',
    'y' => ':count anêye',
    'a_year' => ':count anêye',

    'month' => ':count meûs',
    'm' => ':count meûs',
    'a_month' => ':count meûs',

    'week' => ':count samwinne',
    'w' => ':count samwinne',
    'a_week' => ':count samwinne',

    'day' => ':count djoû',
    'd' => ':count djoû',
    'a_day' => ':count djoû',

    'hour' => ':count eure',
    'h' => ':count eure',
    'a_hour' => ':count eure',

    'minute' => ':count munute',
    'min' => ':count munute',
    'a_minute' => ':count munute',

    'second' => ':count Sigonde',
    's' => ':count Sigonde',
    'a_second' => ':count Sigonde',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Sardinian Translators Team Massimeddu Cireddu massimeddu@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD. MM. YY',
    ],
    'months' => ['Ghennàrgiu', 'Freàrgiu', 'Martzu', 'Abrile', 'Maju', 'Làmpadas', 'Argiolas//Trìulas', 'Austu', 'Cabudanni', 'Santugaine//Ladàmine', 'Onniasantu//Santandria', 'Nadale//Idas'],
    'months_short' => ['Ghe', 'Fre', 'Mar', 'Abr', 'Maj', 'Làm', 'Arg', 'Aus', 'Cab', 'Lad', 'Onn', 'Nad'],
    'weekdays' => ['Domìnigu', 'Lunis', 'Martis', 'Mèrcuris', 'Giòbia', 'Chenàbura', 'Sàbadu'],
    'weekdays_short' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'],
    'weekdays_min' => ['Dom', 'Lun', 'Mar', 'Mèr', 'Giò', 'Che', 'Sàb'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'minute' => ':count mementu', // less reliable
    'min' => ':count mementu', // less reliable
    'a_minute' => ':count mementu', // less reliable

    'year' => ':count annu',
    'y' => ':count annu',
    'a_year' => ':count annu',

    'month' => ':count mese',
    'm' => ':count mese',
    'a_month' => ':count mese',

    'week' => ':count chida',
    'w' => ':count chida',
    'a_week' => ':count chida',

    'day' => ':count dí',
    'd' => ':count dí',
    'a_day' => ':count dí',

    'hour' => ':count ora',
    'h' => ':count ora',
    'a_hour' => ':count ora',

    'second' => ':count secundu',
    's' => ':count secundu',
    'a_second' => ':count secundu',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Janaware', 'Febereware', 'Matšhe', 'Aprele', 'Mei', 'June', 'Julae', 'Agostose', 'Setemere', 'Oktobere', 'Nofemere', 'Disemere'],
    'months_short' => ['Jan', 'Feb', 'Mat', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Set', 'Okt', 'Nof', 'Dis'],
    'weekdays' => ['LaMorena', 'Mošupologo', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Mokibelo'],
    'weekdays_short' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
    'weekdays_min' => ['Son', 'Moš', 'Bed', 'Rar', 'Ne', 'Hla', 'Mok'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => ':count ngwaga',
    'y' => ':count ngwaga',
    'a_year' => ':count ngwaga',

    'month' => ':count Kgwedi',
    'm' => ':count Kgwedi',
    'a_month' => ':count Kgwedi',

    'week' => ':count Beke',
    'w' => ':count Beke',
    'a_week' => ':count Beke',

    'day' => ':count Letšatši',
    'd' => ':count Letšatši',
    'a_day' => ':count Letšatši',

    'hour' => ':count Iri',
    'h' => ':count Iri',
    'a_hour' => ':count Iri',

    'minute' => ':count Motsotso',
    'min' => ':count Motsotso',
    'a_minute' => ':count Motsotso',

    'second' => ':count motsotswana',
    's' => ':count motsotswana',
    'a_second' => ':count motsotswana',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/zh.php', [
    'formats' => [
        'L' => 'YYYY年MM月DD日',
    ],
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Adduha', 'Aluula'],
    'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamiisa', 'Alzuma', 'Asibti'],
    'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'month' => ':count alaada', // less reliable
    'm' => ':count alaada', // less reliable
    'a_month' => ':count alaada', // less reliable

    'hour' => ':count ɲaajin', // less reliable
    'h' => ':count ɲaajin', // less reliable
    'a_hour' => ':count ɲaajin', // less reliable

    'minute' => ':count zarbu', // less reliable
    'min' => ':count zarbu', // less reliable
    'a_minute' => ':count zarbu', // less reliable

    'year' => ':count jiiri',
    'y' => ':count jiiri',
    'a_year' => ':count jiiri',

    'week' => ':count jirbiiyye',
    'w' => ':count jirbiiyye',
    'a_week' => ':count jirbiiyye',

    'day' => ':count zaari',
    'd' => ':count zaari',
    'a_day' => ':count zaari',

    'second' => ':count ihinkante',
    's' => ':count ihinkante',
    'a_second' => ':count ihinkante',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Dieter Sting
 * - François B
 * - Maxime VALY
 * - JD Isaacks
 * - Dieter Sting
 * - François B
 * - JD Isaacks
 * - Sebastian Thierer
 * - Fastfuel
 * - Pete Scopes (pdscopes)
 */
return [
    'millennium' => ':count millénaire|:count millénaires',
    'a_millennium' => 'un millénaire|:count millénaires',
    'century' => ':count siècle|:count siècles',
    'a_century' => 'un siècle|:count siècles',
    'decade' => ':count décennie|:count décennies',
    'a_decade' => 'une décennie|:count décennies',
    'year' => ':count an|:count ans',
    'a_year' => 'un an|:count ans',
    'y' => ':count an|:count ans',
    'month' => ':count mois|:count mois',
    'a_month' => 'un mois|:count mois',
    'm' => ':count mois',
    'week' => ':count semaine|:count semaines',
    'a_week' => 'une semaine|:count semaines',
    'w' => ':count sem.',
    'day' => ':count jour|:count jours',
    'a_day' => 'un jour|:count jours',
    'd' => ':count j',
    'hour' => ':count heure|:count heures',
    'a_hour' => 'une heure|:count heures',
    'h' => ':count h',
    'minute' => ':count minute|:count minutes',
    'a_minute' => 'une minute|:count minutes',
    'min' => ':count min',
    'second' => ':count seconde|:count secondes',
    'a_second' => 'quelques secondes|:count secondes',
    's' => ':count s',
    'millisecond' => ':count milliseconde|:count millisecondes',
    'a_millisecond' => 'une milliseconde|:count millisecondes',
    'ms' => ':countms',
    'microsecond' => ':count microseconde|:count microsecondes',
    'a_microsecond' => 'une microseconde|:count microsecondes',
    'µs' => ':countµs',
    'ago' => 'il y a :time',
    'from_now' => 'dans :time',
    'after' => ':time après',
    'before' => ':time avant',
    'diff_now' => "à l'instant",
    'diff_today' => "aujourd'hui",
    'diff_today_regexp' => "aujourd'hui(?:\s+à)?",
    'diff_yesterday' => 'hier',
    'diff_yesterday_regexp' => 'hier(?:\s+à)?',
    'diff_tomorrow' => 'demain',
    'diff_tomorrow_regexp' => 'demain(?:\s+à)?',
    'diff_before_yesterday' => 'avant-hier',
    'diff_after_tomorrow' => 'après-demain',
    'period_recurrences' => ':count fois',
    'period_interval' => 'tous les :interval',
    'period_start_date' => 'de :date',
    'period_end_date' => 'à :date',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Aujourd’hui à] LT',
        'nextDay' => '[Demain à] LT',
        'nextWeek' => 'dddd [à] LT',
        'lastDay' => '[Hier à] LT',
        'lastWeek' => 'dddd [dernier à] LT',
        'sameElse' => 'L',
    ],
    'months' => ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
    'months_short' => ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.'],
    'weekdays' => ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
    'weekdays_short' => ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
    'weekdays_min' => ['di', 'lu', 'ma', 'me', 'je', 've', 'sa'],
    'ordinal' => static function ($number, $period) {
        return match ($period) {
            // In French, only the first has to be ordinal, other number remains cardinal
            // @link https://fr.wikihow.com/%C3%A9crire-la-date-en-fran%C3%A7ais
            'D' => $number.($number === 1 ? 'er' : ''),
            default => $number.($number === 1 ? 'er' : 'e'),
            'w', 'W' => $number.($number === 1 ? 're' : 'e'),
        };
    },
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' et '],
    'ordinal_words' => [
        'of' => 'de',
        'first' => 'premier',
        'second' => 'deuxième',
        'third' => 'troisième',
        'fourth' => 'quatrième',
        'fifth' => 'cinquième',
        'last' => 'dernier',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ik_CA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kristján Ingi Geirsson
 */
return [
    'year' => '1 ár|:count ár',
    'y' => '1 ár|:count ár',
    'month' => '1 mánuður|:count mánuðir',
    'm' => '1 mánuður|:count mánuðir',
    'week' => '1 vika|:count vikur',
    'w' => '1 vika|:count vikur',
    'day' => '1 dagur|:count dagar',
    'd' => '1 dagur|:count dagar',
    'hour' => '1 klukkutími|:count klukkutímar',
    'h' => '1 klukkutími|:count klukkutímar',
    'minute' => '1 mínúta|:count mínútur',
    'min' => '1 mínúta|:count mínútur',
    'second' => '1 sekúnda|:count sekúndur',
    's' => '1 sekúnda|:count sekúndur',
    'ago' => ':time síðan',
    'from_now' => ':time síðan',
    'after' => ':time eftir',
    'before' => ':time fyrir',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' og '],
    'meridiem' => ['fh', 'eh'],
    'diff_now' => 'núna',
    'diff_yesterday' => 'í gær',
    'diff_tomorrow' => 'á morgun',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM [kl.] HH:mm',
        'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
    ],
    'weekdays' => ['sunnudaginn', 'mánudaginn', 'þriðjudaginn', 'miðvikudaginn', 'fimmtudaginn', 'föstudaginn', 'laugardaginn'],
    'weekdays_short' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],
    'weekdays_min' => ['sun', 'mán', 'þri', 'mið', 'fim', 'fös', 'lau'],
    'months' => ['janúar', 'febrúar', 'mars', 'apríl', 'maí', 'júní', 'júlí', 'ágúst', 'september', 'október', 'nóvember', 'desember'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'maí', 'jún', 'júl', 'ágú', 'sep', 'okt', 'nóv', 'des'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/tn_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sa_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hant_HK.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return PluralizationRules::get($number, 'sr');
    }, 'sr_Latn_XK');
}
// @codeCoverageIgnoreEnd

return array_replace_recursive(require __DIR__.'/sr_Latn_BA.php', [
    'weekdays' => ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Neskie Manuel    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Pellkwet̓min', 'Pelctsipwen̓ten', 'Pellsqépts', 'Peslléwten', 'Pell7ell7é7llqten', 'Pelltspéntsk', 'Pelltqwelq̓wél̓t', 'Pellct̓éxel̓cten', 'Pesqelqlélten', 'Pesllwélsten', 'Pellc7ell7é7llcwten̓', 'Pelltetétq̓em'],
    'months_short' => ['Kwe', 'Tsi', 'Sqe', 'Éwt', 'Ell', 'Tsp', 'Tqw', 'Ct̓é', 'Qel', 'Wél', 'U7l', 'Tet'],
    'weekdays' => ['Sxetspesq̓t', 'Spetkesq̓t', 'Selesq̓t', 'Skellesq̓t', 'Smesesq̓t', 'Stselkstesq̓t', 'Stqmekstesq̓t'],
    'weekdays_short' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'],
    'weekdays_min' => ['Sxe', 'Spe', 'Sel', 'Ske', 'Sme', 'Sts', 'Stq'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => ':count sqlélten', // less reliable
    'y' => ':count sqlélten', // less reliable
    'a_year' => ':count sqlélten', // less reliable

    'month' => ':count swewll', // less reliable
    'm' => ':count swewll', // less reliable
    'a_month' => ':count swewll', // less reliable

    'hour' => ':count seqwlút', // less reliable
    'h' => ':count seqwlút', // less reliable
    'a_hour' => ':count seqwlút', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/an_ES.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/crh_UA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/hu.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - somosazucar.org    libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Petsatin', 'Kupitin', 'Uyaitin', 'Tayutin', 'Kegketin', 'Tegmatin', 'Kuntutin', 'Yagkujutin', 'Daiktatin', 'Ipamtatin', 'Shinutin', 'Sakamtin'],
    'months_short' => ['Pet', 'Kup', 'Uya', 'Tay', 'Keg', 'Teg', 'Kun', 'Yag', 'Dait', 'Ipam', 'Shin', 'Sak'],
    'weekdays' => ['Tuntuamtin', 'Achutin', 'Kugkuktin', 'Saketin', 'Shimpitin', 'Imaptin', 'Bataetin'],
    'weekdays_short' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'],
    'weekdays_min' => ['Tun', 'Ach', 'Kug', 'Sak', 'Shim', 'Im', 'Bat'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 7,
    'meridiem' => ['VM', 'NM'],

    'year' => ':count yaya', // less reliable
    'y' => ':count yaya', // less reliable
    'a_year' => ':count yaya', // less reliable

    'month' => ':count nantu', // less reliable
    'm' => ':count nantu', // less reliable
    'a_month' => ':count nantu', // less reliable

    'day' => ':count nayaim', // less reliable
    'd' => ':count nayaim', // less reliable
    'a_day' => ':count nayaim', // less reliable

    'hour' => ':count kuwiš', // less reliable
    'h' => ':count kuwiš', // less reliable
    'a_hour' => ':count kuwiš', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - du
 * - JD Isaacks
 * - Nafies Luthfi
 * - Raymundus Jati Primanda (mundusjp)
 * - diankur313
 * - a-wip0
 */
return [
    'year' => ':count tahun',
    'a_year' => '{1}setahun|[-Inf,Inf]:count tahun',
    'y' => ':countthn',
    'month' => ':count bulan',
    'a_month' => '{1}sebulan|[-Inf,Inf]:count bulan',
    'm' => ':countbln',
    'week' => ':count minggu',
    'a_week' => '{1}seminggu|[-Inf,Inf]:count minggu',
    'w' => ':countmgg',
    'day' => ':count hari',
    'a_day' => '{1}sehari|[-Inf,Inf]:count hari',
    'd' => ':counthr',
    'hour' => ':count jam',
    'a_hour' => '{1}sejam|[-Inf,Inf]:count jam',
    'h' => ':countj',
    'minute' => ':count menit',
    'a_minute' => '{1}semenit|[-Inf,Inf]:count menit',
    'min' => ':countmnt',
    'second' => ':count detik',
    'a_second' => '{1}beberapa detik|[-Inf,Inf]:count detik',
    's' => ':countdt',
    'ago' => ':time yang lalu',
    'from_now' => ':time dari sekarang',
    'after' => ':time setelahnya',
    'before' => ':time sebelumnya',
    'diff_now' => 'sekarang',
    'diff_today' => 'Hari',
    'diff_today_regexp' => 'Hari(?:\\s+ini)?(?:\\s+pukul)?',
    'diff_yesterday' => 'kemarin',
    'diff_yesterday_regexp' => 'Kemarin(?:\\s+pukul)?',
    'diff_tomorrow' => 'besok',
    'diff_tomorrow_regexp' => 'Besok(?:\\s+pukul)?',
    'formats' => [
        'LT' => 'HH.mm',
        'LTS' => 'HH.mm.ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY [pukul] HH.mm',
        'LLLL' => 'dddd, D MMMM YYYY [pukul] HH.mm',
    ],
    'calendar' => [
        'sameDay' => '[Hari ini pukul] LT',
        'nextDay' => '[Besok pukul] LT',
        'nextWeek' => 'dddd [pukul] LT',
        'lastDay' => '[Kemarin pukul] LT',
        'lastWeek' => 'dddd [lalu pukul] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 11) {
            return 'pagi';
        }
        if ($hour < 15) {
            return 'siang';
        }
        if ($hour < 19) {
            return 'sore';
        }

        return 'malam';
    },
    'months' => ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'],
    'weekdays_short' => ['Min', 'Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab'],
    'weekdays_min' => ['Mg', 'Sn', 'Sl', 'Rb', 'Km', 'Jm', 'Sb'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' dan '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Sugar Labs // OLPC sugarlabs.org libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['janvye', 'fevriye', 'mas', 'avril', 'me', 'jen', 'jiyè', 'out', 'septanm', 'oktòb', 'novanm', 'desanm'],
    'months_short' => ['jan', 'fev', 'mas', 'avr', 'me', 'jen', 'jiy', 'out', 'sep', 'okt', 'nov', 'des'],
    'weekdays' => ['dimanch', 'lendi', 'madi', 'mèkredi', 'jedi', 'vandredi', 'samdi'],
    'weekdays_short' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'],
    'weekdays_min' => ['dim', 'len', 'mad', 'mèk', 'jed', 'van', 'sam'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'year' => ':count lane',
    'y' => ':count lane',
    'a_year' => ':count lane',

    'month' => 'mwa :count',
    'm' => 'mwa :count',
    'a_month' => 'mwa :count',

    'week' => 'semèn :count',
    'w' => 'semèn :count',
    'a_week' => 'semèn :count',

    'day' => ':count jou',
    'd' => ':count jou',
    'a_day' => ':count jou',

    'hour' => ':count lè',
    'h' => ':count lè',
    'a_hour' => ':count lè',

    'minute' => ':count minit',
    'min' => ':count minit',
    'a_minute' => ':count minit',

    'second' => ':count segonn',
    's' => ':count segonn',
    'a_second' => ':count segonn',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - JD Isaacks
 * - Daniel Monaghan
 */
return [
    'year' => '{1}:count flwyddyn|[-Inf,Inf]:count flynedd',
    'a_year' => '{1}blwyddyn|[-Inf,Inf]:count flynedd',
    'y' => ':countbl',
    'month' => ':count mis',
    'a_month' => '{1}mis|[-Inf,Inf]:count mis',
    'm' => ':countmi',
    'week' => ':count wythnos',
    'a_week' => '{1}wythnos|[-Inf,Inf]:count wythnos',
    'w' => ':countw',
    'day' => ':count diwrnod',
    'a_day' => '{1}diwrnod|[-Inf,Inf]:count diwrnod',
    'd' => ':countd',
    'hour' => ':count awr',
    'a_hour' => '{1}awr|[-Inf,Inf]:count awr',
    'h' => ':counth',
    'minute' => ':count munud',
    'a_minute' => '{1}munud|[-Inf,Inf]:count munud',
    'min' => ':countm',
    'second' => ':count eiliad',
    'a_second' => '{0,1}ychydig eiliadau|[-Inf,Inf]:count eiliad',
    's' => ':counts',
    'ago' => ':time yn ôl',
    'from_now' => 'mewn :time',
    'after' => ':time ar ôl',
    'before' => ':time o\'r blaen',
    'diff_now' => 'nawr',
    'diff_today' => 'Heddiw',
    'diff_today_regexp' => 'Heddiw(?:\\s+am)?',
    'diff_yesterday' => 'ddoe',
    'diff_yesterday_regexp' => 'Ddoe(?:\\s+am)?',
    'diff_tomorrow' => 'yfory',
    'diff_tomorrow_regexp' => 'Yfory(?:\\s+am)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Heddiw am] LT',
        'nextDay' => '[Yfory am] LT',
        'nextWeek' => 'dddd [am] LT',
        'lastDay' => '[Ddoe am] LT',
        'lastWeek' => 'dddd [diwethaf am] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        return $number.(
            $number > 20
                ? (\in_array((int) $number, [40, 50, 60, 80, 100], true) ? 'fed' : 'ain')
                : ([
                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed', // 11eg to 20fed
                ])[$number] ?? ''
        );
    },
    'months' => ['Ionawr', 'Chwefror', 'Mawrth', 'Ebrill', 'Mai', 'Mehefin', 'Gorffennaf', 'Awst', 'Medi', 'Hydref', 'Tachwedd', 'Rhagfyr'],
    'months_short' => ['Ion', 'Chwe', 'Maw', 'Ebr', 'Mai', 'Meh', 'Gor', 'Aws', 'Med', 'Hyd', 'Tach', 'Rhag'],
    'weekdays' => ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],
    'weekdays_short' => ['Sul', 'Llun', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],
    'weekdays_min' => ['Su', 'Ll', 'Ma', 'Me', 'Ia', 'Gw', 'Sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' a '],
    'meridiem' => ['yb', 'yh'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/niu_NU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return require __DIR__.'/so.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['enikwsi', 'chkwali', 'xamokhwite', 'kwetayoxe', 'tainipen', 'kichinipen', 'lainipen', 'winaminke', 'kichitahkok', 'puksit', 'wini', 'muxkotae'],
    'months_short' => ['eni', 'chk', 'xam', 'kwe', 'tai', 'nip', 'lai', 'win', 'tah', 'puk', 'kun', 'mux'],
    'weekdays' => ['kentuwei', 'manteke', 'tusteke', 'lelai', 'tasteke', 'pelaiteke', 'sateteke'],
    'weekdays_short' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'],
    'weekdays_min' => ['ken', 'man', 'tus', 'lel', 'tas', 'pel', 'sat'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    // Too unreliable
    /*
    'year' => ':count kaxtëne',
    'y' => ':count kaxtëne',
    'a_year' => ':count kaxtëne',

    'month' => ':count piskewëni kishux', // less reliable
    'm' => ':count piskewëni kishux', // less reliable
    'a_month' => ':count piskewëni kishux', // less reliable

    'week' => ':count kishku', // less reliable
    'w' => ':count kishku', // less reliable
    'a_week' => ':count kishku', // less reliable

    'day' => ':count kishku',
    'd' => ':count kishku',
    'a_day' => ':count kishku',

    'hour' => ':count xkuk', // less reliable
    'h' => ':count xkuk', // less reliable
    'a_hour' => ':count xkuk', // less reliable

    'minute' => ':count txituwàk', // less reliable
    'min' => ':count txituwàk', // less reliable
    'a_minute' => ':count txituwàk', // less reliable

    'second' => ':count nisha', // less reliable
    's' => ':count nisha', // less reliable
    'a_second' => ':count nisha', // less reliable
    */
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - Tim Fish
 * - shaishavgandhi05
 * - Serhan Apaydın
 * - JD Isaacks
 * - tomhorvat
 * - Josh Soref
 * - François B
 * - shaishavgandhi05
 * - Serhan Apaydın
 * - JD Isaacks
 * - tomhorvat
 * - Stjepan Majdak
 * - Vanja Retkovac (vr00)
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count godinu|:count godine|:count godina',
    'y' => ':count god.|:count god.|:count god.',
    'month' => ':count mjesec|:count mjeseca|:count mjeseci',
    'm' => ':count mj.|:count mj.|:count mj.',
    'week' => ':count tjedan|:count tjedna|:count tjedana',
    'w' => ':count tj.|:count tj.|:count tj.',
    'day' => ':count dan|:count dana|:count dana',
    'd' => ':count d.|:count d.|:count d.',
    'hour' => ':count sat|:count sata|:count sati',
    'h' => ':count sat|:count sata|:count sati',
    'minute' => ':count minutu|:count minute|:count minuta',
    'min' => ':count min.|:count min.|:count min.',
    'second' => ':count sekundu|:count sekunde|:count sekundi',
    'a_second' => 'nekoliko sekundi|:count sekunde|:count sekundi',
    's' => ':count sek.|:count sek.|:count sek.',
    'ago' => 'prije :time',
    'from_now' => 'za :time',
    'after' => ':time poslije',
    'before' => ':time prije',
    'diff_now' => 'sad',
    'diff_today' => 'danas',
    'diff_today_regexp' => 'danas(?:\\s+u)?',
    'diff_yesterday' => 'jučer',
    'diff_yesterday_regexp' => 'jučer(?:\\s+u)?',
    'diff_tomorrow' => 'sutra',
    'diff_tomorrow_regexp' => 'sutra(?:\\s+u)?',
    'diff_before_yesterday' => 'prekjučer',
    'diff_after_tomorrow' => 'prekosutra',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'D. M. YYYY.',
        'LL' => 'D. MMMM YYYY.',
        'LLL' => 'D. MMMM YYYY. H:mm',
        'LLLL' => 'dddd, D. MMMM YYYY. H:mm',
    ],
    'calendar' => [
        'sameDay' => '[danas u] LT',
        'nextDay' => '[sutra u] LT',
        'nextWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[u] [nedjelju] [u] LT',
            3 => '[u] [srijedu] [u] LT',
            6 => '[u] [subotu] [u] LT',
            default => '[u] dddd [u] LT',
        },
        'lastDay' => '[jučer u] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0, 3 => '[prošlu] dddd [u] LT',
            6 => '[prošle] [subote] [u] LT',
            default => '[prošli] dddd [u] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['siječnja', 'veljače', 'ožujka', 'travnja', 'svibnja', 'lipnja', 'srpnja', 'kolovoza', 'rujna', 'listopada', 'studenoga', 'prosinca'],
    'months_standalone' => ['siječanj', 'veljača', 'ožujak', 'travanj', 'svibanj', 'lipanj', 'srpanj', 'kolovoz', 'rujan', 'listopad', 'studeni', 'prosinac'],
    'months_short' => ['sij.', 'velj.', 'ožu.', 'tra.', 'svi.', 'lip.', 'srp.', 'kol.', 'ruj.', 'lis.', 'stu.', 'pro.'],
    'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['nedjelju', 'ponedjeljak', 'utorak', 'srijedu', 'četvrtak', 'petak', 'subotu'],
    'weekdays_standalone' => ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'],
    'weekdays_short' => ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'],
    'weekdays_min' => ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' i '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/mi.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'OY[年]MMMMOD[日]',
    ],
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => [' 一 ', ' 二 ', ' 三 ', ' 四 ', ' 五 ', ' 六 ', ' 七 ', ' 八 ', ' 九 ', ' 十 ', '十一', '十二'],
    'weekdays' => ['週日', '週一', '週二', '週三', '週四', '週五', '週六'],
    'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '廿', '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '卅', '卅一'],
    'meridiem' => ['朝', '暮'],

    'year' => ':count 夏', // less reliable
    'y' => ':count 夏', // less reliable
    'a_year' => ':count 夏', // less reliable

    'month' => ':count 月', // less reliable
    'm' => ':count 月', // less reliable
    'a_month' => ':count 月', // less reliable

    'hour' => ':count 氧', // less reliable
    'h' => ':count 氧', // less reliable
    'a_hour' => ':count 氧', // less reliable

    'minute' => ':count 點', // less reliable
    'min' => ':count 點', // less reliable
    'a_minute' => ':count 點', // less reliable

    'second' => ':count 楚', // less reliable
    's' => ':count 楚', // less reliable
    'a_second' => ':count 楚', // less reliable

    'week' => ':count 星期',
    'w' => ':count 星期',
    'a_week' => ':count 星期',

    'day' => ':count 日(曆法)',
    'd' => ':count 日(曆法)',
    'a_day' => ':count 日(曆法)',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sv.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Samsung Electronics Co., Ltd.    akhilesh.k@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['zanvie', 'fevriye', 'mars', 'avril', 'me', 'zin', 'zilye', 'out', 'septam', 'oktob', 'novam', 'desam'],
    'months_short' => ['zan', 'fev', 'mar', 'avr', 'me', 'zin', 'zil', 'out', 'sep', 'okt', 'nov', 'des'],
    'weekdays' => ['dimans', 'lindi', 'mardi', 'merkredi', 'zedi', 'vandredi', 'samdi'],
    'weekdays_short' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],
    'weekdays_min' => ['dim', 'lin', 'mar', 'mer', 'ze', 'van', 'sam'],

    'year' => ':count banané',
    'y' => ':count banané',
    'a_year' => ':count banané',

    'month' => ':count mwa',
    'm' => ':count mwa',
    'a_month' => ':count mwa',

    'week' => ':count sémenn',
    'w' => ':count sémenn',
    'a_week' => ':count sémenn',

    'day' => ':count zour',
    'd' => ':count zour',
    'a_day' => ':count zour',

    'hour' => ':count -er-tan',
    'h' => ':count -er-tan',
    'a_hour' => ':count -er-tan',

    'minute' => ':count minitt',
    'min' => ':count minitt',
    'a_minute' => ':count minitt',

    'second' => ':count déziém',
    's' => ':count déziém',
    'a_second' => ':count déziém',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Karamell
 */
return [
    'year' => '{1}:count jahki|:count jagit',
    'a_year' => '{1}okta jahki|:count jagit',
    'y' => ':count j.',
    'month' => '{1}:count mánnu|:count mánut',
    'a_month' => '{1}okta mánnu|:count mánut',
    'm' => ':count mán.',
    'week' => '{1}:count vahkku|:count vahkku',
    'a_week' => '{1}okta vahkku|:count vahkku',
    'w' => ':count v.',
    'day' => '{1}:count beaivi|:count beaivvit',
    'a_day' => '{1}okta beaivi|:count beaivvit',
    'd' => ':count b.',
    'hour' => '{1}:count diimmu|:count diimmut',
    'a_hour' => '{1}okta diimmu|:count diimmut',
    'h' => ':count d.',
    'minute' => '{1}:count minuhta|:count minuhtat',
    'a_minute' => '{1}okta minuhta|:count minuhtat',
    'min' => ':count min.',
    'second' => '{1}:count sekunddat|:count sekunddat',
    'a_second' => '{1}moadde sekunddat|:count sekunddat',
    's' => ':count s.',
    'ago' => 'maŋit :time',
    'from_now' => ':time geažes',
    'diff_yesterday' => 'ikte',
    'diff_yesterday_regexp' => 'ikte(?:\\s+ti)?',
    'diff_today' => 'otne',
    'diff_today_regexp' => 'otne(?:\\s+ti)?',
    'diff_tomorrow' => 'ihttin',
    'diff_tomorrow_regexp' => 'ihttin(?:\\s+ti)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'MMMM D. [b.] YYYY',
        'LLL' => 'MMMM D. [b.] YYYY [ti.] HH:mm',
        'LLLL' => 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[otne ti] LT',
        'nextDay' => '[ihttin ti] LT',
        'nextWeek' => 'dddd [ti] LT',
        'lastDay' => '[ikte ti] LT',
        'lastWeek' => '[ovddit] dddd [ti] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['ođđajagemánnu', 'guovvamánnu', 'njukčamánnu', 'cuoŋománnu', 'miessemánnu', 'geassemánnu', 'suoidnemánnu', 'borgemánnu', 'čakčamánnu', 'golggotmánnu', 'skábmamánnu', 'juovlamánnu'],
    'months_short' => ['ođđj', 'guov', 'njuk', 'cuo', 'mies', 'geas', 'suoi', 'borg', 'čakč', 'golg', 'skáb', 'juov'],
    'weekdays' => ['sotnabeaivi', 'vuossárga', 'maŋŋebárga', 'gaskavahkku', 'duorastat', 'bearjadat', 'lávvardat'],
    'weekdays_short' => ['sotn', 'vuos', 'maŋ', 'gask', 'duor', 'bear', 'láv'],
    'weekdays_min' => ['s', 'v', 'm', 'g', 'd', 'b', 'L'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' ja '],
    'meridiem' => ['i.b.', 'e.b.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mai_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Munkyo', 'Eigulo'],
    'weekdays' => ['Sabiiti', 'Balaza', 'Owokubili', 'Owokusatu', 'Olokuna', 'Olokutaanu', 'Olomukaaga'],
    'weekdays_short' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
    'weekdays_min' => ['Sabi', 'Bala', 'Kubi', 'Kusa', 'Kuna', 'Kuta', 'Muka'],
    'months' => ['Janwaliyo', 'Febwaliyo', 'Marisi', 'Apuli', 'Maayi', 'Juuni', 'Julaayi', 'Agusito', 'Sebuttemba', 'Okitobba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apu', 'Maa', 'Juu', 'Jul', 'Agu', 'Seb', 'Oki', 'Nov', 'Des'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/li_NL.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/cv.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - Rasulbek
 * - Ilyosjon Kamoldinov (ilyosjon09)
 */
return [
    'year' => ':count yil',
    'a_year' => '{1}bir yil|:count yil',
    'y' => ':count y',
    'month' => ':count oy',
    'a_month' => '{1}bir oy|:count oy',
    'm' => ':count o',
    'week' => ':count hafta',
    'a_week' => '{1}bir hafta|:count hafta',
    'w' => ':count h',
    'day' => ':count kun',
    'a_day' => '{1}bir kun|:count kun',
    'd' => ':count k',
    'hour' => ':count soat',
    'a_hour' => '{1}bir soat|:count soat',
    'h' => ':count soat',
    'minute' => ':count daqiqa',
    'a_minute' => '{1}bir daqiqa|:count daqiqa',
    'min' => ':count d',
    'second' => ':count soniya',
    'a_second' => '{1}soniya|:count soniya',
    's' => ':count son.',
    'ago' => ':time avval',
    'from_now' => 'Yaqin :time ichida',
    'after' => ':timedan keyin',
    'before' => ':time oldin',
    'diff_yesterday' => 'Kecha',
    'diff_yesterday_regexp' => 'Kecha(?:\\s+soat)?',
    'diff_today' => 'Bugun',
    'diff_today_regexp' => 'Bugun(?:\\s+soat)?',
    'diff_tomorrow' => 'Ertaga',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'D MMMM YYYY, dddd HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Bugun soat] LT [da]',
        'nextDay' => '[Ertaga] LT [da]',
        'nextWeek' => 'dddd [kuni soat] LT [da]',
        'lastDay' => '[Kecha soat] LT [da]',
        'lastWeek' => '[O\'tgan] dddd [kuni soat] LT [da]',
        'sameElse' => 'L',
    ],
    'months' => ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'Iyun', 'Iyul', 'Avgust', 'Sentabr', 'Oktabr', 'Noyabr', 'Dekabr'],
    'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyun', 'Iyul', 'Avg', 'Sen', 'Okt', 'Noy', 'Dek'],
    'weekdays' => ['Yakshanba', 'Dushanba', 'Seshanba', 'Chorshanba', 'Payshanba', 'Juma', 'Shanba'],
    'weekdays_short' => ['Yak', 'Dush', 'Sesh', 'Chor', 'Pay', 'Jum', 'Shan'],
    'weekdays_min' => ['Ya', 'Du', 'Se', 'Cho', 'Pa', 'Ju', 'Sha'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' va '],
    'meridiem' => ['TO', 'TK'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ru.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - shaishavgandhi05
 * - Serhan Apaydın
 * - JD Isaacks
 * - Glavić
 * - Nikola Zeravcic
 * - Milos Sakovic
 */

use Carbon\CarbonInterface;

return [
    'year' => ':count година|:count године|:count година',
    'y' => ':count г.',
    'month' => ':count месец|:count месеца|:count месеци',
    'm' => ':count м.',
    'week' => ':count недеља|:count недеље|:count недеља',
    'w' => ':count нед.',
    'day' => ':count дан|:count дана|:count дана',
    'd' => ':count д.',
    'hour' => ':count сат|:count сата|:count сати',
    'h' => ':count ч.',
    'minute' => ':count минут|:count минута|:count минута',
    'min' => ':count мин.',
    'second' => ':count секунд|:count секунде|:count секунди',
    's' => ':count сек.',
    'ago' => 'пре :time',
    'from_now' => 'за :time',
    'after' => ':time након',
    'before' => ':time пре',
    'year_from_now' => ':count годину|:count године|:count година',
    'year_ago' => ':count годину|:count године|:count година',
    'week_from_now' => ':count недељу|:count недеље|:count недеља',
    'week_ago' => ':count недељу|:count недеље|:count недеља',
    'diff_now' => 'управо сада',
    'diff_today' => 'данас',
    'diff_today_regexp' => 'данас(?:\\s+у)?',
    'diff_yesterday' => 'јуче',
    'diff_yesterday_regexp' => 'јуче(?:\\s+у)?',
    'diff_tomorrow' => 'сутра',
    'diff_tomorrow_regexp' => 'сутра(?:\\s+у)?',
    'diff_before_yesterday' => 'прекјуче',
    'diff_after_tomorrow' => 'прекосутра',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY H:mm',
        'LLLL' => 'dddd, D. MMMM YYYY H:mm',
    ],
    'calendar' => [
        'sameDay' => '[данас у] LT',
        'nextDay' => '[сутра у] LT',
        'nextWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[у недељу у] LT',
            3 => '[у среду у] LT',
            6 => '[у суботу у] LT',
            default => '[у] dddd [у] LT',
        },
        'lastDay' => '[јуче у] LT',
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0 => '[прошле недеље у] LT',
            1 => '[прошлог понедељка у] LT',
            2 => '[прошлог уторка у] LT',
            3 => '[прошле среде у] LT',
            4 => '[прошлог четвртка у] LT',
            5 => '[прошлог петка у] LT',
            default => '[прошле суботе у] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'],
    'months_short' => ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'],
    'weekdays' => ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'],
    'weekdays_short' => ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'],
    'weekdays_min' => ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' и '],
    'meridiem' => ['АМ', 'ПМ'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/hi.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/mr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Chitwanix OS Development    info@chitwanix.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'dddd DD MMM YYYY',
    ],
    'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'months_short' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रेल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'weekdays' => ['आइतबार', 'सोमबार', 'मंगलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'],
    'weekdays_short' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'],
    'weekdays_min' => ['आइत', 'सोम', 'मंगल', 'बुध', 'बिहि', 'शुक्र', 'शनि'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ko.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/yi_US.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ff.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM AP Linux Technology Center, Yamato Software Laboratory    bug-glibc@gnu.org
 */
return [
    'diff_now' => 'ବର୍ତ୍ତମାନ',
    'diff_yesterday' => 'ଗତକାଲି',
    'diff_tomorrow' => 'ଆସନ୍ତାକାଲି',
    'formats' => [
        'LT' => 'Oh:Om A',
        'LTS' => 'Oh:Om:Os A',
        'L' => 'OD-OM-OY',
        'LL' => 'OD MMMM OY',
        'LLL' => 'OD MMMM OY Oh:Om A',
        'LLLL' => 'dddd OD MMMM OY Oh:Om A',
    ],
    'months' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'],
    'months_short' => ['ଜାନୁଆରୀ', 'ଫେବୃଆରୀ', 'ମାର୍ଚ୍ଚ', 'ଅପ୍ରେଲ', 'ମଇ', 'ଜୁନ', 'ଜୁଲାଇ', 'ଅଗଷ୍ଟ', 'ସେପ୍ଟେମ୍ବର', 'ଅକ୍ଟୋବର', 'ନଭେମ୍ବର', 'ଡିସେମ୍ବର'],
    'weekdays' => ['ରବିବାର', 'ସୋମବାର', 'ମଙ୍ଗଳବାର', 'ବୁଧବାର', 'ଗୁରୁବାର', 'ଶୁକ୍ରବାର', 'ଶନିବାର'],
    'weekdays_short' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
    'weekdays_min' => ['ରବି', 'ସୋମ', 'ମଙ୍ଗଳ', 'ବୁଧ', 'ଗୁରୁ', 'ଶୁକ୍ର', 'ଶନି'],
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯', '୧୦', '୧୧', '୧୨', '୧୩', '୧୪', '୧୫', '୧୬', '୧୭', '୧୮', '୧୯', '୨୦', '୨୧', '୨୨', '୨୩', '୨୪', '୨୫', '୨୬', '୨୭', '୨୮', '୨୯', '୩୦', '୩୧', '୩୨', '୩୩', '୩୪', '୩୫', '୩୬', '୩୭', '୩୮', '୩୯', '୪୦', '୪୧', '୪୨', '୪୩', '୪୪', '୪୫', '୪୬', '୪୭', '୪୮', '୪୯', '୫୦', '୫୧', '୫୨', '୫୩', '୫୪', '୫୫', '୫୬', '୫୭', '୫୮', '୫୯', '୬୦', '୬୧', '୬୨', '୬୩', '୬୪', '୬୫', '୬୬', '୬୭', '୬୮', '୬୯', '୭୦', '୭୧', '୭୨', '୭୩', '୭୪', '୭୫', '୭୬', '୭୭', '୭୮', '୭୯', '୮୦', '୮୧', '୮୨', '୮୩', '୮୪', '୮୫', '୮୬', '୮୭', '୮୮', '୮୯', '୯୦', '୯୧', '୯୨', '୯୩', '୯୪', '୯୫', '୯୬', '୯୭', '୯୮', '୯୯'],
    'year' => ':count ବର୍ଷ',
    'y' => ':count ବ.',
    'month' => ':count ମାସ',
    'm' => ':count ମା.',
    'week' => ':count ସପ୍ତାହ',
    'w' => ':count ସପ୍ତା.',
    'day' => ':count ଦିନ',
    'd' => ':count ଦିନ',
    'hour' => ':count ଘଣ୍ତ',
    'h' => ':count ଘ.',
    'minute' => ':count ମିନଟ',
    'min' => ':count ମି.',
    'second' => ':count ସେକଣ୍ଢ',
    's' => ':count ସେ.',
    'ago' => ':time ପୂର୍ବେ',
    'from_now' => ':timeରେ',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - acutexyz
 * - Josh Soref
 * - François B
 * - Chyngyz Arystan uulu
 * - Chyngyz
 * - acutexyz
 * - Josh Soref
 * - François B
 * - Chyngyz Arystan uulu
 */
return [
    'year' => ':count жыл',
    'a_year' => '{1}бир жыл|:count жыл',
    'y' => ':count жыл',
    'month' => ':count ай',
    'a_month' => '{1}бир ай|:count ай',
    'm' => ':count ай',
    'week' => ':count апта',
    'a_week' => '{1}бир апта|:count апта',
    'w' => ':count апт.',
    'day' => ':count күн',
    'a_day' => '{1}бир күн|:count күн',
    'd' => ':count күн',
    'hour' => ':count саат',
    'a_hour' => '{1}бир саат|:count саат',
    'h' => ':count саат.',
    'minute' => ':count мүнөт',
    'a_minute' => '{1}бир мүнөт|:count мүнөт',
    'min' => ':count мүн.',
    'second' => ':count секунд',
    'a_second' => '{1}бирнече секунд|:count секунд',
    's' => ':count сек.',
    'ago' => ':time мурун',
    'from_now' => ':time ичинде',
    'diff_now' => 'азыр',
    'diff_today' => 'Бүгүн',
    'diff_today_regexp' => 'Бүгүн(?:\\s+саат)?',
    'diff_yesterday' => 'кечээ',
    'diff_yesterday_regexp' => 'Кече(?:\\s+саат)?',
    'diff_tomorrow' => 'эртең',
    'diff_tomorrow_regexp' => 'Эртең(?:\\s+саат)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Бүгүн саат] LT',
        'nextDay' => '[Эртең саат] LT',
        'nextWeek' => 'dddd [саат] LT',
        'lastDay' => '[Кече саат] LT',
        'lastWeek' => '[Өткен аптанын] dddd [күнү] [саат] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        static $suffixes = [
            0 => '-чү',
            1 => '-чи',
            2 => '-чи',
            3 => '-чү',
            4 => '-чү',
            5 => '-чи',
            6 => '-чы',
            7 => '-чи',
            8 => '-чи',
            9 => '-чу',
            10 => '-чу',
            20 => '-чы',
            30 => '-чу',
            40 => '-чы',
            50 => '-чү',
            60 => '-чы',
            70 => '-чи',
            80 => '-чи',
            90 => '-чу',
            100 => '-чү',
        ];

        return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
    },
    'months' => ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'],
    'months_short' => ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'weekdays' => ['Жекшемби', 'Дүйшөмбү', 'Шейшемби', 'Шаршемби', 'Бейшемби', 'Жума', 'Ишемби'],
    'weekdays_short' => ['Жек', 'Дүй', 'Шей', 'Шар', 'Бей', 'Жум', 'Ише'],
    'weekdays_min' => ['Жк', 'Дй', 'Шй', 'Шр', 'Бй', 'Жм', 'Иш'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => ' ',
    'meridiem' => ['таңкы', 'түштөн кийинки'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - belkacem77@gmail.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Yennayer', 'Fuṛar', 'Meɣres', 'Yebrir', 'Mayyu', 'Yunyu', 'Yulyu', 'ɣuct', 'Ctembeṛ', 'Tubeṛ', 'Wambeṛ', 'Dujembeṛ'],
    'months_short' => ['Yen', 'Fur', 'Meɣ', 'Yeb', 'May', 'Yun', 'Yul', 'ɣuc', 'Cte', 'Tub', 'Wam', 'Duj'],
    'weekdays' => ['Acer', 'Arim', 'Aram', 'Ahad', 'Amhad', 'Sem', 'Sed'],
    'weekdays_short' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'],
    'weekdays_min' => ['Ace', 'Ari', 'Ara', 'Aha', 'Amh', 'Sem', 'Sed'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['FT', 'MD'],

    'year' => ':count n yiseggasen',
    'y' => ':count n yiseggasen',
    'a_year' => ':count n yiseggasen',

    'month' => ':count n wayyuren',
    'm' => ':count n wayyuren',
    'a_month' => ':count n wayyuren',

    'week' => ':count n ledwaṛ', // less reliable
    'w' => ':count n ledwaṛ', // less reliable
    'a_week' => ':count n ledwaṛ', // less reliable

    'day' => ':count n wussan',
    'd' => ':count n wussan',
    'a_day' => ':count n wussan',

    'hour' => ':count n tsaɛtin',
    'h' => ':count n tsaɛtin',
    'a_hour' => ':count n tsaɛtin',

    'minute' => ':count n tedqiqin',
    'min' => ':count n tedqiqin',
    'a_minute' => ':count n tedqiqin',

    'second' => ':count tasdidt', // less reliable
    's' => ':count tasdidt', // less reliable
    'a_second' => ':count tasdidt', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Mashrab Kuvatov Mashrab Kuvatov, Pablo Saratxaga kmashrab@uni-bremen.de, pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/uz.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['Январ', 'Феврал', 'Март', 'Апрел', 'Май', 'Июн', 'Июл', 'Август', 'Сентябр', 'Октябр', 'Ноябр', 'Декабр'],
    'months_short' => ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
    'weekdays' => ['Якшанба', 'Душанба', 'Сешанба', 'Чоршанба', 'Пайшанба', 'Жума', 'Шанба'],
    'weekdays_short' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'],
    'weekdays_min' => ['Якш', 'Душ', 'Сеш', 'Чор', 'Пай', 'Жум', 'Шан'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - Tim Fish
 * - Serhan Apaydın
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/hy.php', [
    'from_now' => ':time հետո',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/lt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return [
    'year' => ':count voros|:count vorsam',
    'y' => ':countv',
    'month' => ':count mhoino|:count mhoine',
    'm' => ':countmh',
    'week' => ':count satolleacho|:count satolleache',
    'w' => ':countsa|:countsa',
    'day' => ':count dis',
    'd' => ':countd',
    'hour' => ':count hor|:count horam',
    'h' => ':counth',
    'minute' => ':count minute|:count mintam',
    'min' => ':countm',
    'second' => ':count second',
    's' => ':counts',

    'diff_today' => 'Aiz',
    'diff_yesterday' => 'Kal',
    'diff_tomorrow' => 'Faleam',
    'formats' => [
        'LT' => 'A h:mm [vazta]',
        'LTS' => 'A h:mm:ss [vazta]',
        'L' => 'DD-MM-YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY A h:mm [vazta]',
        'LLLL' => 'dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]',
        'llll' => 'ddd, D MMM YYYY, A h:mm [vazta]',
    ],

    'calendar' => [
        'sameDay' => '[Aiz] LT',
        'nextDay' => '[Faleam] LT',
        'nextWeek' => '[Ieta to] dddd[,] LT',
        'lastDay' => '[Kal] LT',
        'lastWeek' => '[Fatlo] dddd[,] LT',
        'sameElse' => 'L',
    ],

    'months' => ['Janer', 'Febrer', 'Mars', 'Abril', 'Mai', 'Jun', 'Julai', 'Agost', 'Setembr', 'Otubr', 'Novembr', 'Dezembr'],
    'months_short' => ['Jan.', 'Feb.', 'Mars', 'Abr.', 'Mai', 'Jun', 'Jul.', 'Ago.', 'Set.', 'Otu.', 'Nov.', 'Dez.'],
    'weekdays' => ['Aitar', 'Somar', 'Mongllar', 'Budvar', 'Brestar', 'Sukrar', 'Son\'var'],
    'weekdays_short' => ['Ait.', 'Som.', 'Mon.', 'Bud.', 'Bre.', 'Suk.', 'Son.'],
    'weekdays_min' => ['Ai', 'Sm', 'Mo', 'Bu', 'Br', 'Su', 'Sn'],

    'ordinal' => static fn ($number, $period) => $number.($period === 'D' ? 'er' : ''),

    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'rati';
        }
        if ($hour < 12) {
            return 'sokalli';
        }
        if ($hour < 16) {
            return 'donparam';
        }
        if ($hour < 20) {
            return 'sanje';
        }

        return 'rati';
    },
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' ani '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Philippe Vaucher
 * - Tsutomu Kuroda
 * - tjku
 * - Max Melentiev
 * - Zolzaya Erdenebaatar
 * - Tom Hughes
 * - Akira Matsuda
 * - Christopher Dell
 * - Michael Kessler
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Nicolás Hock Isaza
 * - Ochirkhuyag
 * - Batmandakh
 * - lucifer-crybaby
 */
return [
    'year' => ':count жил',
    'y' => ':count жил',
    'month' => ':count сар',
    'm' => ':count сар',
    'week' => ':count долоо хоног',
    'w' => ':count долоо хоног',
    'day' => ':count өдөр',
    'd' => ':count өдөр',
    'hour' => ':count цаг',
    'h' => ':countц',
    'minute' => ':count минут',
    'min' => ':countм',
    'second' => ':count секунд',
    's' => ':countс',

    'ago_mode' => 'last',
    'ago' => ':time өмнө',
    'year_ago' => ':count жилийн',
    'y_ago' => ':count жилийн',
    'month_ago' => ':count сарын',
    'm_ago' => ':count сарын',
    'day_ago' => ':count хоногийн',
    'd_ago' => ':count хоногийн',
    'week_ago' => ':count долоо хоногийн',
    'w_ago' => ':count долоо хоногийн',
    'hour_ago' => ':count цагийн',
    'minute_ago' => ':count минутын',
    'second_ago' => ':count секундын',

    'from_now_mode' => 'last',
    'from_now' => 'одоогоос :time',
    'year_from_now' => ':count жилийн дараа',
    'y_from_now' => ':count жилийн дараа',
    'month_from_now' => ':count сарын дараа',
    'm_from_now' => ':count сарын дараа',
    'day_from_now' => ':count хоногийн дараа',
    'd_from_now' => ':count хоногийн дараа',
    'hour_from_now' => ':count цагийн дараа',
    'minute_from_now' => ':count минутын дараа',
    'second_from_now' => ':count секундын дараа',

    'after_mode' => 'last',
    'after' => ':time дараа',
    'year_after' => ':count жилийн',
    'y_after' => ':count жилийн',
    'month_after' => ':count сарын',
    'm_after' => ':count сарын',
    'day_after' => ':count хоногийн',
    'd_after' => ':count хоногийн',
    'hour_after' => ':count цагийн',
    'minute_after' => ':count минутын',
    'second_after' => ':count секундын',

    'before_mode' => 'last',
    'before' => ':time өмнө',
    'year_before' => ':count жилийн',
    'y_before' => ':count жилийн',
    'month_before' => ':count сарын',
    'm_before' => ':count сарын',
    'day_before' => ':count хоногийн',
    'd_before' => ':count хоногийн',
    'hour_before' => ':count цагийн',
    'minute_before' => ':count минутын',
    'second_before' => ':count секундын',

    'list' => ', ',
    'diff_now' => 'одоо',
    'diff_yesterday' => 'өчигдөр',
    'diff_tomorrow' => 'маргааш',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'YYYY MMMM DD',
        'LLL' => 'YY-MM-DD, HH:mm',
        'LLLL' => 'YYYY MMMM DD, HH:mm',
    ],
    'weekdays' => ['Ням', 'Даваа', 'Мягмар', 'Лхагва', 'Пүрэв', 'Баасан', 'Бямба'],
    'weekdays_short' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
    'weekdays_min' => ['Ня', 'Да', 'Мя', 'Лх', 'Пү', 'Ба', 'Бя'],
    'months' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'],
    'months_short' => ['1 сар', '2 сар', '3 сар', '4 сар', '5 сар', '6 сар', '7 сар', '8 сар', '9 сар', '10 сар', '11 сар', '12 сар'],
    'meridiem' => ['өглөө', 'орой'],
    'first_day_of_week' => 1,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RFC 2319    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/ru.php', [
    'weekdays' => ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
    'weekdays_short' => ['вск', 'пнд', 'вто', 'срд', 'чтв', 'птн', 'суб'],
    'weekdays_min' => ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'су'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Pablo Saratxaga pablo@mandriva.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'MM/DD/YY',
    ],
    'months' => ['ᔮᓄᐊᓕ', 'ᕕᕗᐊᓕ', 'ᒪᔅᓯ', 'ᐃᐳᓗ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚᐃ', 'ᐊᒋᓯ', 'ᓯᑎᕙ', 'ᐊᑦᑐᕙ', 'ᓄᕕᕙ', 'ᑎᓯᕝᕙ'],
    'months_short' => ['ᔮᓄ', 'ᕕᕗ', 'ᒪᔅ', 'ᐃᐳ', 'ᒪᐃ', 'ᔪᓂ', 'ᔪᓚ', 'ᐊᒋ', 'ᓯᑎ', 'ᐊᑦ', 'ᓄᕕ', 'ᑎᓯ'],
    'weekdays' => ['ᓈᑦᑎᖑᔭᕐᕕᒃ', 'ᓇᒡᒐᔾᔭᐅ', 'ᓇᒡᒐᔾᔭᐅᓕᖅᑭᑦ', 'ᐱᖓᓲᓕᖅᓯᐅᑦ', 'ᕿᑎᖅᑰᑦ', 'ᐅᓪᓗᕈᓘᑐᐃᓇᖅ', 'ᓯᕙᑖᕕᒃ'],
    'weekdays_short' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'],
    'weekdays_min' => ['ᓈ', 'ᓇ', 'ᓕ', 'ᐱ', 'ᕿ', 'ᐅ', 'ᓯ'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => ':count ᐅᑭᐅᖅ',
    'y' => ':count ᐅᑭᐅᖅ',
    'a_year' => ':count ᐅᑭᐅᖅ',

    'month' => ':count qaammat',
    'm' => ':count qaammat',
    'a_month' => ':count qaammat',

    'week' => ':count sapaatip akunnera',
    'w' => ':count sapaatip akunnera',
    'a_week' => ':count sapaatip akunnera',

    'day' => ':count ulloq',
    'd' => ':count ulloq',
    'a_day' => ':count ulloq',

    'hour' => ':count ikarraq',
    'h' => ':count ikarraq',
    'a_hour' => ':count ikarraq',

    'minute' => ':count titiqqaralaaq', // less reliable
    'min' => ':count titiqqaralaaq', // less reliable
    'a_minute' => ':count titiqqaralaaq', // less reliable

    'second' => ':count marluk', // less reliable
    's' => ':count marluk', // less reliable
    'a_second' => ':count marluk', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 */
return [
    'year' => '{1}ⴰⵙⴳⴰⵙ|:count ⵉⵙⴳⴰⵙⵏ',
    'month' => '{1}ⴰⵢoⵓⵔ|:count ⵉⵢⵢⵉⵔⵏ',
    'week' => ':count ⵉⵎⴰⵍⴰⵙⵙ',
    'day' => '{1}ⴰⵙⵙ|:count oⵙⵙⴰⵏ',
    'hour' => '{1}ⵙⴰⵄⴰ|:count ⵜⴰⵙⵙⴰⵄⵉⵏ',
    'minute' => '{1}ⵎⵉⵏⵓⴺ|:count ⵎⵉⵏⵓⴺ',
    'second' => '{1}ⵉⵎⵉⴽ|:count ⵉⵎⵉⴽ',
    'ago' => 'ⵢⴰⵏ :time',
    'from_now' => 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ :time',
    'diff_today' => 'ⴰⵙⴷⵅ',
    'diff_yesterday' => 'ⴰⵚⴰⵏⵜ',
    'diff_yesterday_regexp' => 'ⴰⵚⴰⵏⵜ(?:\\s+ⴴ)?',
    'diff_tomorrow' => 'ⴰⵙⴽⴰ',
    'diff_tomorrow_regexp' => 'ⴰⵙⴽⴰ(?:\\s+ⴴ)?',
    'diff_today_regexp' => 'ⴰⵙⴷⵅ(?:\\s+ⴴ)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[ⴰⵙⴷⵅ ⴴ] LT',
        'nextDay' => '[ⴰⵙⴽⴰ ⴴ] LT',
        'nextWeek' => 'dddd [ⴴ] LT',
        'lastDay' => '[ⴰⵚⴰⵏⵜ ⴴ] LT',
        'lastWeek' => 'dddd [ⴴ] LT',
        'sameElse' => 'L',
    ],
    'months' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'],
    'months_short' => ['ⵉⵏⵏⴰⵢⵔ', 'ⴱⵕⴰⵢⵕ', 'ⵎⴰⵕⵚ', 'ⵉⴱⵔⵉⵔ', 'ⵎⴰⵢⵢⵓ', 'ⵢⵓⵏⵢⵓ', 'ⵢⵓⵍⵢⵓⵣ', 'ⵖⵓⵛⵜ', 'ⵛⵓⵜⴰⵏⴱⵉⵔ', 'ⴽⵟⵓⴱⵕ', 'ⵏⵓⵡⴰⵏⴱⵉⵔ', 'ⴷⵓⵊⵏⴱⵉⵔ'],
    'weekdays' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
    'weekdays_short' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
    'weekdays_min' => ['ⴰⵙⴰⵎⴰⵙ', 'ⴰⵢⵏⴰⵙ', 'ⴰⵙⵉⵏⴰⵙ', 'ⴰⴽⵔⴰⵙ', 'ⴰⴽⵡⴰⵙ', 'ⴰⵙⵉⵎⵡⴰⵙ', 'ⴰⵙⵉⴹⵢⴰⵙ'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'weekend' => [5, 6],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/kw_GB.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ko.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Kristian Sakarisson
 * - François B
 * - JD Isaacks
 * - Sverri Mohr Olsen
 */
return [
    'year' => 'eitt ár|:count ár',
    'y' => ':count ár|:count ár',
    'month' => 'ein mánaði|:count mánaðir',
    'm' => ':count mánaður|:count mánaðir',
    'week' => ':count vika|:count vikur',
    'w' => ':count vika|:count vikur',
    'day' => 'ein dagur|:count dagar',
    'd' => ':count dag|:count dagar',
    'hour' => 'ein tími|:count tímar',
    'h' => ':count tími|:count tímar',
    'minute' => 'ein minutt|:count minuttir',
    'min' => ':count minutt|:count minuttir',
    'second' => 'fá sekund|:count sekundir',
    's' => ':count sekund|:count sekundir',
    'ago' => ':time síðani',
    'from_now' => 'um :time',
    'after' => ':time aftaná',
    'before' => ':time áðrenn',
    'diff_today' => 'Í',
    'diff_yesterday' => 'Í',
    'diff_yesterday_regexp' => 'Í(?:\\s+gjár)?(?:\\s+kl.)?',
    'diff_tomorrow' => 'Í',
    'diff_tomorrow_regexp' => 'Í(?:\\s+morgin)?(?:\\s+kl.)?',
    'diff_today_regexp' => 'Í(?:\\s+dag)?(?:\\s+kl.)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D. MMMM, YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Í dag kl.] LT',
        'nextDay' => '[Í morgin kl.] LT',
        'nextWeek' => 'dddd [kl.] LT',
        'lastDay' => '[Í gjár kl.] LT',
        'lastWeek' => '[síðstu] dddd [kl] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['januar', 'februar', 'mars', 'apríl', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
    'weekdays' => ['sunnudagur', 'mánadagur', 'týsdagur', 'mikudagur', 'hósdagur', 'fríggjadagur', 'leygardagur'],
    'weekdays_short' => ['sun', 'mán', 'týs', 'mik', 'hós', 'frí', 'ley'],
    'weekdays_min' => ['su', 'má', 'tý', 'mi', 'hó', 'fr', 'le'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' og '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ga.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/vi.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ru.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/gom_Latn.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hans.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Z.MU.', 'Z.MW.'],
    'weekdays' => ['Ku w’indwi', 'Ku wa mbere', 'Ku wa kabiri', 'Ku wa gatatu', 'Ku wa kane', 'Ku wa gatanu', 'Ku wa gatandatu'],
    'weekdays_short' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
    'weekdays_min' => ['cu.', 'mbe.', 'kab.', 'gtu.', 'kan.', 'gnu.', 'gnd.'],
    'months' => ['Nzero', 'Ruhuhuma', 'Ntwarante', 'Ndamukiza', 'Rusama', 'Ruheshi', 'Mukakaro', 'Nyandagaro', 'Nyakanga', 'Gitugutu', 'Munyonyo', 'Kigarama'],
    'months_short' => ['Mut.', 'Gas.', 'Wer.', 'Mat.', 'Gic.', 'Kam.', 'Nya.', 'Kan.', 'Nze.', 'Ukw.', 'Ugu.', 'Uku.'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'year' => 'imyaka :count',
    'y' => 'imyaka :count',
    'a_year' => 'imyaka :count',

    'month' => 'amezi :count',
    'm' => 'amezi :count',
    'a_month' => 'amezi :count',

    'week' => 'indwi :count',
    'w' => 'indwi :count',
    'a_week' => 'indwi :count',

    'day' => 'imisi :count',
    'd' => 'imisi :count',
    'a_day' => 'imisi :count',

    'hour' => 'amasaha :count',
    'h' => 'amasaha :count',
    'a_hour' => 'amasaha :count',

    'minute' => 'iminuta :count',
    'min' => 'iminuta :count',
    'a_minute' => 'iminuta :count',

    'second' => 'inguvu :count', // less reliable
    's' => 'inguvu :count', // less reliable
    'a_second' => 'inguvu :count', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/kl_GL.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/tt_RU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/shn_MM.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/tk_TM.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

$months = [
    'ޖަނަވަރީ',
    'ފެބުރުވަރީ',
    'މާރިޗު',
    'އެޕްރީލް',
    'މޭ',
    'ޖޫން',
    'ޖުލައި',
    'އޮގަސްޓު',
    'ސެޕްޓެންބަރު',
    'އޮކްޓޫބަރު',
    'ނޮވެންބަރު',
    'ޑިސެންބަރު',
];

$weekdays = [
    'އާދިއްތަ',
    'ހޯމަ',
    'އަންގާރަ',
    'ބުދަ',
    'ބުރާސްފަތި',
    'ހުކުރު',
    'ހޮނިހިރު',
];

/*
 * Authors:
 * - Josh Soref
 * - Jawish Hameed
 * - Saiph Muhammad
 */
return [
    'year' => ':count '.'އަހަރު',
    'a_year' => '{1}'.'އަހަރެއް'.'|:count '.'އަހަރު',
    'month' => ':count '.'މަސް',
    'a_month' => '{1}'.'މަހެއް'.'|:count '.'މަސް',
    'week' => ':count '.'ހަފްތާ',
    'a_week' => '{1}'.'ސިކުންތުކޮޅެއް'.'|:count '.'ހަފްތާ',
    'day' => ':count '.'ދުވަސް',
    'a_day' => '{1}'.'ދުވަހެއް'.'|:count '.'ދުވަސް',
    'hour' => ':count '.'ގަޑިއިރު',
    'a_hour' => '{1}'.'ގަޑިއިރެއް'.'|:count '.'ގަޑިއިރު',
    'minute' => ':count '.'މިނިޓު',
    'a_minute' => '{1}'.'މިނިޓެއް'.'|:count '.'މިނިޓު',
    'second' => ':count '.'ސިކުންތު',
    'a_second' => '{1}'.'ސިކުންތުކޮޅެއް'.'|:count '.'ސިކުންތު',
    'ago' => 'ކުރިން :time',
    'from_now' => 'ތެރޭގައި :time',
    'after' => ':time ފަހުން',
    'before' => ':time ކުރި',
    'diff_yesterday' => 'އިއްޔެ',
    'diff_today' => 'މިއަދު',
    'diff_tomorrow' => 'މާދަމާ',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[މިއަދު] LT',
        'nextDay' => '[މާދަމާ] LT',
        'nextWeek' => 'dddd LT',
        'lastDay' => '[އިއްޔެ] LT',
        'lastWeek' => '[ފާއިތުވި] dddd LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['މކ', 'މފ'],
    'months' => $months,
    'months_short' => $months,
    'weekdays' => $weekdays,
    'weekdays_short' => $weekdays,
    'weekdays_min' => ['އާދި', 'ހޯމަ', 'އަން', 'ބުދަ', 'ބުރާ', 'ހުކު', 'ހޮނި'],
    'list' => [', ', ' އަދި '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/bo.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/id.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/te.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/byn_ER.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Pablo Saratxaga pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['yanvar', 'fevral', 'mart', 'aprel', 'may', 'iyun', 'iyul', 'avqust', 'sentyabr', 'oktyabr', 'noyabr', 'dekabr'],
    'months_short' => ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyn', 'İyl', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
    'weekdays' => ['bazar günü', 'birinci gün', 'ikinci gün', 'üçüncü gün', 'dördüncü gün', 'beşinci gün', 'altıncı gün'],
    'weekdays_short' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
    'weekdays_min' => ['baz', 'bir', 'iki', 'üçü', 'dör', 'beş', 'alt'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'OY/OM/OD',
    ],
    'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
    'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مئی', 'ژوئن', 'جولای', 'آقۇست', 'سپتامبر', 'اوْکتوْبر', 'نوْوامبر', 'دسامبر'],
    'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
    'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
    'weekdays_min' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چارشنبه', 'جۆمعه آخشامی', 'جۆمعه', 'شنبه'],
    'first_day_of_week' => 6,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/mk.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fr.php', [
    'first_day_of_week' => 6,
    'weekend' => [5, 6],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'dddd D MMMM YYYY h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Joshua Brooks
 * - François B
 */
return [
    'year' => 'tinan :count',
    'a_year' => '{1}tinan ida|tinan :count',
    'month' => 'fulan :count',
    'a_month' => '{1}fulan ida|fulan :count',
    'week' => 'semana :count',
    'a_week' => '{1}semana ida|semana :count',
    'day' => 'loron :count',
    'a_day' => '{1}loron ida|loron :count',
    'hour' => 'oras :count',
    'a_hour' => '{1}oras ida|oras :count',
    'minute' => 'minutu :count',
    'a_minute' => '{1}minutu ida|minutu :count',
    'second' => 'segundu :count',
    'a_second' => '{1}segundu balun|segundu :count',
    'ago' => ':time liuba',
    'from_now' => 'iha :time',
    'diff_yesterday' => 'Horiseik',
    'diff_yesterday_regexp' => 'Horiseik(?:\\s+iha)?',
    'diff_today' => 'Ohin',
    'diff_today_regexp' => 'Ohin(?:\\s+iha)?',
    'diff_tomorrow' => 'Aban',
    'diff_tomorrow_regexp' => 'Aban(?:\\s+iha)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Ohin iha] LT',
        'nextDay' => '[Aban iha] LT',
        'nextWeek' => 'dddd [iha] LT',
        'lastDay' => '[Horiseik iha] LT',
        'lastWeek' => 'dddd [semana kotuk] [iha] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberº',
    'months' => ['Janeiru', 'Fevereiru', 'Marsu', 'Abril', 'Maiu', 'Juñu', 'Jullu', 'Agustu', 'Setembru', 'Outubru', 'Novembru', 'Dezembru'],
    'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
    'weekdays' => ['Domingu', 'Segunda', 'Tersa', 'Kuarta', 'Kinta', 'Sesta', 'Sabadu'],
    'weekdays_short' => ['Dom', 'Seg', 'Ters', 'Kua', 'Kint', 'Sest', 'Sab'],
    'weekdays_min' => ['Do', 'Seg', 'Te', 'Ku', 'Ki', 'Ses', 'Sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/lzh_TW.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/lg_UG.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['Subbaahi', 'Zaarikay b'],
    'weekdays' => ['Alhadi', 'Atinni', 'Atalaata', 'Alarba', 'Alhamisi', 'Alzuma', 'Asibti'],
    'weekdays_short' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    'weekdays_min' => ['Alh', 'Ati', 'Ata', 'Ala', 'Alm', 'Alz', 'Asi'],
    'months' => ['Žanwiye', 'Feewiriye', 'Marsi', 'Awiril', 'Me', 'Žuweŋ', 'Žuyye', 'Ut', 'Sektanbur', 'Oktoobur', 'Noowanbur', 'Deesanbur'],
    'months_short' => ['Žan', 'Fee', 'Mar', 'Awi', 'Me', 'Žuw', 'Žuy', 'Ut', 'Sek', 'Okt', 'Noo', 'Dee'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'year' => ':count hari', // less reliable
    'y' => ':count hari', // less reliable
    'a_year' => ':count hari', // less reliable

    'week' => ':count alzuma', // less reliable
    'w' => ':count alzuma', // less reliable
    'a_week' => ':count alzuma', // less reliable

    'second' => ':count atinni', // less reliable
    's' => ':count atinni', // less reliable
    'a_second' => ':count atinni', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - abhimanyu003
 * - Josh Soref
 * - JD Isaacks
 */
return [
    'year' => 'एक वर्ष|:count वर्ष',
    'y' => '1 वर्ष|:count वर्षों',
    'month' => 'एक महीने|:count महीने',
    'm' => '1 माह|:count महीने',
    'week' => '1 सप्ताह|:count सप्ताह',
    'w' => '1 सप्ताह|:count सप्ताह',
    'day' => 'एक दिन|:count दिन',
    'd' => '1 दिन|:count दिनों',
    'hour' => 'एक घंटा|:count घंटे',
    'h' => '1 घंटा|:count घंटे',
    'minute' => 'एक मिनट|:count मिनट',
    'min' => '1 मिनट|:count मिनटों',
    'second' => 'कुछ ही क्षण|:count सेकंड',
    's' => '1 सेकंड|:count सेकंड',
    'ago' => ':time पहले',
    'from_now' => ':time में',
    'after' => ':time के बाद',
    'before' => ':time के पहले',
    'diff_now' => 'अब',
    'diff_today' => 'आज',
    'diff_yesterday' => 'कल',
    'diff_tomorrow' => 'कल',
    'formats' => [
        'LT' => 'A h:mm बजे',
        'LTS' => 'A h:mm:ss बजे',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, A h:mm बजे',
        'LLLL' => 'dddd, D MMMM YYYY, A h:mm बजे',
    ],
    'calendar' => [
        'sameDay' => '[आज] LT',
        'nextDay' => '[कल] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[कल] LT',
        'lastWeek' => '[पिछले] dddd, LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'रात';
        }
        if ($hour < 10) {
            return 'सुबह';
        }
        if ($hour < 17) {
            return 'दोपहर';
        }
        if ($hour < 20) {
            return 'शाम';
        }

        return 'रात';
    },
    'months' => ['जनवरी', 'फ़रवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर'],
    'months_short' => ['जन.', 'फ़र.', 'मार्च', 'अप्रै.', 'मई', 'जून', 'जुल.', 'अग.', 'सित.', 'अक्टू.', 'नव.', 'दिस.'],
    'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरूवार', 'शुक्रवार', 'शनिवार'],
    'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरू', 'शुक्र', 'शनि'],
    'weekdays_min' => ['र', 'सो', 'मं', 'बु', 'गु', 'शु', 'श'],
    'list' => [', ', ' और '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['v.M.', 'n.M.'],
    'weekdays' => ['Sunndaach', 'Mohndaach', 'Dinnsdaach', 'Metwoch', 'Dunnersdaach', 'Friidaach', 'Samsdaach'],
    'weekdays_short' => ['Su.', 'Mo.', 'Di.', 'Me.', 'Du.', 'Fr.', 'Sa.'],
    'weekdays_min' => ['Su', 'Mo', 'Di', 'Me', 'Du', 'Fr', 'Sa'],
    'months' => ['Jannewa', 'Fäbrowa', 'Määz', 'Aprell', 'Mai', 'Juuni', 'Juuli', 'Oujoß', 'Septämber', 'Oktohber', 'Novämber', 'Dezämber'],
    'months_short' => ['Jan', 'Fäb', 'Mäz', 'Apr', 'Mai', 'Jun', 'Jul', 'Ouj', 'Säp', 'Okt', 'Nov', 'Dez'],
    'months_short_standalone' => ['Jan.', 'Fäb.', 'Mäz.', 'Apr.', 'Mai', 'Jun.', 'Jul.', 'Ouj.', 'Säp.', 'Okt.', 'Nov.', 'Dez.'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D. M. YYYY',
        'LL' => 'D. MMM. YYYY',
        'LLL' => 'D. MMMM YYYY HH:mm',
        'LLLL' => 'dddd, [dä] D. MMMM YYYY HH:mm',
    ],

    'year' => ':count Johr',
    'y' => ':count Johr',
    'a_year' => ':count Johr',

    'month' => ':count Moohnd',
    'm' => ':count Moohnd',
    'a_month' => ':count Moohnd',

    'week' => ':count woch',
    'w' => ':count woch',
    'a_week' => ':count woch',

    'day' => ':count Daach',
    'd' => ':count Daach',
    'a_day' => ':count Daach',

    'hour' => ':count Uhr',
    'h' => ':count Uhr',
    'a_hour' => ':count Uhr',

    'minute' => ':count Menutt',
    'min' => ':count Menutt',
    'a_minute' => ':count Menutt',

    'second' => ':count Sekůndt',
    's' => ':count Sekůndt',
    'a_second' => ':count Sekůndt',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - information from Kenneth Christiansen Kenneth Christiansen, Pablo Saratxaga kenneth@gnu.org, pablo@mandriva.com
 */
return array_replace_recursive(require __DIR__.'/fy.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Jaunuwoa', 'Februwoa', 'Moaz', 'Aprell', 'Mai', 'Juni', 'Juli', 'August', 'Septamba', 'Oktoba', 'Nowamba', 'Dezamba'],
    'months_short' => ['Jan', 'Feb', 'Moz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Now', 'Dez'],
    'weekdays' => ['Sinndag', 'Mondag', 'Dingsdag', 'Meddwäakj', 'Donnadag', 'Friedag', 'Sinnowend'],
    'weekdays_short' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
    'weekdays_min' => ['Sdg', 'Mdg', 'Dsg', 'Mwk', 'Ddg', 'Fdg', 'Swd'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    'weekdays' => ['Sambata', 'Sanyo', 'Maakisanyo', 'Roowe', 'Hamuse', 'Arbe', 'Qidaame'],
    'weekdays_short' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'],
    'weekdays_min' => ['Sam', 'San', 'Mak', 'Row', 'Ham', 'Arb', 'Qid'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['soodo', 'hawwaro'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - sheriffmarley
 * - Timo
 * - Michael Hohl
 * - Namoshek
 * - Bernhard Baumrock (BernhardBaumrock)
 */
return array_replace_recursive(require __DIR__.'/de.php', [
    'months' => [
        0 => 'Jänner',
    ],
    'months_short' => [
        0 => 'Jän',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - http://www.uyip.org/ Pablo Saratxaga pablo@mandrakesoft.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'year' => '{1}:count יאר|{0}:count יאר|[-Inf,Inf]:count יאר',
    'a_year' => '{1}א יאר|{0}:count יאר|[-Inf,Inf]:count יאר',
    'y' => ':count יאר',
    'month' => '{1}:count חודש|{0}:count חדשים|[-Inf,Inf]:count חדשים',
    'a_month' => '{1}א חודש|{0}:count חדשים|[-Inf,Inf]:count חדשים',
    'm' => '{1}:count חודש|{0}:count חדשים|[-Inf,Inf]:count חדשים',
    'week' => '{1}:count וואך|{0}:count וואכן|[-Inf,Inf]:count וואכן',
    'a_week' => '{1}א וואך|{0}:count וואכן|[-Inf,Inf]:count וואכן',
    'w' => ':count וואך',
    'day' => '{1}:count טאג|{0}:count טעג|[-Inf,Inf]:count טעג',
    'a_day' => '{1}א טאג|{0}:count טעג|[-Inf,Inf]:count טעג',
    'd' => ':count טאג',
    'hour'   => ':count שעה',
    'a_hour' => 'א שעה',
    'h' => ':count שעה',
    'minute' => '{1}:count מינוט|{0}:count מינוט|[-Inf,Inf]:count מינוט',
    'a_minute' => '{1}א מינוט|{0}:count מינוט|[-Inf,Inf]:count מינוט',
    'min' => ':count מינוט',
    'second' => '{1}:count סעקונדע|{0}:count סעקונדעס|[-Inf,Inf]:count סעקונדעס',
    'a_second' => '{0,1}א סעקונדע|[-Inf,Inf]:count סעקונדעס',
    's' => ':count סעק',
    'millisecond' => '{1}:count מילי-סעקונדע|{0}:count מילי-סעקונדעס|[-Inf,Inf]:count מילי-סעקונדעס',
    'a_millisecond' => '{1}א מילי-סעקונדע|{0}:count מילי-סעקונדעס|[-Inf,Inf]:count מילי-סעקונדעס',
    'ms' => ':count מס',
    'microsecond' => '{1}:count מיקרא-סעקונדע|{0}:count מיקרא-סעקונדעס|[-Inf,Inf]:count מיקרא-סעקונדעס',
    'a_microsecond' => '{1}א מיקרא-סעקונדע|{0}:count מיקרא-סעקונדעס|[-Inf,Inf]:count מיקרא-סעקונדעס',
    'µs' => ':count מיקרא',
    'ago' => ':time פון יעצט',
    'from_now' => ':time ארום',
    'after' => ':time נאך',
    'before' => ':time פאר',
    'diff_now' => 'ממש יעצט',
    'diff_today' => 'היינט',
    'diff_yesterday' => 'נעכטן',
    'diff_tomorrow' => 'מארגן',
    'diff_before_yesterday' => 'אייער-נעכטן',
    'diff_after_tomorrow' => 'איבער-מארגן',
    'period_recurrences' => '{1}איין מאל|{0}:count מאל|[-Inf,Inf]:count מאל',
    'period_interval' => 'יעדע :interval',
    'period_start_date' => 'פון :date',
    'period_end_date' => 'ביז :date',
    'months' => ['יאנואר', 'פעברואר', 'מארטש', 'אפריל', 'מאי', 'יוני', 'יולי', 'אויגוסט', 'סעפטעמבער', 'אקטאבער', 'נאוועמבער', 'דעצעמבער'],
    'months_short' => ['יאנ\'', 'פעב\'', 'מאר\'', 'אפר\'', 'מאי', 'יוני', 'יולי', 'אויג\'', 'סעפ\'', 'אקט\'', 'נאו\'', 'דעצ\''],
    'weekdays' => ['זונטאג', 'מאנטאג', 'דינסטאג', 'מיטוואך', 'דאנערשטאג', 'פרייטאג', 'שבת'],
    'weekdays_short' => ['זונ\'', 'מאנ\'', 'דינ\'', 'מיט\'', 'דאנ\'', 'פריי\'', 'שבת'],
    'weekdays_min' => ['ז\'', 'מ\'', 'ד\'', 'מ\'', 'ד\'', 'ו\'', 'ש\''],
    'ordinal' => static function ($number) {
        return $number.'טע';
    },
    'list' => [', ', ' און '],
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/az.php', [
    'weekdays' => ['базар', 'базар ертәси', 'чәршәнбә ахшамы', 'чәршәнбә', 'ҹүмә ахшамы', 'ҹүмә', 'шәнбә'],
    'weekdays_short' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'],
    'weekdays_min' => ['Б.', 'Б.Е.', 'Ч.А.', 'Ч.', 'Ҹ.А.', 'Ҹ.', 'Ш.'],
    'months' => ['јанвар', 'феврал', 'март', 'апрел', 'май', 'ијун', 'ијул', 'август', 'сентјабр', 'октјабр', 'нојабр', 'декабр'],
    'months_short' => ['јан', 'фев', 'мар', 'апр', 'май', 'ијн', 'ијл', 'авг', 'сен', 'окт', 'ној', 'дек'],
    'meridiem' => ['а', 'п'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Rinat Norkin Pablo Saratxaga, Rinat Norkin pablo@mandrakesoft.com, rinat@taif.ru
 */
return [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'DD MMM, HH:mm',
        'LLLL' => 'DD MMMM YYYY, HH:mm',
    ],
    'months' => ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
    'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'weekdays' => ['якшәмбе', 'дышәмбе', 'сишәмбе', 'чәршәәмбе', 'пәнҗешмбе', 'җомга', 'шимбә'],
    'weekdays_short' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'],
    'weekdays_min' => ['якш', 'дыш', 'сиш', 'чәрш', 'пәнҗ', 'җом', 'шим'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'year' => ':count ел',
    'month' => ':count ай',
    'week' => ':count атна',
    'day' => ':count көн',
    'hour' => ':count сәгать',
    'minute' => ':count минут',
    'second' => ':count секунд',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - International Components for Unicode    akhilesh.k@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'dddd DD MMM YYYY',
    ],
    'months' => ['Sānuali', 'Fēpueli', 'Maʻasi', 'ʻEpeleli', 'Mē', 'Sune', 'Siulai', 'ʻAokosi', 'Sepitema', 'ʻOkatopa', 'Nōvema', 'Tīsema'],
    'months_short' => ['Sān', 'Fēp', 'Maʻa', 'ʻEpe', 'Mē', 'Sun', 'Siu', 'ʻAok', 'Sep', 'ʻOka', 'Nōv', 'Tīs'],
    'weekdays' => ['Sāpate', 'Mōnite', 'Tūsite', 'Pulelulu', 'Tuʻapulelulu', 'Falaite', 'Tokonaki'],
    'weekdays_short' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
    'weekdays_min' => ['Sāp', 'Mōn', 'Tūs', 'Pul', 'Tuʻa', 'Fal', 'Tok'],
    'meridiem' => ['hengihengi', 'efiafi'],

    'year' => ':count fitu', // less reliable
    'y' => ':count fitu', // less reliable
    'a_year' => ':count fitu', // less reliable

    'month' => ':count mahina', // less reliable
    'm' => ':count mahina', // less reliable
    'a_month' => ':count mahina', // less reliable

    'week' => ':count Sapate', // less reliable
    'w' => ':count Sapate', // less reliable
    'a_week' => ':count Sapate', // less reliable

    'day' => ':count ʻaho', // less reliable
    'd' => ':count ʻaho', // less reliable
    'a_day' => ':count ʻaho', // less reliable

    'hour' => ':count houa',
    'h' => ':count houa',
    'a_hour' => ':count houa',

    'minute' => ':count miniti',
    'min' => ':count miniti',
    'a_minute' => ':count miniti',

    'second' => ':count sekoni',
    's' => ':count sekoni',
    'a_second' => ':count sekoni',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Qunxa Garablu', 'Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Liiqen', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
    'months_short' => ['qun', 'nah', 'cig', 'agd', 'cax', 'qas', 'qad', 'leq', 'way', 'dit', 'xim', 'kax'],
    'weekdays' => ['Acaada', 'Etleeni', 'Talaata', 'Arbaqa', 'Kamiisi', 'Gumqata', 'Sabti'],
    'weekdays_short' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'],
    'weekdays_min' => ['aca', 'etl', 'tal', 'arb', 'kam', 'gum', 'sab'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['saaku', 'carra'],

    'year' => ':count gaqambo', // less reliable
    'y' => ':count gaqambo', // less reliable
    'a_year' => ':count gaqambo', // less reliable

    'month' => ':count àlsa',
    'm' => ':count àlsa',
    'a_month' => ':count àlsa',

    'day' => ':count saaku', // less reliable
    'd' => ':count saaku', // less reliable
    'a_day' => ':count saaku', // less reliable

    'hour' => ':count ayti', // less reliable
    'h' => ':count ayti', // less reliable
    'a_hour' => ':count ayti', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/or_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/de.php', [
    'formats' => [
        'L' => 'YYYY-MM-DD',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/gsw.php', [
    'meridiem' => ['vorm.', 'nam.'],
    'months' => ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Auguscht', 'Septämber', 'Oktoober', 'Novämber', 'Dezämber'],
    'first_day_of_week' => 1,
    'formats' => [
        'LLL' => 'Do MMMM YYYY HH:mm',
        'LLLL' => 'dddd, Do MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Rwanda Steve Murphy murf@e-tools.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Mutarama', 'Gashyantare', 'Werurwe', 'Mata', 'Gicuransi', 'Kamena', 'Nyakanga', 'Kanama', 'Nzeli', 'Ukwakira', 'Ugushyingo', 'Ukuboza'],
    'months_short' => ['Mut', 'Gas', 'Wer', 'Mat', 'Gic', 'Kam', 'Nya', 'Kan', 'Nze', 'Ukw', 'Ugu', 'Uku'],
    'weekdays' => ['Ku cyumweru', 'Kuwa mbere', 'Kuwa kabiri', 'Kuwa gatatu', 'Kuwa kane', 'Kuwa gatanu', 'Kuwa gatandatu'],
    'weekdays_short' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'],
    'weekdays_min' => ['Mwe', 'Mbe', 'Kab', 'Gtu', 'Kan', 'Gnu', 'Gnd'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'second' => ':count vuna', // less reliable
    's' => ':count vuna', // less reliable
    'a_second' => ':count vuna', // less reliable

    'year' => 'aka :count',
    'y' => 'aka :count',
    'a_year' => 'aka :count',

    'month' => 'ezi :count',
    'm' => 'ezi :count',
    'a_month' => 'ezi :count',

    'week' => ':count icyumweru',
    'w' => ':count icyumweru',
    'a_week' => ':count icyumweru',

    'day' => ':count nsi',
    'd' => ':count nsi',
    'a_day' => ':count nsi',

    'hour' => 'saha :count',
    'h' => 'saha :count',
    'a_hour' => 'saha :count',

    'minute' => ':count -nzinya',
    'min' => ':count -nzinya',
    'a_minute' => ':count -nzinya',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/tr.php', [
    'weekdays_short' => ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'],
    'weekdays_min' => ['Pa', 'Pt', 'Sa', 'Ça', 'Pe', 'Cu', 'Ct'],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'D.MM.YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm a',
        'LLLL' => 'D MMMM YYYY dddd h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YY',
        'LL' => 'MMMM DD, YYYY',
        'LLL' => 'DD MMM HH:mm',
        'LLLL' => 'MMMM DD, YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/wal_ET.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - Nasser Ghiasi
 * - JD Isaacks
 * - Hossein Jabbari
 * - nimamo
 * - hafezdivandari
 * - Hassan Pezeshk (hpez)
 */
return [
    'year' => ':count سال',
    'a_year' => 'یک سال'.'|:count '.'سال',
    'y' => ':count سال',
    'month' => ':count ماه',
    'a_month' => 'یک ماه'.'|:count '.'ماه',
    'm' => ':count ماه',
    'week' => ':count هفته',
    'a_week' => 'یک هفته'.'|:count '.'هفته',
    'w' => ':count هفته',
    'day' => ':count روز',
    'a_day' => 'یک روز'.'|:count '.'روز',
    'd' => ':count روز',
    'hour' => ':count ساعت',
    'a_hour' => 'یک ساعت'.'|:count '.'ساعت',
    'h' => ':count ساعت',
    'minute' => ':count دقیقه',
    'a_minute' => 'یک دقیقه'.'|:count '.'دقیقه',
    'min' => ':count دقیقه',
    'second' => ':count ثانیه',
    's' => ':count ثانیه',
    'ago' => ':time پیش',
    'from_now' => ':time دیگر',
    'after' => ':time پس از',
    'before' => ':time پیش از',
    'diff_now' => 'اکنون',
    'diff_today' => 'امروز',
    'diff_today_regexp' => 'امروز(?:\\s+ساعت)?',
    'diff_yesterday' => 'دیروز',
    'diff_yesterday_regexp' => 'دیروز(?:\\s+ساعت)?',
    'diff_tomorrow' => 'فردا',
    'diff_tomorrow_regexp' => 'فردا(?:\\s+ساعت)?',
    'formats' => [
        'LT' => 'OH:Om',
        'LTS' => 'OH:Om:Os',
        'L' => 'OD/OM/OY',
        'LL' => 'OD MMMM OY',
        'LLL' => 'OD MMMM OY OH:Om',
        'LLLL' => 'dddd, OD MMMM OY OH:Om',
    ],
    'calendar' => [
        'sameDay' => '[امروز ساعت] LT',
        'nextDay' => '[فردا ساعت] LT',
        'nextWeek' => 'dddd [ساعت] LT',
        'lastDay' => '[دیروز ساعت] LT',
        'lastWeek' => 'dddd [پیش] [ساعت] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':timeم',
    'meridiem' => ['قبل از ظهر', 'بعد از ظهر'],
    'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
    'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
    'weekdays' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    'weekdays_short' => ['یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'],
    'weekdays_min' => ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'list' => ['، ', ' و '],
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰۴', '۰۵', '۰۶', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱۴', '۱۵', '۱۶', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲۴', '۲۵', '۲۶', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳۴', '۳۵', '۳۶', '۳۷', '۳۸', '۳۹', '۴۰', '۴۱', '۴۲', '۴۳', '۴۴', '۴۵', '۴۶', '۴۷', '۴۸', '۴۹', '۵۰', '۵۱', '۵۲', '۵۳', '۵۴', '۵۵', '۵۶', '۵۷', '۵۸', '۵۹', '۶۰', '۶۱', '۶۲', '۶۳', '۶۴', '۶۵', '۶۶', '۶۷', '۶۸', '۶۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷۴', '۷۵', '۷۶', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸۴', '۸۵', '۸۶', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹۴', '۹۵', '۹۶', '۹۷', '۹۸', '۹۹'],
    'months_short_standalone' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
    'weekend' => [5, 5],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/sw.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Pherekgong', 'Hlakola', 'Tlhakubele', 'Mmese', 'Motsheanong', 'Phupjane', 'Phupu', 'Phato', 'Leotse', 'Mphalane', 'Pudungwana', 'Tshitwe'],
    'months_short' => ['Phe', 'Hla', 'TlH', 'Mme', 'Mot', 'Jan', 'Upu', 'Pha', 'Leo', 'Mph', 'Pud', 'Tsh'],
    'weekdays' => ['Sontaha', 'Mantaha', 'Labobedi', 'Laboraro', 'Labone', 'Labohlano', 'Moqebelo'],
    'weekdays_short' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'],
    'weekdays_min' => ['Son', 'Mma', 'Bed', 'Rar', 'Ne', 'Hla', 'Moq'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'week' => ':count Sontaha', // less reliable
    'w' => ':count Sontaha', // less reliable
    'a_week' => ':count Sontaha', // less reliable

    'day' => ':count letsatsi', // less reliable
    'd' => ':count letsatsi', // less reliable
    'a_day' => ':count letsatsi', // less reliable

    'hour' => ':count sešupanako', // less reliable
    'h' => ':count sešupanako', // less reliable
    'a_hour' => ':count sešupanako', // less reliable

    'minute' => ':count menyane', // less reliable
    'min' => ':count menyane', // less reliable
    'a_minute' => ':count menyane', // less reliable

    'second' => ':count thusa', // less reliable
    's' => ':count thusa', // less reliable
    'a_second' => ':count thusa', // less reliable

    'year' => ':count selemo',
    'y' => ':count selemo',
    'a_year' => ':count selemo',

    'month' => ':count kgwedi',
    'm' => ':count kgwedi',
    'a_month' => ':count kgwedi',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hant.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY年MM月DD日',
    ],
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
    'weekdays' => ['禮拜日', '禮拜一', '禮拜二', '禮拜三', '禮拜四', '禮拜五', '禮拜六'],
    'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['上晝', '下晝'],

    'year' => ':count ngien11',
    'y' => ':count ngien11',
    'a_year' => ':count ngien11',

    'month' => ':count ngie̍t',
    'm' => ':count ngie̍t',
    'a_month' => ':count ngie̍t',

    'week' => ':count lî-pai',
    'w' => ':count lî-pai',
    'a_week' => ':count lî-pai',

    'day' => ':count ngit',
    'd' => ':count ngit',
    'a_day' => ':count ngit',

    'hour' => ':count sṳ̀',
    'h' => ':count sṳ̀',
    'a_hour' => ':count sṳ̀',

    'minute' => ':count fûn',
    'min' => ':count fûn',
    'a_minute' => ':count fûn',

    'second' => ':count miéu',
    's' => ':count miéu',
    'a_second' => ':count miéu',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/rw_RW.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/da.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ml.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ka.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ff.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ta.php', [
    'formats' => [
        'LT' => 'a h:mm',
        'LTS' => 'a h:mm:ss',
        'L' => 'D/M/yy',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM, YYYY, a h:mm',
        'LLLL' => 'dddd, D MMMM, YYYY, a h:mm',
    ],
    'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
    'months_short' => ['ஜன.', 'பிப்.', 'மார்.', 'ஏப்.', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக.', 'செப்.', 'அக்.', 'நவ.', 'டிச.'],
    'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
    'weekdays_short' => ['ஞாயி.', 'திங்.', 'செவ்.', 'புத.', 'வியா.', 'வெள்.', 'சனி'],
    'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'meridiem' => ['மு.ப', 'பி.ப'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Yoav Amit
 * - François B
 * - Mayank Badola
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Qunxa Garablu', 'Naharsi Kudo', 'Ciggilta Kudo', 'Agda Baxisso', 'Caxah Alsa', 'Qasa Dirri', 'Qado Dirri', 'Leqeeni', 'Waysu', 'Diteli', 'Ximoli', 'Kaxxa Garablu'],
    'months_short' => ['Qun', 'Nah', 'Cig', 'Agd', 'Cax', 'Qas', 'Qad', 'Leq', 'Way', 'Dit', 'Xim', 'Kax'],
    'weekdays' => ['Naba Sambat', 'Sani', 'Salus', 'Rabuq', 'Camus', 'Jumqata', 'Qunxa Sambat'],
    'weekdays_short' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
    'weekdays_min' => ['Nab', 'San', 'Sal', 'Rab', 'Cam', 'Jum', 'Qun'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['saaku', 'carra'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ses.php', [
    'meridiem' => ['Subbaahi', 'Zaarikay b'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/xh_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Nate Whittaker
 * - John MacAslan
 * - Chanintorn Asavavichairoj
 * - JD Isaacks
 * - ROKAISAKKON
 * - RO'KAISAKKON
 * - Andreas Möller
 * - nithisa
 */
return [
    'year' => ':count ปี',
    'y' => ':count ปี',
    'month' => ':count เดือน',
    'm' => ':count เดือน',
    'week' => ':count สัปดาห์',
    'w' => ':count สัปดาห์',
    'day' => ':count วัน',
    'd' => ':count วัน',
    'hour' => ':count ชั่วโมง',
    'h' => ':count ชั่วโมง',
    'minute' => ':count นาที',
    'min' => ':count นาที',
    'second' => ':count วินาที',
    'a_second' => '{1}ไม่กี่วินาที|[-Inf,Inf]:count วินาที',
    's' => ':count วินาที',
    'ago' => ':timeที่แล้ว',
    'from_now' => 'อีก :time',
    'after' => ':timeหลังจากนี้',
    'before' => ':timeก่อน',
    'diff_now' => 'ขณะนี้',
    'diff_today' => 'วันนี้',
    'diff_today_regexp' => 'วันนี้(?:\\s+เวลา)?',
    'diff_yesterday' => 'เมื่อวาน',
    'diff_yesterday_regexp' => 'เมื่อวานนี้(?:\\s+เวลา)?',
    'diff_tomorrow' => 'พรุ่งนี้',
    'diff_tomorrow_regexp' => 'พรุ่งนี้(?:\\s+เวลา)?',
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY เวลา H:mm',
        'LLLL' => 'วันddddที่ D MMMM YYYY เวลา H:mm',
    ],
    'calendar' => [
        'sameDay' => '[วันนี้ เวลา] LT',
        'nextDay' => '[พรุ่งนี้ เวลา] LT',
        'nextWeek' => 'dddd[หน้า เวลา] LT',
        'lastDay' => '[เมื่อวานนี้ เวลา] LT',
        'lastWeek' => '[วัน]dddd[ที่แล้ว เวลา] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => ['ก่อนเที่ยง', 'หลังเที่ยง'],
    'months' => ['มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน', 'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'],
    'months_short' => ['ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.', 'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'],
    'weekdays' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัสบดี', 'ศุกร์', 'เสาร์'],
    'weekdays_short' => ['อาทิตย์', 'จันทร์', 'อังคาร', 'พุธ', 'พฤหัส', 'ศุกร์', 'เสาร์'],
    'weekdays_min' => ['อา.', 'จ.', 'อ.', 'พ.', 'พฤ.', 'ศ.', 'ส.'],
    'list' => [', ', ' และ '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'formats' => [
        'L' => 'YYYY年MM月DD號',
    ],
    'months' => ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
    'months_short' => [' 1月', ' 2月', ' 3月', ' 4月', ' 5月', ' 6月', ' 7月', ' 8月', ' 9月', '10月', '11月', '12月'],
    'weekdays' => ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
    'weekdays_short' => ['日', '一', '二', '三', '四', '五', '六'],
    'weekdays_min' => ['日', '一', '二', '三', '四', '五', '六'],
    'meridiem' => ['上午', '下午'],

    'year' => ':count 年',
    'y' => ':count 年',
    'a_year' => ':count 年',

    'month' => ':count 月',
    'm' => ':count 月',
    'a_month' => ':count 月',

    'week' => ':count 周',
    'w' => ':count 周',
    'a_week' => ':count 周',

    'day' => ':count 白天',
    'd' => ':count 白天',
    'a_day' => ':count 白天',

    'hour' => ':count 小时',
    'h' => ':count 小时',
    'a_hour' => ':count 小时',

    'minute' => ':count 分钟',
    'min' => ':count 分钟',
    'a_minute' => ':count 分钟',

    'second' => ':count 秒',
    's' => ':count 秒',
    'a_second' => ':count 秒',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/bo.php', [
    'meridiem' => ['སྔ་དྲོ་', 'ཕྱི་དྲོ་'],
    'weekdays' => ['གཟའ་ཉི་མ་', 'གཟའ་ཟླ་བ་', 'གཟའ་མིག་དམར་', 'གཟའ་ལྷག་པ་', 'གཟའ་ཕུར་བུ་', 'གཟའ་པ་སངས་', 'གཟའ་སྤེན་པ་'],
    'weekdays_short' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'],
    'weekdays_min' => ['ཉི་མ་', 'ཟླ་བ་', 'མིག་དམར་', 'ལྷག་པ་', 'ཕུར་བུ་', 'པ་སངས་', 'སྤེན་པ་'],
    'months' => ['ཟླ་བ་དང་པོ', 'ཟླ་བ་གཉིས་པ', 'ཟླ་བ་གསུམ་པ', 'ཟླ་བ་བཞི་པ', 'ཟླ་བ་ལྔ་པ', 'ཟླ་བ་དྲུག་པ', 'ཟླ་བ་བདུན་པ', 'ཟླ་བ་བརྒྱད་པ', 'ཟླ་བ་དགུ་པ', 'ཟླ་བ་བཅུ་པ', 'ཟླ་བ་བཅུ་གཅིག་པ', 'ཟླ་བ་བཅུ་གཉིས་པ'],
    'months_short' => ['ཟླ་༡', 'ཟླ་༢', 'ཟླ་༣', 'ཟླ་༤', 'ཟླ་༥', 'ཟླ་༦', 'ཟླ་༧', 'ཟླ་༨', 'ཟླ་༩', 'ཟླ་༡༠', 'ཟླ་༡༡', 'ཟླ་༡༢'],
    'months_standalone' => ['ཟླ་བ་དང་པོ་', 'ཟླ་བ་གཉིས་པ་', 'ཟླ་བ་གསུམ་པ་', 'ཟླ་བ་བཞི་པ་', 'ཟླ་བ་ལྔ་པ་', 'ཟླ་བ་དྲུག་པ་', 'ཟླ་བ་བདུན་པ་', 'ཟླ་བ་བརྒྱད་པ་', 'ཟླ་བ་དགུ་པ་', 'ཟླ་བ་བཅུ་པ་', 'ཟླ་བ་བཅུ་གཅིག་པ་', 'ཟླ་བ་བཅུ་གཉིས་པ་'],
    'weekend' => [0, 0],
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'L' => 'YYYY-MM-DD',
        'LL' => 'YYYY ལོའི་MMMཚེས་D',
        'LLL' => 'སྤྱི་ལོ་YYYY MMMMའི་ཚེས་D h:mm a',
        'LLLL' => 'YYYY MMMMའི་ཚེས་D, dddd h:mm a',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'diff_before_yesterday' => 'antier',
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/nl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,

    'month' => ':count haŋwí', // less reliable
    'm' => ':count haŋwí', // less reliable
    'a_month' => ':count haŋwí', // less reliable

    'week' => ':count šakówiŋ', // less reliable
    'w' => ':count šakówiŋ', // less reliable
    'a_week' => ':count šakówiŋ', // less reliable

    'hour' => ':count maza škaŋškaŋ', // less reliable
    'h' => ':count maza škaŋškaŋ', // less reliable
    'a_hour' => ':count maza škaŋškaŋ', // less reliable

    'minute' => ':count číkʼala', // less reliable
    'min' => ':count číkʼala', // less reliable
    'a_minute' => ':count číkʼala', // less reliable

    'year' => ':count waníyetu',
    'y' => ':count waníyetu',
    'a_year' => ':count waníyetu',

    'day' => ':count aŋpétu',
    'd' => ':count aŋpétu',
    'a_day' => ':count aŋpétu',

    'second' => ':count icinuŋpa',
    's' => ':count icinuŋpa',
    'a_second' => ':count icinuŋpa',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hant.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/pt.php', [
    'formats' => [
        'LT' => 'h:mm a',
        'LTS' => 'h:mm:ss a',
        'LLL' => 'D [de] MMMM [de] YYYY, h:mm a',
        'LLLL' => 'dddd, D [de] MMMM [de] YYYY, h:mm a',
    ],
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጃንዩወሪ', 'ፌብሩወሪ', 'ማርች', 'ኤፕረል', 'ሜይ', 'ጁን', 'ጁላይ', 'ኦገስት', 'ሴፕቴምበር', 'ኦክተውበር', 'ኖቬምበር', 'ዲሴምበር'],
    'months_short' => ['ጃንዩ', 'ፌብሩ', 'ማርች', 'ኤፕረ', 'ሜይ ', 'ጁን ', 'ጁላይ', 'ኦገስ', 'ሴፕቴ', 'ኦክተ', 'ኖቬም', 'ዲሴም'],
    'weekdays' => ['ወጋ', 'ሳይኖ', 'ማቆሳኛ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ'],
    'weekdays_short' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '],
    'weekdays_min' => ['ወጋ ', 'ሳይኖ', 'ማቆሳ', 'አሩዋ', 'ሃሙሳ', 'አርባ', 'ቄራ '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ማለዶ', 'ቃማ'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - J.Yogaraj 94-777-315206 yogaraj.ubuntu@gmail.com
 */
return array_replace_recursive(require __DIR__.'/ta.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
    'months_short' => ['ஜன', 'பிப்', 'மார்', 'ஏப்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆக', 'செப்', 'அக்', 'நவ', 'டிச'],
    'weekdays' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
    'weekdays_short' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['காலை', 'மாலை'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sid_ET.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Alessandro Maruccia
 */
return [
    'year' => 'sena|:count sni|:count sni|:count sni',
    'y' => 'sa sena|:count snin|:count snin|:count snin',
    'month' => 'xahar|:count xhur|:count xhur|:count xhur',
    'm' => ':count xahar|:count xhur|:count xhur|:count xhur',
    'week' => 'gimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat',
    'w' => 'ġimgħa|:count ġimgħat|:count ġimgħat|:count ġimgħat',
    'day' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet',
    'd' => 'ġurnata|:count ġranet|:count ġranet|:count ġranet',
    'hour' => 'siegħa|:count siegħat|:count siegħat|:count siegħat',
    'h' => 'siegħa|:count sigħat|:count sigħat|:count sigħat',
    'minute' => 'minuta|:count minuti|:count minuti|:count minuti',
    'min' => 'min.|:count min.|:count min.|:count min.',
    'second' => 'ftit sekondi|:count sekondi|:count sekondi|:count sekondi',
    's' => 'sek.|:count sek.|:count sek.|:count sek.',
    'ago' => ':time ilu',
    'from_now' => 'f’ :time',
    'diff_now' => 'issa',
    'diff_today' => 'Illum',
    'diff_today_regexp' => 'Illum(?:\\s+fil-)?',
    'diff_yesterday' => 'lbieraħ',
    'diff_yesterday_regexp' => 'Il-bieraħ(?:\\s+fil-)?',
    'diff_tomorrow' => 'għada',
    'diff_tomorrow_regexp' => 'Għada(?:\\s+fil-)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Illum fil-]LT',
        'nextDay' => '[Għada fil-]LT',
        'nextWeek' => 'dddd [fil-]LT',
        'lastDay' => '[Il-bieraħ fil-]LT',
        'lastWeek' => 'dddd [li għadda] [fil-]LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberº',
    'months' => ['Jannar', 'Frar', 'Marzu', 'April', 'Mejju', 'Ġunju', 'Lulju', 'Awwissu', 'Settembru', 'Ottubru', 'Novembru', 'Diċembru'],
    'months_short' => ['Jan', 'Fra', 'Mar', 'Apr', 'Mej', 'Ġun', 'Lul', 'Aww', 'Set', 'Ott', 'Nov', 'Diċ'],
    'weekdays' => ['Il-Ħadd', 'It-Tnejn', 'It-Tlieta', 'L-Erbgħa', 'Il-Ħamis', 'Il-Ġimgħa', 'Is-Sibt'],
    'weekdays_short' => ['Ħad', 'Tne', 'Tli', 'Erb', 'Ħam', 'Ġim', 'Sib'],
    'weekdays_min' => ['Ħa', 'Tn', 'Tl', 'Er', 'Ħa', 'Ġi', 'Si'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' u '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mfe_MU.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Samsung Electronics Co., Ltd.    akhilesh.k@samsung.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Janueri', 'Februeri', 'Mas', 'Epril', 'Me', 'Jun', 'Julai', 'Ogas', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mas', 'Epr', 'Me', 'Jun', 'Jul', 'Oga', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['Sande', 'Mande', 'Tunde', 'Trinde', 'Fonde', 'Fraide', 'Sarere'],
    'weekdays_short' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'],
    'weekdays_min' => ['San', 'Man', 'Tun', 'Tri', 'Fon', 'Fra', 'Sar'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['biknait', 'apinun'],

    'year' => 'yia :count',
    'y' => 'yia :count',
    'a_year' => 'yia :count',

    'month' => ':count mun',
    'm' => ':count mun',
    'a_month' => ':count mun',

    'week' => ':count wik',
    'w' => ':count wik',
    'a_week' => ':count wik',

    'day' => ':count de',
    'd' => ':count de',
    'a_day' => ':count de',

    'hour' => ':count aua',
    'h' => ':count aua',
    'a_hour' => ':count aua',

    'minute' => ':count minit',
    'min' => ':count minit',
    'a_minute' => ':count minit',

    'second' => ':count namba tu',
    's' => ':count namba tu',
    'a_second' => ':count namba tu',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - Talat Uspanov
 * - Нурлан Рахимжанов
 * - Toleugazy Kali
 */
return [
    'year' => ':count жыл',
    'a_year' => '{1}бір жыл|:count жыл',
    'y' => ':count ж.',
    'month' => ':count ай',
    'a_month' => '{1}бір ай|:count ай',
    'm' => ':count ай',
    'week' => ':count апта',
    'a_week' => '{1}бір апта',
    'w' => ':count ап.',
    'day' => ':count күн',
    'a_day' => '{1}бір күн|:count күн',
    'd' => ':count к.',
    'hour' => ':count сағат',
    'a_hour' => '{1}бір сағат|:count сағат',
    'h' => ':count са.',
    'minute' => ':count минут',
    'a_minute' => '{1}бір минут|:count минут',
    'min' => ':count м.',
    'second' => ':count секунд',
    'a_second' => '{1}бірнеше секунд|:count секунд',
    's' => ':count се.',
    'ago' => ':time бұрын',
    'from_now' => ':time ішінде',
    'after' => ':time кейін',
    'before' => ':time бұрын',
    'diff_now' => 'қазір',
    'diff_today' => 'Бүгін',
    'diff_today_regexp' => 'Бүгін(?:\\s+сағат)?',
    'diff_yesterday' => 'кеше',
    'diff_yesterday_regexp' => 'Кеше(?:\\s+сағат)?',
    'diff_tomorrow' => 'ертең',
    'diff_tomorrow_regexp' => 'Ертең(?:\\s+сағат)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Бүгін сағат] LT',
        'nextDay' => '[Ертең сағат] LT',
        'nextWeek' => 'dddd [сағат] LT',
        'lastDay' => '[Кеше сағат] LT',
        'lastWeek' => '[Өткен аптаның] dddd [сағат] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        static $suffixes = [
            0 => '-ші',
            1 => '-ші',
            2 => '-ші',
            3 => '-ші',
            4 => '-ші',
            5 => '-ші',
            6 => '-шы',
            7 => '-ші',
            8 => '-ші',
            9 => '-шы',
            10 => '-шы',
            20 => '-шы',
            30 => '-шы',
            40 => '-шы',
            50 => '-ші',
            60 => '-шы',
            70 => '-ші',
            80 => '-ші',
            90 => '-шы',
            100 => '-ші',
        ];

        return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
    },
    'months' => ['қаңтар', 'ақпан', 'наурыз', 'сәуір', 'мамыр', 'маусым', 'шілде', 'тамыз', 'қыркүйек', 'қазан', 'қараша', 'желтоқсан'],
    'months_short' => ['қаң', 'ақп', 'нау', 'сәу', 'мам', 'мау', 'шіл', 'там', 'қыр', 'қаз', 'қар', 'жел'],
    'weekdays' => ['жексенбі', 'дүйсенбі', 'сейсенбі', 'сәрсенбі', 'бейсенбі', 'жұма', 'сенбі'],
    'weekdays_short' => ['жек', 'дүй', 'сей', 'сәр', 'бей', 'жұм', 'сен'],
    'weekdays_min' => ['жк', 'дй', 'сй', 'ср', 'бй', 'жм', 'сн'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' және '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat Pune    libc-alpha@sourceware.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'],
    'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रेल', 'मई', 'जुन', 'जुलाई', 'अगस्त', 'सितम्बर', 'अखथबर', 'नवम्बर', 'दिसम्बर'],
    'weekdays' => ['सिंगेमाँहाँ', 'ओतेमाँहाँ', 'बालेमाँहाँ', 'सागुनमाँहाँ', 'सारदीमाँहाँ', 'जारुममाँहाँ', 'ञुहुममाँहाँ'],
    'weekdays_short' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'],
    'weekdays_min' => ['सिंगे', 'ओते', 'बाले', 'सागुन', 'सारदी', 'जारुम', 'ञुहुम'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'month' => ':count ńindạ cando', // less reliable
    'm' => ':count ńindạ cando', // less reliable
    'a_month' => ':count ńindạ cando', // less reliable

    'week' => ':count mãhã', // less reliable
    'w' => ':count mãhã', // less reliable
    'a_week' => ':count mãhã', // less reliable

    'hour' => ':count ᱥᱳᱱᱚ', // less reliable
    'h' => ':count ᱥᱳᱱᱚ', // less reliable
    'a_hour' => ':count ᱥᱳᱱᱚ', // less reliable

    'minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable
    'min' => ':count ᱯᱤᱞᱪᱩ', // less reliable
    'a_minute' => ':count ᱯᱤᱞᱪᱩ', // less reliable

    'second' => ':count ar', // less reliable
    's' => ':count ar', // less reliable
    'a_second' => ':count ar', // less reliable

    'year' => ':count ne̲s',
    'y' => ':count ne̲s',
    'a_year' => ':count ne̲s',

    'day' => ':count ᱫᱤᱱ',
    'd' => ':count ᱫᱤᱱ',
    'a_day' => ':count ᱫᱤᱱ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/om.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/nds_DE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - bhashaghar@googlegroups.com
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'],
    'months_short' => ['जनवरी', 'फरवरी', 'मार्च', 'अप्रैल', 'मई', 'जून', 'जुलाई', 'अगस्त', 'सितम्बर', 'अक्टूबर', 'नवम्बर', 'दिसम्बर"'],
    'weekdays' => ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],
    'weekdays_short' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
    'weekdays_min' => ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['पूर्वाह्न', 'अपराह्न'],

    'hour' => ':count मौसम',
    'h' => ':count मौसम',
    'a_hour' => ':count मौसम',

    'minute' => ':count कला',
    'min' => ':count कला',
    'a_minute' => ':count कला',

    'second' => ':count सोमार',
    's' => ':count सोमार',
    'a_second' => ':count सोमार',

    'year' => ':count साल',
    'y' => ':count साल',
    'a_year' => ':count साल',

    'month' => ':count महिना',
    'm' => ':count महिना',
    'a_month' => ':count महिना',

    'week' => ':count सप्ताह',
    'w' => ':count सप्ताह',
    'a_week' => ':count सप्ताह',

    'day' => ':count दिन',
    'd' => ':count दिन',
    'a_day' => ':count दिन',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pt.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/hif_FJ.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Martin McWhorter
 * - François B
 * - Chris Cartlidge
 * - JD Isaacks
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'from_now' => 'in :time',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD-MM-YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/af.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/sq.php', [
    'formats' => [
        'L' => 'D.M.YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY, HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Arnas Udovičius bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'YYYY.MM.DD',
    ],
    'months' => ['sausė', 'vasarė', 'kuova', 'balondė', 'gegožės', 'bėrželė', 'lëpas', 'rogpjūtė', 'siejės', 'spalė', 'lapkrėstė', 'grůdė'],
    'months_short' => ['Sau', 'Vas', 'Kuo', 'Bal', 'Geg', 'Bėr', 'Lëp', 'Rgp', 'Sie', 'Spa', 'Lap', 'Grd'],
    'weekdays' => ['nedielės dëna', 'panedielis', 'oterninks', 'sereda', 'četvergs', 'petnīčė', 'sobata'],
    'weekdays_short' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'],
    'weekdays_min' => ['Nd', 'Pn', 'Ot', 'Sr', 'Čt', 'Pt', 'Sb'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'minute' => ':count mažos', // less reliable
    'min' => ':count mažos', // less reliable
    'a_minute' => ':count mažos', // less reliable

    'year' => ':count metā',
    'y' => ':count metā',
    'a_year' => ':count metā',

    'month' => ':count mienou',
    'm' => ':count mienou',
    'a_month' => ':count mienou',

    'week' => ':count nedielė',
    'w' => ':count nedielė',
    'a_week' => ':count nedielė',

    'day' => ':count dīna',
    'd' => ':count dīna',
    'a_day' => ':count dīna',

    'hour' => ':count adīna',
    'h' => ':count adīna',
    'a_hour' => ':count adīna',

    'second' => ':count Sekondė',
    's' => ':count Sekondė',
    'a_second' => ':count Sekondė',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Unicode, Inc.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'ago' => 'berî :time',
    'from_now' => 'di :time de',
    'after' => ':time piştî',
    'before' => ':time berê',
    'year' => ':count sal',
    'a_year' => ':count sal',
    'y' => ':count sal',
    'year_ago' => ':count salê|:count salan',
    'y_ago' => ':count salê|:count salan',
    'year_from_now' => 'salekê|:count salan',
    'y_from_now' => 'salekê|:count salan',
    'month' => ':count meh',
    'a_month' => ':count meh',
    'm' => ':count meh',
    'week' => ':count hefte',
    'a_week' => ':count hefte',
    'w' => ':count hefte',
    'day' => ':count roj',
    'a_day' => ':count roj',
    'd' => ':count roj',
    'hour' => ':count saet',
    'a_hour' => ':count saet',
    'h' => ':count saet',
    'minute' => ':count deqîqe',
    'a_minute' => ':count deqîqe',
    'min' => ':count deqîqe',
    'second' => ':count saniye',
    'a_second' => ':count saniye',
    's' => ':count saniye',
    'months' => ['rêbendanê', 'reşemiyê', 'adarê', 'avrêlê', 'gulanê', 'pûşperê', 'tîrmehê', 'gelawêjê', 'rezberê', 'kewçêrê', 'sermawezê', 'berfanbarê'],
    'months_standalone' => ['rêbendan', 'reşemî', 'adar', 'avrêl', 'gulan', 'pûşper', 'tîrmeh', 'gelawêj', 'rezber', 'kewçêr', 'sermawez', 'berfanbar'],
    'months_short' => ['rêb', 'reş', 'ada', 'avr', 'gul', 'pûş', 'tîr', 'gel', 'rez', 'kew', 'ser', 'ber'],
    'weekdays' => ['yekşem', 'duşem', 'sêşem', 'çarşem', 'pêncşem', 'în', 'şemî'],
    'weekdays_short' => ['yş', 'dş', 'sş', 'çş', 'pş', 'în', 'ş'],
    'weekdays_min' => ['Y', 'D', 'S', 'Ç', 'P', 'Î', 'Ş'],
    'list' => [', ', ' û '],
    'ordinal' => ':number',
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['KI', 'UT'],
    'weekdays' => ['Kiumia', 'Njumatatu', 'Njumaine', 'Njumatano', 'Aramithi', 'Njumaa', 'NJumamothii'],
    'weekdays_short' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
    'weekdays_min' => ['Kma', 'Tat', 'Ine', 'Tan', 'Arm', 'Maa', 'NMM'],
    'months' => ['Mweri wa mbere', 'Mweri wa kaĩri', 'Mweri wa kathatũ', 'Mweri wa kana', 'Mweri wa gatano', 'Mweri wa gatantatũ', 'Mweri wa mũgwanja', 'Mweri wa kanana', 'Mweri wa kenda', 'Mweri wa ikũmi', 'Mweri wa ikũmi na ũmwe', 'Mweri wa ikũmi na Kaĩrĩ'],
    'months_short' => ['Mbe', 'Kai', 'Kat', 'Kan', 'Gat', 'Gan', 'Mug', 'Knn', 'Ken', 'Iku', 'Imw', 'Igi'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/pl.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/bhb_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory  bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - nootanghimire
 * - Josh Soref
 * - Nj Subedi
 * - JD Isaacks
 */
return [
    'year' => 'एक बर्ष|:count बर्ष',
    'y' => ':count वर्ष',
    'month' => 'एक महिना|:count महिना',
    'm' => ':count महिना',
    'week' => ':count हप्ता',
    'w' => ':count हप्ता',
    'day' => 'एक दिन|:count दिन',
    'd' => ':count दिन',
    'hour' => 'एक घण्टा|:count घण्टा',
    'h' => ':count घण्टा',
    'minute' => 'एक मिनेट|:count मिनेट',
    'min' => ':count मिनेट',
    'second' => 'केही क्षण|:count सेकेण्ड',
    's' => ':count सेकेण्ड',
    'ago' => ':time अगाडि',
    'from_now' => ':timeमा',
    'after' => ':time पछि',
    'before' => ':time अघि',
    'diff_now' => 'अहिले',
    'diff_today' => 'आज',
    'diff_yesterday' => 'हिजो',
    'diff_tomorrow' => 'भोलि',
    'formats' => [
        'LT' => 'Aको h:mm बजे',
        'LTS' => 'Aको h:mm:ss बजे',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, Aको h:mm बजे',
        'LLLL' => 'dddd, D MMMM YYYY, Aको h:mm बजे',
    ],
    'calendar' => [
        'sameDay' => '[आज] LT',
        'nextDay' => '[भोलि] LT',
        'nextWeek' => '[आउँदो] dddd[,] LT',
        'lastDay' => '[हिजो] LT',
        'lastWeek' => '[गएको] dddd[,] LT',
        'sameElse' => 'L',
    ],
    'meridiem' => static function ($hour) {
        if ($hour < 3) {
            return 'राति';
        }
        if ($hour < 12) {
            return 'बिहान';
        }
        if ($hour < 16) {
            return 'दिउँसो';
        }
        if ($hour < 20) {
            return 'साँझ';
        }

        return 'राति';
    },
    'months' => ['जनवरी', 'फेब्रुवरी', 'मार्च', 'अप्रिल', 'मई', 'जुन', 'जुलाई', 'अगष्ट', 'सेप्टेम्बर', 'अक्टोबर', 'नोभेम्बर', 'डिसेम्बर'],
    'months_short' => ['जन.', 'फेब्रु.', 'मार्च', 'अप्रि.', 'मई', 'जुन', 'जुलाई.', 'अग.', 'सेप्ट.', 'अक्टो.', 'नोभे.', 'डिसे.'],
    'weekdays' => ['आइतबार', 'सोमबार', 'मङ्गलबार', 'बुधबार', 'बिहिबार', 'शुक्रबार', 'शनिबार'],
    'weekdays_short' => ['आइत.', 'सोम.', 'मङ्गल.', 'बुध.', 'बिहि.', 'शुक्र.', 'शनि.'],
    'weekdays_min' => ['आ.', 'सो.', 'मं.', 'बु.', 'बि.', 'शु.', 'श.'],
    'list' => [', ', ' र '],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['kíkíríg', 'ngəgógəle'],
    'weekdays' => ['sɔ́ndɔ', 'mɔ́ndi', 'sɔ́ndɔ məlú mə́bɛ̌', 'sɔ́ndɔ məlú mə́lɛ́', 'sɔ́ndɔ məlú mə́nyi', 'fúladé', 'séradé'],
    'weekdays_short' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
    'weekdays_min' => ['sɔ́n', 'mɔ́n', 'smb', 'sml', 'smn', 'fúl', 'sér'],
    'months' => ['ngɔn osú', 'ngɔn bɛ̌', 'ngɔn lála', 'ngɔn nyina', 'ngɔn tána', 'ngɔn saməna', 'ngɔn zamgbála', 'ngɔn mwom', 'ngɔn ebulú', 'ngɔn awóm', 'ngɔn awóm ai dziá', 'ngɔn awóm ai bɛ̌'],
    'months_short' => ['ngo', 'ngb', 'ngl', 'ngn', 'ngt', 'ngs', 'ngz', 'ngm', 'nge', 'nga', 'ngad', 'ngab'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    // Too unreliable
    /*
    'year' => ':count mbu', // less reliable
    'y' => ':count mbu', // less reliable
    'a_year' => ':count mbu', // less reliable

    'month' => ':count ngòn', // less reliable
    'm' => ':count ngòn', // less reliable
    'a_month' => ':count ngòn', // less reliable

    'week' => ':count mësë', // less reliable
    'w' => ':count mësë', // less reliable
    'a_week' => ':count mësë', // less reliable

    'day' => ':count mësë', // less reliable
    'd' => ':count mësë', // less reliable
    'a_day' => ':count mësë', // less reliable

    'hour' => ':count awola', // less reliable
    'h' => ':count awola', // less reliable
    'a_hour' => ':count awola', // less reliable

    'minute' => ':count awola', // less reliable
    'min' => ':count awola', // less reliable
    'a_minute' => ':count awola', // less reliable
    */
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/bho_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ky.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/shi.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/fil_PH.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/hsb_DE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Alexander Tømmerås
 * - Øystein
 * - JD Isaacks
 * - Gaute Hvoslef Kvalnes (gaute)
 */
return [
    'year' => ':count år',
    'a_year' => 'eit år|:count år',
    'y' => ':count år',
    'month' => ':count månad|:count månader',
    'a_month' => 'ein månad|:count månader',
    'm' => ':count md',
    'week' => ':count veke|:count veker',
    'a_week' => 'ei veke|:count veker',
    'w' => ':countv',
    'day' => ':count dag|:count dagar',
    'a_day' => 'ein dag|:count dagar',
    'd' => ':countd',
    'hour' => ':count time|:count timar',
    'a_hour' => 'ein time|:count timar',
    'h' => ':countt',
    'minute' => ':count minutt',
    'a_minute' => 'eit minutt|:count minutt',
    'min' => ':countm',
    'second' => ':count sekund',
    'a_second' => 'nokre sekund|:count sekund',
    's' => ':counts',
    'ago' => ':time sidan',
    'from_now' => 'om :time',
    'after' => ':time etter',
    'before' => ':time før',
    'diff_today' => 'I dag',
    'diff_yesterday' => 'I går',
    'diff_yesterday_regexp' => 'I går(?:\\s+klokka)?',
    'diff_tomorrow' => 'I morgon',
    'diff_tomorrow_regexp' => 'I morgon(?:\\s+klokka)?',
    'diff_today_regexp' => 'I dag(?:\\s+klokka)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D. MMMM YYYY',
        'LLL' => 'D. MMMM YYYY [kl.] H:mm',
        'LLLL' => 'dddd D. MMMM YYYY [kl.] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[I dag klokka] LT',
        'nextDay' => '[I morgon klokka] LT',
        'nextWeek' => 'dddd [klokka] LT',
        'lastDay' => '[I går klokka] LT',
        'lastWeek' => '[Føregåande] dddd [klokka] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':number.',
    'months' => ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'mai', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'des'],
    'weekdays' => ['sundag', 'måndag', 'tysdag', 'onsdag', 'torsdag', 'fredag', 'laurdag'],
    'weekdays_short' => ['sun', 'mån', 'tys', 'ons', 'tor', 'fre', 'lau'],
    'weekdays_min' => ['su', 'må', 'ty', 'on', 'to', 'fr', 'la'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' og '],
    'meridiem' => ['f.m.', 'e.m.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - The Debian Project modified by GNU//Linux Malagasy Rado Ramarotafika,Do-Risika RAFIEFERANTSIARONJY rado@linuxmg.org,dourix@free.fr
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD.MM.YYYY',
    ],
    'months' => ['Janoary', 'Febroary', 'Martsa', 'Aprily', 'Mey', 'Jona', 'Jolay', 'Aogositra', 'Septambra', 'Oktobra', 'Novambra', 'Desambra'],
    'months_short' => ['Jan', 'Feb', 'Mar', 'Apr', 'Mey', 'Jon', 'Jol', 'Aog', 'Sep', 'Okt', 'Nov', 'Des'],
    'weekdays' => ['alahady', 'alatsinainy', 'talata', 'alarobia', 'alakamisy', 'zoma', 'sabotsy'],
    'weekdays_short' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'],
    'weekdays_min' => ['lhd', 'lts', 'tlt', 'lrb', 'lkm', 'zom', 'sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,

    'minute' => ':count minitra', // less reliable
    'min' => ':count minitra', // less reliable
    'a_minute' => ':count minitra', // less reliable

    'year' => ':count taona',
    'y' => ':count taona',
    'a_year' => ':count taona',

    'month' => ':count volana',
    'm' => ':count volana',
    'a_month' => ':count volana',

    'week' => ':count herinandro',
    'w' => ':count herinandro',
    'a_week' => ':count herinandro',

    'day' => ':count andro',
    'd' => ':count andro',
    'a_day' => ':count andro',

    'hour' => ':count ora',
    'h' => ':count ora',
    'a_hour' => ':count ora',

    'second' => ':count segondra',
    's' => ':count segondra',
    'a_second' => ':count segondra',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'dddd, YYYY MMMM DD HH:mm',
    ],
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - monkeycon
 * - François B
 * - Jason Katz-Brown
 * - Serhan Apaydın
 * - Matt Johnson
 * - JD Isaacks
 * - Zeno Zeng
 * - Chris Hemp
 * - shankesgk2
 */
return array_merge(require __DIR__.'/zh.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY/MM/DD',
        'LL' => 'YYYY年M月D日',
        'LLL' => 'YYYY年M月D日Ah点mm分',
        'LLLL' => 'YYYY年M月D日ddddAh点mm分',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'weekdays' => ['Dimingu', 'Chiposi', 'Chipiri', 'Chitatu', 'Chinai', 'Chishanu', 'Sabudu'],
    'weekdays_short' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
    'weekdays_min' => ['Dim', 'Pos', 'Pir', 'Tat', 'Nai', 'Sha', 'Sab'],
    'months' => ['Janeiro', 'Fevreiro', 'Marco', 'Abril', 'Maio', 'Junho', 'Julho', 'Augusto', 'Setembro', 'Otubro', 'Novembro', 'Decembro'],
    'months_short' => ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Aug', 'Set', 'Otu', 'Nov', 'Dec'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'd [de] MMM [de] YYYY',
        'LLL' => 'd [de] MMMM [de] YYYY HH:mm',
        'LLLL' => 'dddd, d [de] MMMM [de] YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/nl.php', [
    'formats' => [
        'L' => 'DD-MM-YY',
    ],
    'months' => ['januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
    'months_short' => ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
    'weekdays' => ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
    'weekdays_short' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    'weekdays_min' => ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Muhammad Nasir Rahimi
 * - Nassim Nasibullah (spinzar)
 */
return [
    'year' => ':count کال|:count کاله',
    'y' => ':countکال|:countکاله',
    'month' => ':count مياشت|:count مياشتي',
    'm' => ':countمياشت|:countمياشتي',
    'week' => ':count اونۍ|:count اونۍ',
    'w' => ':countاونۍ|:countاونۍ',
    'day' => ':count ورځ|:count ورځي',
    'd' => ':countورځ|:countورځي',
    'hour' => ':count ساعت|:count ساعته',
    'h' => ':countساعت|:countساعته',
    'minute' => ':count دقيقه|:count دقيقې',
    'min' => ':countدقيقه|:countدقيقې',
    'second' => ':count ثانيه|:count ثانيې',
    's' => ':countثانيه|:countثانيې',
    'ago' => ':time دمخه',
    'from_now' => ':time له اوس څخه',
    'after' => ':time وروسته',
    'before' => ':time دمخه',
    'list' => ['، ', ' او '],
    'meridiem' => ['غ.م.', 'غ.و.'],
    'weekdays' => ['اتوار', 'ګل', 'نهه', 'شورو', 'زيارت', 'جمعه', 'خالي'],
    'weekdays_short' => ['ا', 'ګ', 'ن', 'ش', 'ز', 'ج', 'خ'],
    'weekdays_min' => ['ا', 'ګ', 'ن', 'ش', 'ز', 'ج', 'خ'],
    'months' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سېپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_standalone' => ['جنوري', 'فېبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'months_short_standalone' => ['جنوري', 'فبروري', 'مارچ', 'اپریل', 'مۍ', 'جون', 'جولای', 'اگست', 'سپتمبر', 'اکتوبر', 'نومبر', 'دسمبر'],
    'first_day_of_week' => 6,
    'weekend' => [4, 5],
    'formats' => [
        'LT' => 'H:mm',
        'LTS' => 'H:mm:ss',
        'L' => 'YYYY/M/d',
        'LL' => 'YYYY MMM D',
        'LLL' => 'د YYYY د MMMM D H:mm',
        'LLLL' => 'dddd د YYYY د MMMM D H:mm',
    ],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Carbon\CarbonInterface;

$processHoursFunction = static function (CarbonInterface $date, string $format) {
    return $format.'о'.($date->hour === 11 ? 'б' : '').'] LT';
};

/*
 * Authors:
 * - Kunal Marwaha
 * - Josh Soref
 * - François B
 * - Tim Fish
 * - Serhan Apaydın
 * - Max Mykhailenko
 * - JD Isaacks
 * - Max Kovpak
 * - AucT
 * - Philippe Vaucher
 * - Ilya Shaplyko
 * - Vadym Ievsieiev
 * - Denys Kurets
 * - Igor Kasyanchuk
 * - Tsutomu Kuroda
 * - tjku
 * - Max Melentiev
 * - Oleh
 * - epaminond
 * - Juanito Fatas
 * - Vitalii Khustochka
 * - Akira Matsuda
 * - Christopher Dell
 * - Enrique Vidal
 * - Simone Carletti
 * - Aaron Patterson
 * - Andriy Tyurnikov
 * - Nicolás Hock Isaza
 * - Iwakura Taro
 * - Andrii Ponomarov
 * - alecrabbit
 * - vystepanenko
 * - AlexWalkerson
 * - Andre Havryliuk (Andrend)
 * - Max Datsenko (datsenko-md)
 */
return [
    'year' => ':count рік|:count роки|:count років',
    'y' => ':countр|:countрр|:countрр',
    'a_year' => '{1}рік|:count рік|:count роки|:count років',
    'month' => ':count місяць|:count місяці|:count місяців',
    'm' => ':countм',
    'a_month' => '{1}місяць|:count місяць|:count місяці|:count місяців',
    'week' => ':count тиждень|:count тижні|:count тижнів',
    'w' => ':countт',
    'a_week' => '{1}тиждень|:count тиждень|:count тижні|:count тижнів',
    'day' => ':count день|:count дні|:count днів',
    'd' => ':countд',
    'a_day' => '{1}день|:count день|:count дні|:count днів',
    'hour' => ':count година|:count години|:count годин',
    'h' => ':countг',
    'a_hour' => '{1}година|:count година|:count години|:count годин',
    'minute' => ':count хвилина|:count хвилини|:count хвилин',
    'min' => ':countхв',
    'a_minute' => '{1}хвилина|:count хвилина|:count хвилини|:count хвилин',
    'second' => ':count секунда|:count секунди|:count секунд',
    's' => ':countсек',
    'a_second' => '{1}декілька секунд|:count секунда|:count секунди|:count секунд',

    'hour_ago' => ':count годину|:count години|:count годин',
    'a_hour_ago' => '{1}годину|:count годину|:count години|:count годин',
    'minute_ago' => ':count хвилину|:count хвилини|:count хвилин',
    'a_minute_ago' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
    'second_ago' => ':count секунду|:count секунди|:count секунд',
    'a_second_ago' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',

    'hour_from_now' => ':count годину|:count години|:count годин',
    'a_hour_from_now' => '{1}годину|:count годину|:count години|:count годин',
    'minute_from_now' => ':count хвилину|:count хвилини|:count хвилин',
    'a_minute_from_now' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
    'second_from_now' => ':count секунду|:count секунди|:count секунд',
    'a_second_from_now' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',

    'hour_after' => ':count годину|:count години|:count годин',
    'a_hour_after' => '{1}годину|:count годину|:count години|:count годин',
    'minute_after' => ':count хвилину|:count хвилини|:count хвилин',
    'a_minute_after' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
    'second_after' => ':count секунду|:count секунди|:count секунд',
    'a_second_after' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',

    'hour_before' => ':count годину|:count години|:count годин',
    'a_hour_before' => '{1}годину|:count годину|:count години|:count годин',
    'minute_before' => ':count хвилину|:count хвилини|:count хвилин',
    'a_minute_before' => '{1}хвилину|:count хвилину|:count хвилини|:count хвилин',
    'second_before' => ':count секунду|:count секунди|:count секунд',
    'a_second_before' => '{1}декілька секунд|:count секунду|:count секунди|:count секунд',

    'ago' => ':time тому',
    'from_now' => 'за :time',
    'after' => ':time після',
    'before' => ':time до',
    'diff_now' => 'щойно',
    'diff_today' => 'Сьогодні',
    'diff_today_regexp' => 'Сьогодні(?:\\s+о)?',
    'diff_yesterday' => 'вчора',
    'diff_yesterday_regexp' => 'Вчора(?:\\s+о)?',
    'diff_tomorrow' => 'завтра',
    'diff_tomorrow_regexp' => 'Завтра(?:\\s+о)?',
    'diff_before_yesterday' => 'позавчора',
    'diff_after_tomorrow' => 'післязавтра',
    'period_recurrences' => 'один раз|:count рази|:count разів',
    'period_interval' => 'кожні :interval',
    'period_start_date' => 'з :date',
    'period_end_date' => 'до :date',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
    ],
    'calendar' => [
        'sameDay' => static fn (CarbonInterface $date) => $processHoursFunction($date, '[Сьогодні '),
        'nextDay' => static fn (CarbonInterface $date) => $processHoursFunction($date, '[Завтра '),
        'nextWeek' => static fn (CarbonInterface $date) => $processHoursFunction($date, '[У] dddd ['),
        'lastDay' => static fn (CarbonInterface $date) => $processHoursFunction($date, '[Вчора '),
        'lastWeek' => static fn (CarbonInterface $date) => match ($date->dayOfWeek) {
            0, 3, 5, 6 => $processHoursFunction($date, '[Минулої] dddd ['),
            default => $processHoursFunction($date, '[Минулого] dddd ['),
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static fn ($number, $period) => match ($period) {
        'M', 'd', 'DDD', 'w', 'W' => $number.'-й',
        'D' => $number.'-го',
        default => $number,
    },
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'ночі';
        }

        if ($hour < 12) {
            return 'ранку';
        }

        if ($hour < 17) {
            return 'дня';
        }

        return 'вечора';
    },
    'months' => ['січня', 'лютого', 'березня', 'квітня', 'травня', 'червня', 'липня', 'серпня', 'вересня', 'жовтня', 'листопада', 'грудня'],
    'months_standalone' => ['січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень', 'жовтень', 'листопад', 'грудень'],
    'months_short' => ['січ', 'лют', 'бер', 'кві', 'тра', 'чер', 'лип', 'сер', 'вер', 'жов', 'лис', 'гру'],
    'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => static function (CarbonInterface $date, $format, $index) {
        static $words = [
            'nominative' => ['неділя', 'понеділок', 'вівторок', 'середа', 'четвер', 'п’ятниця', 'субота'],
            'accusative' => ['неділю', 'понеділок', 'вівторок', 'середу', 'четвер', 'п’ятницю', 'суботу'],
            'genitive' => ['неділі', 'понеділка', 'вівторка', 'середи', 'четверга', 'п’ятниці', 'суботи'],
        ];

        $format ??= '';
        $nounCase = preg_match('/(\[(В|в|У|у)\])\s+dddd/u', $format)
            ? 'accusative'
            : (
                preg_match('/\[?(?:минулої|наступної)?\s*\]\s+dddd/u', $format)
                    ? 'genitive'
                    : 'nominative'
            );

        return $words[$nounCase][$index] ?? null;
    },
    'weekdays_short' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    'weekdays_min' => ['нд', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' i '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/nhn_MX.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - ANLoc Martin Benjamin locales@africanlocalization.net
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/mag_IN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ber_DZ.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Orif N. Jr
 */
return [
    'year' => '{1}як сол|:count сол',
    'month' => '{1}як моҳ|:count моҳ',
    'week' => '{1}як ҳафта|:count ҳафта',
    'day' => '{1}як рӯз|:count рӯз',
    'hour' => '{1}як соат|:count соат',
    'minute' => '{1}як дақиқа|:count дақиқа',
    'second' => '{1}якчанд сония|:count сония',
    'ago' => ':time пеш',
    'from_now' => 'баъди :time',
    'diff_today' => 'Имрӯз',
    'diff_yesterday' => 'Дирӯз',
    'diff_yesterday_regexp' => 'Дирӯз(?:\\s+соати)?',
    'diff_tomorrow' => 'Пагоҳ',
    'diff_tomorrow_regexp' => 'Пагоҳ(?:\\s+соати)?',
    'diff_today_regexp' => 'Имрӯз(?:\\s+соати)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Имрӯз соати] LT',
        'nextDay' => '[Пагоҳ соати] LT',
        'nextWeek' => 'dddd[и] [ҳафтаи оянда соати] LT',
        'lastDay' => '[Дирӯз соати] LT',
        'lastWeek' => 'dddd[и] [ҳафтаи гузашта соати] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        if ($number === 0) { // special case for zero
            return "$number-ıncı";
        }

        static $suffixes = [
            0 => '-ум',
            1 => '-ум',
            2 => '-юм',
            3 => '-юм',
            4 => '-ум',
            5 => '-ум',
            6 => '-ум',
            7 => '-ум',
            8 => '-ум',
            9 => '-ум',
            10 => '-ум',
            12 => '-ум',
            13 => '-ум',
            20 => '-ум',
            30 => '-юм',
            40 => '-ум',
            50 => '-ум',
            60 => '-ум',
            70 => '-ум',
            80 => '-ум',
            90 => '-ум',
            100 => '-ум',
        ];

        return $number.($suffixes[$number] ?? $suffixes[$number % 10] ?? $suffixes[$number >= 100 ? 100 : -1] ?? '');
    },
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'шаб';
        }
        if ($hour < 11) {
            return 'субҳ';
        }
        if ($hour < 16) {
            return 'рӯз';
        }
        if ($hour < 19) {
            return 'бегоҳ';
        }

        return 'шаб';
    },
    'months' => ['январ', 'феврал', 'март', 'апрел', 'май', 'июн', 'июл', 'август', 'сентябр', 'октябр', 'ноябр', 'декабр'],
    'months_short' => ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'],
    'weekdays' => ['якшанбе', 'душанбе', 'сешанбе', 'чоршанбе', 'панҷшанбе', 'ҷумъа', 'шанбе'],
    'weekdays_short' => ['яшб', 'дшб', 'сшб', 'чшб', 'пшб', 'ҷум', 'шнб'],
    'weekdays_min' => ['яш', 'дш', 'сш', 'чш', 'пш', 'ҷм', 'шб'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' ва '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - François B
 * - JD Isaacks
 * - Satheez
 */
return [
    'year' => ':count வருடம்|:count ஆண்டுகள்',
    'a_year' => 'ஒரு வருடம்|:count ஆண்டுகள்',
    'y' => ':count வருட.|:count ஆண்.',
    'month' => ':count மாதம்|:count மாதங்கள்',
    'a_month' => 'ஒரு மாதம்|:count மாதங்கள்',
    'm' => ':count மாத.',
    'week' => ':count வாரம்|:count வாரங்கள்',
    'a_week' => 'ஒரு வாரம்|:count வாரங்கள்',
    'w' => ':count வார.',
    'day' => ':count நாள்|:count நாட்கள்',
    'a_day' => 'ஒரு நாள்|:count நாட்கள்',
    'd' => ':count நாள்|:count நாட்.',
    'hour' => ':count மணி நேரம்|:count மணி நேரம்',
    'a_hour' => 'ஒரு மணி நேரம்|:count மணி நேரம்',
    'h' => ':count மணி.',
    'minute' => ':count நிமிடம்|:count நிமிடங்கள்',
    'a_minute' => 'ஒரு நிமிடம்|:count நிமிடங்கள்',
    'min' => ':count நிமி.',
    'second' => ':count சில விநாடிகள்|:count விநாடிகள்',
    'a_second' => 'ஒரு சில விநாடிகள்|:count விநாடிகள்',
    's' => ':count விநா.',
    'ago' => ':time முன்',
    'from_now' => ':time இல்',
    'before' => ':time முன்',
    'after' => ':time பின்',
    'diff_now' => 'இப்போது',
    'diff_today' => 'இன்று',
    'diff_yesterday' => 'நேற்று',
    'diff_tomorrow' => 'நாளை',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY, HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY, HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[இன்று] LT',
        'nextDay' => '[நாளை] LT',
        'nextWeek' => 'dddd, LT',
        'lastDay' => '[நேற்று] LT',
        'lastWeek' => '[கடந்த வாரம்] dddd, LT',
        'sameElse' => 'L',
    ],
    'ordinal' => ':numberவது',
    'meridiem' => static function ($hour) {
        if ($hour < 2) {
            return ' யாமம்';
        }
        if ($hour < 6) {
            return ' வைகறை';
        }
        if ($hour < 10) {
            return ' காலை';
        }
        if ($hour < 14) {
            return ' நண்பகல்';
        }
        if ($hour < 18) {
            return ' எற்பாடு';
        }
        if ($hour < 22) {
            return ' மாலை';
        }

        return ' யாமம்';
    },
    'months' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
    'months_short' => ['ஜனவரி', 'பிப்ரவரி', 'மார்ச்', 'ஏப்ரல்', 'மே', 'ஜூன்', 'ஜூலை', 'ஆகஸ்ட்', 'செப்டெம்பர்', 'அக்டோபர்', 'நவம்பர்', 'டிசம்பர்'],
    'weekdays' => ['ஞாயிற்றுக்கிழமை', 'திங்கட்கிழமை', 'செவ்வாய்கிழமை', 'புதன்கிழமை', 'வியாழக்கிழமை', 'வெள்ளிக்கிழமை', 'சனிக்கிழமை'],
    'weekdays_short' => ['ஞாயிறு', 'திங்கள்', 'செவ்வாய்', 'புதன்', 'வியாழன்', 'வெள்ளி', 'சனி'],
    'weekdays_min' => ['ஞா', 'தி', 'செ', 'பு', 'வி', 'வெ', 'ச'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' மற்றும் '],
    'weekend' => [0, 0],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return [
    'year' => ':count taon',
    'a_year' => '{1}isang taon|:count taon',
    'month' => ':count buwan',
    'a_month' => '{1}isang buwan|:count buwan',
    'week' => ':count linggo',
    'a_week' => '{1}isang linggo|:count linggo',
    'day' => ':count araw',
    'a_day' => '{1}isang araw|:count araw',
    'hour' => ':count oras',
    'a_hour' => '{1}isang oras|:count oras',
    'minute' => ':count minuto',
    'a_minute' => '{1}isang minuto|:count minuto',
    'min' => ':count min.',
    'second' => ':count segundo',
    'a_second' => '{1}ilang segundo|:count segundo',
    's' => ':count seg.',
    'ago' => ':time ang nakalipas',
    'from_now' => 'sa loob ng :time',
    'diff_now' => 'ngayon',
    'diff_today' => 'ngayong',
    'diff_today_regexp' => 'ngayong(?:\\s+araw)?',
    'diff_yesterday' => 'kahapon',
    'diff_tomorrow' => 'bukas',
    'diff_tomorrow_regexp' => 'Bukas(?:\\s+ng)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'MM/D/YYYY',
        'LL' => 'MMMM D, YYYY',
        'LLL' => 'MMMM D, YYYY HH:mm',
        'LLLL' => 'dddd, MMMM DD, YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => 'LT [ngayong araw]',
        'nextDay' => '[Bukas ng] LT',
        'nextWeek' => 'LT [sa susunod na] dddd',
        'lastDay' => 'LT [kahapon]',
        'lastWeek' => 'LT [noong nakaraang] dddd',
        'sameElse' => 'L',
    ],
    'months' => ['Enero', 'Pebrero', 'Marso', 'Abril', 'Mayo', 'Hunyo', 'Hulyo', 'Agosto', 'Setyembre', 'Oktubre', 'Nobyembre', 'Disyembre'],
    'months_short' => ['Ene', 'Peb', 'Mar', 'Abr', 'May', 'Hun', 'Hul', 'Ago', 'Set', 'Okt', 'Nob', 'Dis'],
    'weekdays' => ['Linggo', 'Lunes', 'Martes', 'Miyerkules', 'Huwebes', 'Biyernes', 'Sabado'],
    'weekdays_short' => ['Lin', 'Lun', 'Mar', 'Miy', 'Huw', 'Biy', 'Sab'],
    'weekdays_min' => ['Li', 'Lu', 'Ma', 'Mi', 'Hu', 'Bi', 'Sab'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' at '],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/bs.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/sc_IT.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Thanks to André Silva : https://github.com/askpt
 */

return [
    'year' => ':count bliain',
    'a_year' => '{1}bliain|:count bliain',
    'y' => ':countb',
    'month' => ':count mí',
    'a_month' => '{1}mí|:count mí',
    'm' => ':countm',
    'week' => ':count sheachtain',
    'a_week' => '{1}sheachtain|:count sheachtain',
    'w' => ':countsh',
    'day' => ':count lá',
    'a_day' => '{1}lá|:count lá',
    'd' => ':countl',
    'hour' => ':count uair an chloig',
    'a_hour' => '{1}uair an chloig|:count uair an chloig',
    'h' => ':countu',
    'minute' => ':count nóiméad',
    'a_minute' => '{1}nóiméad|:count nóiméad',
    'min' => ':countn',
    'second' => ':count soicind',
    'a_second' => '{1}cúpla soicind|:count soicind',
    's' => ':countso',
    'ago' => ':time ó shin',
    'from_now' => 'i :time',
    'after' => ':time tar éis',
    'before' => ':time roimh',
    'diff_now' => 'anois',
    'diff_today' => 'Inniu',
    'diff_today_regexp' => 'Inniu(?:\\s+ag)?',
    'diff_yesterday' => 'inné',
    'diff_yesterday_regexp' => 'Inné(?:\\s+aig)?',
    'diff_tomorrow' => 'amárach',
    'diff_tomorrow_regexp' => 'Amárach(?:\\s+ag)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Inniu ag] LT',
        'nextDay' => '[Amárach ag] LT',
        'nextWeek' => 'dddd [ag] LT',
        'lastDay' => '[Inné aig] LT',
        'lastWeek' => 'dddd [seo caite] [ag] LT',
        'sameElse' => 'L',
    ],
    'months' => ['Eanáir', 'Feabhra', 'Márta', 'Aibreán', 'Bealtaine', 'Méitheamh', 'Iúil', 'Lúnasa', 'Meán Fómhair', 'Deaireadh Fómhair', 'Samhain', 'Nollaig'],
    'months_short' => ['Eaná', 'Feab', 'Márt', 'Aibr', 'Beal', 'Méit', 'Iúil', 'Lúna', 'Meán', 'Deai', 'Samh', 'Noll'],
    'weekdays' => ['Dé Domhnaigh', 'Dé Luain', 'Dé Máirt', 'Dé Céadaoin', 'Déardaoin', 'Dé hAoine', 'Dé Satharn'],
    'weekdays_short' => ['Dom', 'Lua', 'Mái', 'Céa', 'Déa', 'hAo', 'Sat'],
    'weekdays_min' => ['Do', 'Lu', 'Má', 'Ce', 'Dé', 'hA', 'Sa'],
    'ordinal' => static fn ($number) => $number.($number === 1 ? 'd' : ($number % 10 === 2 ? 'na' : 'mh')),
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' agus '],
    'meridiem' => ['r.n.', 'i.n.'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/ha.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Kristoffer Snabb
 * - JD Isaacks
 * - Jens Herlevsen
 * - Nightpine
 * - Anders Nygren (litemerafrukt)
 */
return [
    'year' => ':count år',
    'a_year' => 'ett år|:count år',
    'y' => ':count år',
    'month' => ':count månad|:count månader',
    'a_month' => 'en månad|:count månader',
    'm' => ':count mån',
    'week' => ':count vecka|:count veckor',
    'a_week' => 'en vecka|:count veckor',
    'w' => ':count v',
    'day' => ':count dag|:count dagar',
    'a_day' => 'en dag|:count dagar',
    'd' => ':count dgr',
    'hour' => ':count timme|:count timmar',
    'a_hour' => 'en timme|:count timmar',
    'h' => ':count tim',
    'minute' => ':count minut|:count minuter',
    'a_minute' => 'en minut|:count minuter',
    'min' => ':count min',
    'second' => ':count sekund|:count sekunder',
    'a_second' => 'några sekunder|:count sekunder',
    's' => ':count s',
    'ago' => 'för :time sedan',
    'from_now' => 'om :time',
    'after' => ':time efter',
    'before' => ':time före',
    'diff_now' => 'nu',
    'diff_today' => 'I dag',
    'diff_yesterday' => 'i går',
    'diff_yesterday_regexp' => 'I går',
    'diff_tomorrow' => 'i morgon',
    'diff_tomorrow_regexp' => 'I morgon',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-DD',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY [kl.] HH:mm',
        'LLLL' => 'dddd D MMMM YYYY [kl.] HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[I dag] LT',
        'nextDay' => '[I morgon] LT',
        'nextWeek' => '[På] dddd LT',
        'lastDay' => '[I går] LT',
        'lastWeek' => '[I] dddd[s] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        $lastDigit = $number % 10;

        return $number.(
            ((int) ($number % 100 / 10) === 1) ? 'e' : (
                ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e'
            )
        );
    },
    'months' => ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],
    'months_short' => ['jan', 'feb', 'mar', 'apr', 'maj', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
    'weekdays' => ['söndag', 'måndag', 'tisdag', 'onsdag', 'torsdag', 'fredag', 'lördag'],
    'weekdays_short' => ['sön', 'mån', 'tis', 'ons', 'tors', 'fre', 'lör'],
    'weekdays_min' => ['sö', 'må', 'ti', 'on', 'to', 'fr', 'lö'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' och '],
    'meridiem' => ['fm', 'em'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/bem_ZM.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es_UY.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM, YYYY HH:mm',
    ],
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/es.php', [
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/wo_SN.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/kk.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Ge'ez Frontier Foundation    locales@geez.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['ጥሪ', 'ለካቲት', 'መጋቢት', 'ሚያዝያ', 'ግንቦት', 'ሰነ', 'ሓምለ', 'ነሓሰ', 'መስከረም', 'ጥቅምቲ', 'ሕዳር', 'ታሕሳስ'],
    'months_short' => ['ጥሪ ', 'ለካቲ', 'መጋቢ', 'ሚያዝ', 'ግንቦ', 'ሰነ ', 'ሓምለ', 'ነሓሰ', 'መስከ', 'ጥቅም', 'ሕዳር', 'ታሕሳ'],
    'weekdays' => ['ሰንበት ዓባይ', 'ሰኖ', 'ታላሸኖ', 'ኣረርባዓ', 'ከሚሽ', 'ጅምዓት', 'ሰንበት ንኢሽ'],
    'weekdays_short' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'],
    'weekdays_min' => ['ሰ//ዓ', 'ሰኖ ', 'ታላሸ', 'ኣረር', 'ከሚሽ', 'ጅምዓ', 'ሰ//ን'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['ቀደም ሰር ምዕል', 'ሓቆ ሰር ምዕል'],

    'year' => ':count ማይ', // less reliable
    'y' => ':count ማይ', // less reliable
    'a_year' => ':count ማይ', // less reliable

    'month' => ':count ሸምሽ', // less reliable
    'm' => ':count ሸምሽ', // less reliable
    'a_month' => ':count ሸምሽ', // less reliable

    'week' => ':count ሰቡዕ', // less reliable
    'w' => ':count ሰቡዕ', // less reliable
    'a_week' => ':count ሰቡዕ', // less reliable

    'day' => ':count ዎሮ', // less reliable
    'd' => ':count ዎሮ', // less reliable
    'a_day' => ':count ዎሮ', // less reliable

    'hour' => ':count ሰዓት', // less reliable
    'h' => ':count ሰዓት', // less reliable
    'a_hour' => ':count ሰዓት', // less reliable

    'minute' => ':count ካልኣይት', // less reliable
    'min' => ':count ካልኣይት', // less reliable
    'a_minute' => ':count ካልኣይት', // less reliable

    'second' => ':count ካልኣይ',
    's' => ':count ካልኣይ',
    'a_second' => ':count ካልኣይ',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/shi.php', [
    'meridiem' => ['tifawt', 'tadggʷat'],
    'weekdays' => ['asamas', 'aynas', 'asinas', 'akṛas', 'akwas', 'asimwas', 'asiḍyas'],
    'weekdays_short' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
    'weekdays_min' => ['asa', 'ayn', 'asi', 'akṛ', 'akw', 'asim', 'asiḍ'],
    'months' => ['innayr', 'bṛayṛ', 'maṛṣ', 'ibrir', 'mayyu', 'yunyu', 'yulyuz', 'ɣuct', 'cutanbir', 'ktubr', 'nuwanbir', 'dujanbir'],
    'months_short' => ['inn', 'bṛa', 'maṛ', 'ibr', 'may', 'yun', 'yul', 'ɣuc', 'cut', 'ktu', 'nuw', 'duj'],
    'first_day_of_week' => 6,
    'weekend' => [5, 6],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'minute' => ':count agur', // less reliable
    'min' => ':count agur', // less reliable
    'a_minute' => ':count agur', // less reliable
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Josh Soref
 * - JD Isaacks
 */
return [
    'year' => '{1}:count asgas|:count isgasn',
    'a_year' => 'asgas|:count isgasn',
    'month' => '{1}:count ayowr|:count iyyirn',
    'a_month' => 'ayowr|:count iyyirn',
    'week' => ':count imalass',
    'a_week' => ':imalass',
    'day' => '{1}:count ass|:count ossan',
    'a_day' => 'ass|:count ossan',
    'hour' => '{1}:count saɛa|:count tassaɛin',
    'a_hour' => '{1}saɛa|:count tassaɛin',
    'minute' => ':count minuḍ',
    'a_minute' => '{1}minuḍ|:count minuḍ',
    'second' => ':count imik',
    'a_second' => '{1}imik|:count imik',
    'ago' => 'yan :time',
    'from_now' => 'dadkh s yan :time',
    'diff_yesterday' => 'assant',
    'diff_yesterday_regexp' => 'assant(?:\\s+g)?',
    'diff_today' => 'asdkh',
    'diff_today_regexp' => 'asdkh(?:\\s+g)?',
    'diff_tomorrow' => 'aska',
    'diff_tomorrow_regexp' => 'aska(?:\\s+g)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[asdkh g] LT',
        'nextDay' => '[aska g] LT',
        'nextWeek' => 'dddd [g] LT',
        'lastDay' => '[assant g] LT',
        'lastWeek' => 'dddd [g] LT',
        'sameElse' => 'L',
    ],
    'months' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'],
    'months_short' => ['innayr', 'brˤayrˤ', 'marˤsˤ', 'ibrir', 'mayyw', 'ywnyw', 'ywlywz', 'ɣwšt', 'šwtanbir', 'ktˤwbrˤ', 'nwwanbir', 'dwjnbir'],
    'weekdays' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
    'weekdays_short' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
    'weekdays_min' => ['asamas', 'aynas', 'asinas', 'akras', 'akwas', 'asimwas', 'asiḍyas'],
    'meridiem' => ['Zdat azal', 'Ḍeffir aza'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Alastair McKinstry    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YY',
    ],
    'months' => ['mis Genver', 'mis Hwevrer', 'mis Meurth', 'mis Ebrel', 'mis Me', 'mis Metheven', 'mis Gortheren', 'mis Est', 'mis Gwynngala', 'mis Hedra', 'mis Du', 'mis Kevardhu'],
    'months_short' => ['Gen', 'Hwe', 'Meu', 'Ebr', 'Me', 'Met', 'Gor', 'Est', 'Gwn', 'Hed', 'Du', 'Kev'],
    'weekdays' => ['De Sul', 'De Lun', 'De Merth', 'De Merher', 'De Yow', 'De Gwener', 'De Sadorn'],
    'weekdays_short' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
    'weekdays_min' => ['Sul', 'Lun', 'Mth', 'Mhr', 'Yow', 'Gwe', 'Sad'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,

    'year' => ':count bledhen',
    'y' => ':count bledhen',
    'a_year' => ':count bledhen',

    'month' => ':count mis',
    'm' => ':count mis',
    'a_month' => ':count mis',

    'week' => ':count seythen',
    'w' => ':count seythen',
    'a_week' => ':count seythen',

    'day' => ':count dydh',
    'd' => ':count dydh',
    'a_day' => ':count dydh',

    'hour' => ':count eur',
    'h' => ':count eur',
    'a_hour' => ':count eur',

    'minute' => ':count mynysen',
    'min' => ':count mynysen',
    'a_minute' => ':count mynysen',

    'second' => ':count pryjwyth',
    's' => ':count pryjwyth',
    'a_second' => ':count pryjwyth',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['makeo', 'nyiaghuo'],
    'weekdays' => ['Jumaapii', 'Jumaatatu', 'Jumaane', 'Jumaatano', 'Alhamisi', 'Ijumaa', 'Jumaamosi'],
    'weekdays_short' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'weekdays_min' => ['Jpi', 'Jtt', 'Jmn', 'Jtn', 'Alh', 'Iju', 'Jmo'],
    'months' => ['Januali', 'Febluali', 'Machi', 'Aplili', 'Mei', 'Juni', 'Julai', 'Agosti', 'Septemba', 'Oktoba', 'Novemba', 'Desemba'],
    'months_short' => ['Jan', 'Feb', 'Mac', 'Apr', 'Mei', 'Jun', 'Jul', 'Ago', 'Sep', 'Okt', 'Nov', 'Des'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Zuza Software Foundation (Translate.org.za) Dwayne Bailey dwayne@translate.org.za
 */
return array_replace_recursive(require __DIR__.'/en.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['Januwari', 'Februwari', 'Mashi', 'Ephreli', 'Meyi', 'Juni', 'Julayi', 'Agasti', 'Septhemba', 'Okthoba', 'Novemba', 'Disemba'],
    'months_short' => ['Jan', 'Feb', 'Mas', 'Eph', 'Mey', 'Jun', 'Jul', 'Aga', 'Sep', 'Okt', 'Nov', 'Dis'],
    'weekdays' => ['iSonto', 'uMsombuluko', 'uLwesibili', 'uLwesithathu', 'uLwesine', 'uLwesihlanu', 'uMgqibelo'],
    'weekdays_short' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
    'weekdays_min' => ['Son', 'Mso', 'Bil', 'Tha', 'Sin', 'Hla', 'Mgq'],
    'first_day_of_week' => 0,
    'day_of_first_week_of_year' => 1,

    'year' => 'kweminyaka engu-:count',
    'y' => 'kweminyaka engu-:count',
    'a_year' => 'kweminyaka engu-:count',

    'month' => 'izinyanga ezingu-:count',
    'm' => 'izinyanga ezingu-:count',
    'a_month' => 'izinyanga ezingu-:count',

    'week' => 'lwamasonto angu-:count',
    'w' => 'lwamasonto angu-:count',
    'a_week' => 'lwamasonto angu-:count',

    'day' => 'ezingaba ngu-:count',
    'd' => 'ezingaba ngu-:count',
    'a_day' => 'ezingaba ngu-:count',

    'hour' => 'amahora angu-:count',
    'h' => 'amahora angu-:count',
    'a_hour' => 'amahora angu-:count',

    'minute' => 'ngemizuzu engu-:count',
    'min' => 'ngemizuzu engu-:count',
    'a_minute' => 'ngemizuzu engu-:count',

    'second' => 'imizuzwana engu-:count',
    's' => 'imizuzwana engu-:count',
    'a_second' => 'imizuzwana engu-:count',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ak_GH.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['ND', 'LK'],
    'weekdays' => ['Bikua-ôko', 'Bïkua-ûse', 'Bïkua-ptâ', 'Bïkua-usïö', 'Bïkua-okü', 'Lâpôsö', 'Lâyenga'],
    'weekdays_short' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
    'weekdays_min' => ['Bk1', 'Bk2', 'Bk3', 'Bk4', 'Bk5', 'Lâp', 'Lây'],
    'months' => ['Nyenye', 'Fulundïgi', 'Mbängü', 'Ngubùe', 'Bêläwü', 'Föndo', 'Lengua', 'Kükürü', 'Mvuka', 'Ngberere', 'Nabändüru', 'Kakauka'],
    'months_short' => ['Nye', 'Ful', 'Mbä', 'Ngu', 'Bêl', 'Fön', 'Len', 'Kük', 'Mvu', 'Ngb', 'Nab', 'Kak'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM, YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'year' => ':count dā', // less reliable
    'y' => ':count dā', // less reliable
    'a_year' => ':count dā', // less reliable

    'week' => ':count bïkua-okü', // less reliable
    'w' => ':count bïkua-okü', // less reliable
    'a_week' => ':count bïkua-okü', // less reliable

    'day' => ':count ziggawâ', // less reliable
    'd' => ':count ziggawâ', // less reliable
    'a_day' => ':count ziggawâ', // less reliable

    'hour' => ':count yângâködörö', // less reliable
    'h' => ':count yângâködörö', // less reliable
    'a_hour' => ':count yângâködörö', // less reliable

    'second' => ':count bïkua-ôko', // less reliable
    's' => ':count bïkua-ôko', // less reliable
    'a_second' => ':count bïkua-ôko', // less reliable

    'month' => ':count Nze tî ngu',
    'm' => ':count Nze tî ngu',
    'a_month' => ':count Nze tî ngu',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ve_ZA.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/fr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'weekdays' => ['Dimas', 'Teneŋ', 'Talata', 'Alarbay', 'Aramisay', 'Arjuma', 'Sibiti'],
    'weekdays_short' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
    'weekdays_min' => ['Dim', 'Ten', 'Tal', 'Ala', 'Ara', 'Arj', 'Sib'],
    'months' => ['Sanvie', 'Fébirie', 'Mars', 'Aburil', 'Mee', 'Sueŋ', 'Súuyee', 'Ut', 'Settembar', 'Oktobar', 'Novembar', 'Disambar'],
    'months_short' => ['Sa', 'Fe', 'Ma', 'Ab', 'Me', 'Su', 'Sú', 'Ut', 'Se', 'Ok', 'No', 'De'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ar.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/sr.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Serhan Apaydın
 * - JD Isaacks
 */
return [
    'year' => '{1}:count bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz',
    'a_year' => '{1}ur bloaz|{3,4,5,9}:count bloaz|[0,Inf[:count vloaz',
    'month' => '{1}:count miz|{2}:count viz|[0,Inf[:count miz',
    'a_month' => '{1}ur miz|{2}:count viz|[0,Inf[:count miz',
    'week' => ':count sizhun',
    'a_week' => '{1}ur sizhun|:count sizhun',
    'day' => '{1}:count devezh|{2}:count zevezh|[0,Inf[:count devezh',
    'a_day' => '{1}un devezh|{2}:count zevezh|[0,Inf[:count devezh',
    'hour' => ':count eur',
    'a_hour' => '{1}un eur|:count eur',
    'minute' => '{1}:count vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn',
    'a_minute' => '{1}ur vunutenn|{2}:count vunutenn|[0,Inf[:count munutenn',
    'second' => ':count eilenn',
    'a_second' => '{1}un nebeud segondennoù|[0,Inf[:count eilenn',
    'ago' => ':time \'zo',
    'from_now' => 'a-benn :time',
    'diff_now' => 'bremañ',
    'diff_today' => 'Hiziv',
    'diff_today_regexp' => 'Hiziv(?:\\s+da)?',
    'diff_yesterday' => 'decʼh',
    'diff_yesterday_regexp' => 'Dec\'h(?:\\s+da)?',
    'diff_tomorrow' => 'warcʼhoazh',
    'diff_tomorrow_regexp' => 'Warc\'hoazh(?:\\s+da)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D [a viz] MMMM YYYY',
        'LLL' => 'D [a viz] MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D [a viz] MMMM YYYY HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Hiziv da] LT',
        'nextDay' => '[Warc\'hoazh da] LT',
        'nextWeek' => 'dddd [da] LT',
        'lastDay' => '[Dec\'h da] LT',
        'lastWeek' => 'dddd [paset da] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static fn ($number) => $number.($number === 1 ? 'añ' : 'vet'),
    'months' => ['Genver', 'C\'hwevrer', 'Meurzh', 'Ebrel', 'Mae', 'Mezheven', 'Gouere', 'Eost', 'Gwengolo', 'Here', 'Du', 'Kerzu'],
    'months_short' => ['Gen', 'C\'hwe', 'Meu', 'Ebr', 'Mae', 'Eve', 'Gou', 'Eos', 'Gwe', 'Her', 'Du', 'Ker'],
    'weekdays' => ['Sul', 'Lun', 'Meurzh', 'Merc\'her', 'Yaou', 'Gwener', 'Sadorn'],
    'weekdays_short' => ['Sul', 'Lun', 'Meu', 'Mer', 'Yao', 'Gwe', 'Sad'],
    'weekdays_min' => ['Su', 'Lu', 'Me', 'Mer', 'Ya', 'Gw', 'Sa'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
    'list' => [', ', ' hag '],
    'meridiem' => ['A.M.', 'G.M.'],

    'y' => ':count bl.',
    'd' => ':count d',
    'h' => ':count e',
    'min' => ':count min',
    's' => ':count s',
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/it.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
    'meridiem' => ['Tesiran', 'Teipa'],
    'weekdays' => ['Mderot ee are', 'Mderot ee kuni', 'Mderot ee ong’wan', 'Mderot ee inet', 'Mderot ee ile', 'Mderot ee sapa', 'Mderot ee kwe'],
    'weekdays_short' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
    'weekdays_min' => ['Are', 'Kun', 'Ong', 'Ine', 'Ile', 'Sap', 'Kwe'],
    'months' => ['Lapa le obo', 'Lapa le waare', 'Lapa le okuni', 'Lapa le ong’wan', 'Lapa le imet', 'Lapa le ile', 'Lapa le sapa', 'Lapa le isiet', 'Lapa le saal', 'Lapa le tomon', 'Lapa le tomon obo', 'Lapa le tomon waare'],
    'months_short' => ['Obo', 'Waa', 'Oku', 'Ong', 'Ime', 'Ile', 'Sap', 'Isi', 'Saa', 'Tom', 'Tob', 'Tow'],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Guo Xiang Tan
 * - Josh Soref
 * - Ash
 * - harpreetkhalsagtbit
 */
return require __DIR__.'/pa.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Unknown default region, use the first alphabetically.
 */
return require __DIR__.'/ayc_PE.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/cy.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat, Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/sd.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'],
    'months_short' => ['جنوري', 'فبروري', 'مارچ', 'اپريل', 'مي', 'جون', 'جولاءِ', 'آگسٽ', 'سيپٽيمبر', 'آڪٽوبر', 'نومبر', 'ڊسمبر'],
    'weekdays' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
    'weekdays_short' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
    'weekdays_min' => ['آرتوارُ', 'سومرُ', 'منگلُ', 'ٻُڌرُ', 'وسپت', 'جُمو', 'ڇنڇر'],
    'day_of_first_week_of_year' => 1,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - François B
 * - Nicolai Davies
 */
return [
    'year' => '{1}umnyaka|:count iminyaka',
    'month' => '{1}inyanga|:count tinyanga',
    'week' => '{1}:count liviki|:count emaviki',
    'day' => '{1}lilanga|:count emalanga',
    'hour' => '{1}lihora|:count emahora',
    'minute' => '{1}umzuzu|:count emizuzu',
    'second' => '{1}emizuzwana lomcane|:count mzuzwana',
    'ago' => 'wenteka nga :time',
    'from_now' => 'nga :time',
    'diff_yesterday' => 'Itolo',
    'diff_yesterday_regexp' => 'Itolo(?:\\s+nga)?',
    'diff_today' => 'Namuhla',
    'diff_today_regexp' => 'Namuhla(?:\\s+nga)?',
    'diff_tomorrow' => 'Kusasa',
    'diff_tomorrow_regexp' => 'Kusasa(?:\\s+nga)?',
    'formats' => [
        'LT' => 'h:mm A',
        'LTS' => 'h:mm:ss A',
        'L' => 'DD/MM/YYYY',
        'LL' => 'D MMMM YYYY',
        'LLL' => 'D MMMM YYYY h:mm A',
        'LLLL' => 'dddd, D MMMM YYYY h:mm A',
    ],
    'calendar' => [
        'sameDay' => '[Namuhla nga] LT',
        'nextDay' => '[Kusasa nga] LT',
        'nextWeek' => 'dddd [nga] LT',
        'lastDay' => '[Itolo nga] LT',
        'lastWeek' => 'dddd [leliphelile] [nga] LT',
        'sameElse' => 'L',
    ],
    'ordinal' => static function ($number) {
        $lastDigit = $number % 10;

        return $number.(
            ((int) ($number % 100 / 10) === 1) ? 'e' : (
                ($lastDigit === 1 || $lastDigit === 2) ? 'a' : 'e'
            )
        );
    },
    'meridiem' => static function ($hour) {
        if ($hour < 11) {
            return 'ekuseni';
        }
        if ($hour < 15) {
            return 'emini';
        }
        if ($hour < 19) {
            return 'entsambama';
        }

        return 'ebusuku';
    },
    'months' => ['Bhimbidvwane', 'Indlovana', 'Indlov\'lenkhulu', 'Mabasa', 'Inkhwekhweti', 'Inhlaba', 'Kholwane', 'Ingci', 'Inyoni', 'Imphala', 'Lweti', 'Ingongoni'],
    'months_short' => ['Bhi', 'Ina', 'Inu', 'Mab', 'Ink', 'Inh', 'Kho', 'Igc', 'Iny', 'Imp', 'Lwe', 'Igo'],
    'weekdays' => ['Lisontfo', 'Umsombuluko', 'Lesibili', 'Lesitsatfu', 'Lesine', 'Lesihlanu', 'Umgcibelo'],
    'weekdays_short' => ['Lis', 'Umb', 'Lsb', 'Les', 'Lsi', 'Lsh', 'Umg'],
    'weekdays_min' => ['Li', 'Us', 'Lb', 'Lt', 'Ls', 'Lh', 'Ug'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - sheriffmarley
 * - Timo
 * - Michael Hohl
 */
return array_replace_recursive(require __DIR__.'/de.php', [
    'weekdays_short' => ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - tarunvelli
 * - Eddie
 * - KID
 * - shankesgk2
 */
return array_replace_recursive(require __DIR__.'/zh_Hant.php', [
    'after' => ':time后',
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'months_short' => ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'أيار', 'حزيران', 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - RAP    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/pt.php', [
    'formats' => [
        'L' => 'DD/MM/YYYY',
    ],
    'months' => ['janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho', 'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
    'months_short' => ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'],
    'weekdays' => ['domingo', 'segunda', 'terça', 'quarta', 'quinta', 'sexta', 'sábado'],
    'weekdays_short' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    'weekdays_min' => ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb'],
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 4,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - IBM Globalization Center of Competency, Yamato Software Laboratory    bug-glibc-locales@gnu.org
 * - Abdullah-Alhariri
 */
return array_replace_recursive(require __DIR__.'/ar.php', [
    'formats' => [
        'L' => 'DD MMM, YYYY',
    ],
    'months' => ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'أكتوبر', 'نوفمبر', 'ديسمبر'],
    'months_short' => ['ينا', 'فبر', 'مار', 'أبر', 'ماي', 'يون', 'يول', 'أغس', 'سبت', 'أكت', 'نوف', 'ديس'],
    'weekdays' => ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
    'weekdays_short' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'weekdays_min' => ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
    'first_day_of_week' => 6,
    'day_of_first_week_of_year' => 1,
    'alt_numbers' => ['۰۰', '۰۱', '۰۲', '۰۳', '۰٤', '۰٥', '۰٦', '۰۷', '۰۸', '۰۹', '۱۰', '۱۱', '۱۲', '۱۳', '۱٤', '۱٥', '۱٦', '۱۷', '۱۸', '۱۹', '۲۰', '۲۱', '۲۲', '۲۳', '۲٤', '۲٥', '۲٦', '۲۷', '۲۸', '۲۹', '۳۰', '۳۱', '۳۲', '۳۳', '۳٤', '۳٥', '۳٦', '۳۷', '۳۸', '۳۹', '٤۰', '٤۱', '٤۲', '٤۳', '٤٤', '٤٥', '٤٦', '٤۷', '٤۸', '٤۹', '٥۰', '٥۱', '٥۲', '٥۳', '٥٤', '٥٥', '٥٦', '٥۷', '٥۸', '٥۹', '٦۰', '٦۱', '٦۲', '٦۳', '٦٤', '٦٥', '٦٦', '٦۷', '٦۸', '٦۹', '۷۰', '۷۱', '۷۲', '۷۳', '۷٤', '۷٥', '۷٦', '۷۷', '۷۸', '۷۹', '۸۰', '۸۱', '۸۲', '۸۳', '۸٤', '۸٥', '۸٦', '۸۷', '۸۸', '۸۹', '۹۰', '۹۱', '۹۲', '۹۳', '۹٤', '۹٥', '۹٦', '۹۷', '۹۸', '۹۹'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'first_day_of_week' => 0,
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ca.php', [
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/zh_Hans.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/ee.php', [
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'LLL' => 'HH:mm MMMM D [lia] YYYY',
        'LLLL' => 'HH:mm dddd, MMMM D [lia] YYYY',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Red Hat, Pune    bug-glibc-locales@gnu.org
 */
return array_replace_recursive(require __DIR__.'/sd.php', [
    'formats' => [
        'L' => 'D/M/YY',
    ],
    'months' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'],
    'months_short' => ['जनवरी', 'फबरवरी', 'मार्चि', 'अप्रेल', 'मे', 'जूनि', 'जूलाइ', 'आगस्टु', 'सेप्टेंबरू', 'आक्टूबरू', 'नवंबरू', 'ॾिसंबरू'],
    'weekdays' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
    'weekdays_short' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
    'weekdays_min' => ['आर्तवारू', 'सूमरू', 'मंगलू', 'ॿुधरू', 'विस्पति', 'जुमो', 'छंछस'],
    'day_of_first_week_of_year' => 1,
    'meridiem' => ['म.पू.', 'म.नं.'],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Carbon\CarbonInterface;
use Symfony\Component\Translation\PluralizationRules;

// @codeCoverageIgnoreStart
if (class_exists(PluralizationRules::class)) {
    PluralizationRules::set(static function ($number) {
        return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
    }, 'be');
}
// @codeCoverageIgnoreEnd

/*
 * Authors:
 * - Josh Soref
 * - SobakaSlava
 * - François B
 * - Serhan Apaydın
 * - JD Isaacks
 * - AbadonnaAbbys
 * - Siomkin Alexander
 */
return [
    'year' => ':count год|:count гады|:count гадоў',
    'a_year' => '{1}год|:count год|:count гады|:count гадоў',
    'y' => ':count год|:count гады|:count гадоў',
    'month' => ':count месяц|:count месяцы|:count месяцаў',
    'a_month' => '{1}месяц|:count месяц|:count месяцы|:count месяцаў',
    'm' => ':count месяц|:count месяцы|:count месяцаў',
    'week' => ':count тыдзень|:count тыдні|:count тыдняў',
    'a_week' => '{1}тыдзень|:count тыдзень|:count тыдні|:count тыдняў',
    'w' => ':count тыдзень|:count тыдні|:count тыдняў',
    'day' => ':count дзень|:count дні|:count дзён',
    'a_day' => '{1}дзень|:count дзень|:count дні|:count дзён',
    'd' => ':count дн',
    'hour' => ':count гадзіну|:count гадзіны|:count гадзін',
    'a_hour' => '{1}гадзіна|:count гадзіна|:count гадзіны|:count гадзін',
    'h' => ':count гадзіна|:count гадзіны|:count гадзін',
    'minute' => ':count хвіліна|:count хвіліны|:count хвілін',
    'a_minute' => '{1}хвіліна|:count хвіліна|:count хвіліны|:count хвілін',
    'min' => ':count хв',
    'second' => ':count секунда|:count секунды|:count секунд',
    'a_second' => '{1}некалькі секунд|:count секунда|:count секунды|:count секунд',
    's' => ':count сек',

    'hour_ago' => ':count гадзіну|:count гадзіны|:count гадзін',
    'a_hour_ago' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
    'h_ago' => ':count гадзіну|:count гадзіны|:count гадзін',
    'minute_ago' => ':count хвіліну|:count хвіліны|:count хвілін',
    'a_minute_ago' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
    'min_ago' => ':count хвіліну|:count хвіліны|:count хвілін',
    'second_ago' => ':count секунду|:count секунды|:count секунд',
    'a_second_ago' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
    's_ago' => ':count секунду|:count секунды|:count секунд',

    'hour_from_now' => ':count гадзіну|:count гадзіны|:count гадзін',
    'a_hour_from_now' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
    'h_from_now' => ':count гадзіну|:count гадзіны|:count гадзін',
    'minute_from_now' => ':count хвіліну|:count хвіліны|:count хвілін',
    'a_minute_from_now' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
    'min_from_now' => ':count хвіліну|:count хвіліны|:count хвілін',
    'second_from_now' => ':count секунду|:count секунды|:count секунд',
    'a_second_from_now' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
    's_from_now' => ':count секунду|:count секунды|:count секунд',

    'hour_after' => ':count гадзіну|:count гадзіны|:count гадзін',
    'a_hour_after' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
    'h_after' => ':count гадзіну|:count гадзіны|:count гадзін',
    'minute_after' => ':count хвіліну|:count хвіліны|:count хвілін',
    'a_minute_after' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
    'min_after' => ':count хвіліну|:count хвіліны|:count хвілін',
    'second_after' => ':count секунду|:count секунды|:count секунд',
    'a_second_after' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
    's_after' => ':count секунду|:count секунды|:count секунд',

    'hour_before' => ':count гадзіну|:count гадзіны|:count гадзін',
    'a_hour_before' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',
    'h_before' => ':count гадзіну|:count гадзіны|:count гадзін',
    'minute_before' => ':count хвіліну|:count хвіліны|:count хвілін',
    'a_minute_before' => '{1}хвіліну|:count хвіліну|:count хвіліны|:count хвілін',
    'min_before' => ':count хвіліну|:count хвіліны|:count хвілін',
    'second_before' => ':count секунду|:count секунды|:count секунд',
    'a_second_before' => '{1}некалькі секунд|:count секунду|:count секунды|:count секунд',
    's_before' => ':count секунду|:count секунды|:count секунд',

    'ago' => ':time таму',
    'from_now' => 'праз :time',
    'after' => ':time пасля',
    'before' => ':time да',
    'diff_now' => 'цяпер',
    'diff_today' => 'Сёння',
    'diff_today_regexp' => 'Сёння(?:\\s+ў)?',
    'diff_yesterday' => 'учора',
    'diff_yesterday_regexp' => 'Учора(?:\\s+ў)?',
    'diff_tomorrow' => 'заўтра',
    'diff_tomorrow_regexp' => 'Заўтра(?:\\s+ў)?',
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'DD.MM.YYYY',
        'LL' => 'D MMMM YYYY г.',
        'LLL' => 'D MMMM YYYY г., HH:mm',
        'LLLL' => 'dddd, D MMMM YYYY г., HH:mm',
    ],
    'calendar' => [
        'sameDay' => '[Сёння ў] LT',
        'nextDay' => '[Заўтра ў] LT',
        'nextWeek' => '[У] dddd [ў] LT',
        'lastDay' => '[Учора ў] LT',
        'lastWeek' => static fn (CarbonInterface $current) => match ($current->dayOfWeek) {
            1, 2, 4 => '[У мінулы] dddd [ў] LT',
            default => '[У мінулую] dddd [ў] LT',
        },
        'sameElse' => 'L',
    ],
    'ordinal' => static fn ($number, $period) => match ($period) {
        'M', 'd', 'DDD', 'w', 'W' => ($number % 10 === 2 || $number % 10 === 3) &&
                ($number % 100 !== 12 && $number % 100 !== 13) ? $number.'-і' : $number.'-ы',
        'D' => $number.'-га',
        default => $number,
    },
    'meridiem' => static function ($hour) {
        if ($hour < 4) {
            return 'ночы';
        }

        if ($hour < 12) {
            return 'раніцы';
        }

        if ($hour < 17) {
            return 'дня';
        }

        return 'вечара';
    },
    'months' => ['студзеня', 'лютага', 'сакавіка', 'красавіка', 'траўня', 'чэрвеня', 'ліпеня', 'жніўня', 'верасня', 'кастрычніка', 'лістапада', 'снежня'],
    'months_standalone' => ['студзень', 'люты', 'сакавік', 'красавік', 'травень', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'],
    'months_short' => ['студ', 'лют', 'сак', 'крас', 'трав', 'чэрв', 'ліп', 'жнів', 'вер', 'каст', 'ліст', 'снеж'],
    'months_regexp' => '/(DD?o?\.?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
    'weekdays' => ['нядзелю', 'панядзелак', 'аўторак', 'сераду', 'чацвер', 'пятніцу', 'суботу'],
    'weekdays_standalone' => ['нядзеля', 'панядзелак', 'аўторак', 'серада', 'чацвер', 'пятніца', 'субота'],
    'weekdays_short' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],
    'weekdays_min' => ['нд', 'пн', 'ат', 'ср', 'чц', 'пт', 'сб'],
    'weekdays_regexp' => '/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/',
    'first_day_of_week' => 1,
    'day_of_first_week_of_year' => 1,
    'list' => [', ', ' і '],
    'months_short_standalone' => ['сту', 'лют', 'сак', 'кра', 'май', 'чэр', 'ліп', 'жні', 'вер', 'кас', 'ліс', 'сне'],
];
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/en.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/fa.php', [
    'months' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
    'months_short' => ['ژانویه', 'فوریه', 'مارس', 'آوریل', 'مه', 'ژوئن', 'ژوئیه', 'اوت', 'سپتامبر', 'اکتبر', 'نوامبر', 'دسامبر'],
    'first_day_of_week' => 6,
    'weekend' => [5, 5],
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'YYYY-MM-dd',
        'LL' => 'YYYY MMM D',
        'LLL' => 'YYYY MMMM D HH:mm',
        'LLLL' => 'YYYY MMMM D, dddd HH:mm',
    ],
]);
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/*
 * Authors:
 * - Free Software Foundation, Inc.    bug-glibc-locales@gnu.org
 */
return require __DIR__.'/de.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return require __DIR__.'/mn.php';
<?php

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

return array_replace_recursive(require __DIR__.'/en.php', [
    'meridiem' => ['idiɓa', 'ebyámu'],
    'weekdays' => ['éti', 'mɔ́sú', 'kwasú', 'mukɔ́sú', 'ŋgisú', 'ɗónɛsú', 'esaɓasú'],
    'weekdays_short' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
    'weekdays_min' => ['ét', 'mɔ́s', 'kwa', 'muk', 'ŋgi', 'ɗón', 'esa'],
    'months' => ['dimɔ́di', 'ŋgɔndɛ', 'sɔŋɛ', 'diɓáɓá', 'emiasele', 'esɔpɛsɔpɛ', 'madiɓɛ́díɓɛ́', 'diŋgindi', 'nyɛtɛki', 'mayésɛ́', 'tiníní', 'eláŋgɛ́'],
    'months_short' => ['di', 'ŋgɔn', 'sɔŋ', 'diɓ', 'emi', 'esɔ', 'mad', 'diŋ', 'nyɛt', 'may', 'tin', 'elá'],
    'first_day_of_week' => 1,
    'formats' => [
        'LT' => 'HH:mm',
        'LTS' => 'HH:mm:ss',
        'L' => 'D/M/YYYY',
        'LL' => 'D MMM YYYY',
        'LLL' => 'D MMMM YYYY HH:mm',
        'LLLL' => 'dddd D MMMM YYYY HH:mm',
    ],

    'year' => ':count ma mbu', // less reliable
    'y' => ':count ma mbu', // less reliable
    'a_year' => ':count ma mbu', // less reliable

    'month' => ':count myo̱di', // less reliable
    'm' => ':count myo̱di', // less reliable
    'a_month' => ':count myo̱di', // less reliable

    'week' => ':count woki', // less reliable
    'w' => ':count woki', // less reliable
    'a_week' => ':count woki', // less reliable

    'day' => ':count buńa', // less reliable
    'd' => ':count buńa', // less reliable
    'a_day' => ':count buńa', // less reliable

    'hour' => ':count ma awa', // less reliable
    'h' => ':count ma awa', // less reliable
    'a_hour' => ':count ma awa', // less reliable

    'minute' => ':count minuti', // less reliable
    'min' => ':count minuti', // less reliable
    'a_minute' => ':count minuti', // less reliable

    'second' => ':count maba', // less reliable
    's' => ':count maba', // less reliable
    'a_second' => ':count maba', // less reliable
]);
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use BadMethodCallException;
use Carbon\Constants\DiffOptions;
use Carbon\Constants\Format;
use Carbon\Constants\TranslationOptions;
use Carbon\Constants\UnitValue;
use Carbon\Exceptions\BadComparisonUnitException;
use Carbon\Exceptions\ImmutableException;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use Carbon\Exceptions\UnknownGetterException;
use Carbon\Exceptions\UnknownMethodException;
use Carbon\Exceptions\UnknownSetterException;
use Closure;
use DateInterval;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use JsonSerializable;
use ReflectionException;
use ReturnTypeWillChange;
use Symfony\Contracts\Translation\TranslatorInterface;
use Throwable;

/**
 * Common interface for Carbon and CarbonImmutable.
 *
 * <autodoc generated by `composer phpdoc`>
 *
 * @property      string           $localeDayOfWeek                                                                   the day of week in current locale
 * @property      string           $shortLocaleDayOfWeek                                                              the abbreviated day of week in current locale
 * @property      string           $localeMonth                                                                       the month in current locale
 * @property      string           $shortLocaleMonth                                                                  the abbreviated month in current locale
 * @property      int              $year
 * @property      int              $yearIso
 * @property      int              $month
 * @property      int              $day
 * @property      int              $hour
 * @property      int              $minute
 * @property      int              $second
 * @property      int              $micro
 * @property      int              $microsecond
 * @property      int              $dayOfWeekIso                                                                      1 (for Monday) through 7 (for Sunday)
 * @property      int|float|string $timestamp                                                                         seconds since the Unix Epoch
 * @property      string           $englishDayOfWeek                                                                  the day of week in English
 * @property      string           $shortEnglishDayOfWeek                                                             the abbreviated day of week in English
 * @property      string           $englishMonth                                                                      the month in English
 * @property      string           $shortEnglishMonth                                                                 the abbreviated month in English
 * @property      int              $milliseconds
 * @property      int              $millisecond
 * @property      int              $milli
 * @property      int              $week                                                                              1 through 53
 * @property      int              $isoWeek                                                                           1 through 53
 * @property      int              $weekYear                                                                          year according to week format
 * @property      int              $isoWeekYear                                                                       year according to ISO week format
 * @property      int              $age                                                                               does a diffInYears() with default parameters
 * @property      int              $offset                                                                            the timezone offset in seconds from UTC
 * @property      int              $offsetMinutes                                                                     the timezone offset in minutes from UTC
 * @property      int              $offsetHours                                                                       the timezone offset in hours from UTC
 * @property      CarbonTimeZone   $timezone                                                                          the current timezone
 * @property      CarbonTimeZone   $tz                                                                                alias of $timezone
 * @property      int              $centuryOfMillennium                                                               The value of the century starting from the beginning of the current millennium
 * @property      int              $dayOfCentury                                                                      The value of the day starting from the beginning of the current century
 * @property      int              $dayOfDecade                                                                       The value of the day starting from the beginning of the current decade
 * @property      int              $dayOfMillennium                                                                   The value of the day starting from the beginning of the current millennium
 * @property      int              $dayOfMonth                                                                        The value of the day starting from the beginning of the current month
 * @property      int              $dayOfQuarter                                                                      The value of the day starting from the beginning of the current quarter
 * @property      int              $dayOfWeek                                                                         0 (for Sunday) through 6 (for Saturday)
 * @property      int              $dayOfYear                                                                         1 through 366
 * @property      int              $decadeOfCentury                                                                   The value of the decade starting from the beginning of the current century
 * @property      int              $decadeOfMillennium                                                                The value of the decade starting from the beginning of the current millennium
 * @property      int              $hourOfCentury                                                                     The value of the hour starting from the beginning of the current century
 * @property      int              $hourOfDay                                                                         The value of the hour starting from the beginning of the current day
 * @property      int              $hourOfDecade                                                                      The value of the hour starting from the beginning of the current decade
 * @property      int              $hourOfMillennium                                                                  The value of the hour starting from the beginning of the current millennium
 * @property      int              $hourOfMonth                                                                       The value of the hour starting from the beginning of the current month
 * @property      int              $hourOfQuarter                                                                     The value of the hour starting from the beginning of the current quarter
 * @property      int              $hourOfWeek                                                                        The value of the hour starting from the beginning of the current week
 * @property      int              $hourOfYear                                                                        The value of the hour starting from the beginning of the current year
 * @property      int              $microsecondOfCentury                                                              The value of the microsecond starting from the beginning of the current century
 * @property      int              $microsecondOfDay                                                                  The value of the microsecond starting from the beginning of the current day
 * @property      int              $microsecondOfDecade                                                               The value of the microsecond starting from the beginning of the current decade
 * @property      int              $microsecondOfHour                                                                 The value of the microsecond starting from the beginning of the current hour
 * @property      int              $microsecondOfMillennium                                                           The value of the microsecond starting from the beginning of the current millennium
 * @property      int              $microsecondOfMillisecond                                                          The value of the microsecond starting from the beginning of the current millisecond
 * @property      int              $microsecondOfMinute                                                               The value of the microsecond starting from the beginning of the current minute
 * @property      int              $microsecondOfMonth                                                                The value of the microsecond starting from the beginning of the current month
 * @property      int              $microsecondOfQuarter                                                              The value of the microsecond starting from the beginning of the current quarter
 * @property      int              $microsecondOfSecond                                                               The value of the microsecond starting from the beginning of the current second
 * @property      int              $microsecondOfWeek                                                                 The value of the microsecond starting from the beginning of the current week
 * @property      int              $microsecondOfYear                                                                 The value of the microsecond starting from the beginning of the current year
 * @property      int              $millisecondOfCentury                                                              The value of the millisecond starting from the beginning of the current century
 * @property      int              $millisecondOfDay                                                                  The value of the millisecond starting from the beginning of the current day
 * @property      int              $millisecondOfDecade                                                               The value of the millisecond starting from the beginning of the current decade
 * @property      int              $millisecondOfHour                                                                 The value of the millisecond starting from the beginning of the current hour
 * @property      int              $millisecondOfMillennium                                                           The value of the millisecond starting from the beginning of the current millennium
 * @property      int              $millisecondOfMinute                                                               The value of the millisecond starting from the beginning of the current minute
 * @property      int              $millisecondOfMonth                                                                The value of the millisecond starting from the beginning of the current month
 * @property      int              $millisecondOfQuarter                                                              The value of the millisecond starting from the beginning of the current quarter
 * @property      int              $millisecondOfSecond                                                               The value of the millisecond starting from the beginning of the current second
 * @property      int              $millisecondOfWeek                                                                 The value of the millisecond starting from the beginning of the current week
 * @property      int              $millisecondOfYear                                                                 The value of the millisecond starting from the beginning of the current year
 * @property      int              $minuteOfCentury                                                                   The value of the minute starting from the beginning of the current century
 * @property      int              $minuteOfDay                                                                       The value of the minute starting from the beginning of the current day
 * @property      int              $minuteOfDecade                                                                    The value of the minute starting from the beginning of the current decade
 * @property      int              $minuteOfHour                                                                      The value of the minute starting from the beginning of the current hour
 * @property      int              $minuteOfMillennium                                                                The value of the minute starting from the beginning of the current millennium
 * @property      int              $minuteOfMonth                                                                     The value of the minute starting from the beginning of the current month
 * @property      int              $minuteOfQuarter                                                                   The value of the minute starting from the beginning of the current quarter
 * @property      int              $minuteOfWeek                                                                      The value of the minute starting from the beginning of the current week
 * @property      int              $minuteOfYear                                                                      The value of the minute starting from the beginning of the current year
 * @property      int              $monthOfCentury                                                                    The value of the month starting from the beginning of the current century
 * @property      int              $monthOfDecade                                                                     The value of the month starting from the beginning of the current decade
 * @property      int              $monthOfMillennium                                                                 The value of the month starting from the beginning of the current millennium
 * @property      int              $monthOfQuarter                                                                    The value of the month starting from the beginning of the current quarter
 * @property      int              $monthOfYear                                                                       The value of the month starting from the beginning of the current year
 * @property      int              $quarterOfCentury                                                                  The value of the quarter starting from the beginning of the current century
 * @property      int              $quarterOfDecade                                                                   The value of the quarter starting from the beginning of the current decade
 * @property      int              $quarterOfMillennium                                                               The value of the quarter starting from the beginning of the current millennium
 * @property      int              $quarterOfYear                                                                     The value of the quarter starting from the beginning of the current year
 * @property      int              $secondOfCentury                                                                   The value of the second starting from the beginning of the current century
 * @property      int              $secondOfDay                                                                       The value of the second starting from the beginning of the current day
 * @property      int              $secondOfDecade                                                                    The value of the second starting from the beginning of the current decade
 * @property      int              $secondOfHour                                                                      The value of the second starting from the beginning of the current hour
 * @property      int              $secondOfMillennium                                                                The value of the second starting from the beginning of the current millennium
 * @property      int              $secondOfMinute                                                                    The value of the second starting from the beginning of the current minute
 * @property      int              $secondOfMonth                                                                     The value of the second starting from the beginning of the current month
 * @property      int              $secondOfQuarter                                                                   The value of the second starting from the beginning of the current quarter
 * @property      int              $secondOfWeek                                                                      The value of the second starting from the beginning of the current week
 * @property      int              $secondOfYear                                                                      The value of the second starting from the beginning of the current year
 * @property      int              $weekOfCentury                                                                     The value of the week starting from the beginning of the current century
 * @property      int              $weekOfDecade                                                                      The value of the week starting from the beginning of the current decade
 * @property      int              $weekOfMillennium                                                                  The value of the week starting from the beginning of the current millennium
 * @property      int              $weekOfMonth                                                                       1 through 5
 * @property      int              $weekOfQuarter                                                                     The value of the week starting from the beginning of the current quarter
 * @property      int              $weekOfYear                                                                        ISO-8601 week number of year, weeks starting on Monday
 * @property      int              $yearOfCentury                                                                     The value of the year starting from the beginning of the current century
 * @property      int              $yearOfDecade                                                                      The value of the year starting from the beginning of the current decade
 * @property      int              $yearOfMillennium                                                                  The value of the year starting from the beginning of the current millennium
 * @property-read string           $latinMeridiem                                                                     "am"/"pm" (Ante meridiem or Post meridiem latin lowercase mark)
 * @property-read string           $latinUpperMeridiem                                                                "AM"/"PM" (Ante meridiem or Post meridiem latin uppercase mark)
 * @property-read string           $timezoneAbbreviatedName                                                           the current timezone abbreviated name
 * @property-read string           $tzAbbrName                                                                        alias of $timezoneAbbreviatedName
 * @property-read string           $dayName                                                                           long name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortDayName                                                                      short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $minDayName                                                                        very short name of weekday translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $monthName                                                                         long name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $shortMonthName                                                                    short name of month translated according to Carbon locale, in english if no translation available for current language
 * @property-read string           $meridiem                                                                          lowercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read string           $upperMeridiem                                                                     uppercase meridiem mark translated according to Carbon locale, in latin if no translation available for current language
 * @property-read int              $noZeroHour                                                                        current hour from 1 to 24
 * @property-read int              $isoWeeksInYear                                                                    51 through 53
 * @property-read int              $weekNumberInMonth                                                                 1 through 5
 * @property-read int              $firstWeekDay                                                                      0 through 6
 * @property-read int              $lastWeekDay                                                                       0 through 6
 * @property-read int              $quarter                                                                           the quarter of this instance, 1 - 4
 * @property-read int              $decade                                                                            the decade of this instance
 * @property-read int              $century                                                                           the century of this instance
 * @property-read int              $millennium                                                                        the millennium of this instance
 * @property-read bool             $dst                                                                               daylight savings time indicator, true if DST, false otherwise
 * @property-read bool             $local                                                                             checks if the timezone is local, true if local, false otherwise
 * @property-read bool             $utc                                                                               checks if the timezone is UTC, true if UTC, false otherwise
 * @property-read string           $timezoneName                                                                      the current timezone name
 * @property-read string           $tzName                                                                            alias of $timezoneName
 * @property-read string           $locale                                                                            locale of the current instance
 * @property-read int              $centuriesInMillennium                                                             The number of centuries contained in the current millennium
 * @property-read int              $daysInCentury                                                                     The number of days contained in the current century
 * @property-read int              $daysInDecade                                                                      The number of days contained in the current decade
 * @property-read int              $daysInMillennium                                                                  The number of days contained in the current millennium
 * @property-read int              $daysInMonth                                                                       number of days in the given month
 * @property-read int              $daysInQuarter                                                                     The number of days contained in the current quarter
 * @property-read int              $daysInWeek                                                                        The number of days contained in the current week
 * @property-read int              $daysInYear                                                                        365 or 366
 * @property-read int              $decadesInCentury                                                                  The number of decades contained in the current century
 * @property-read int              $decadesInMillennium                                                               The number of decades contained in the current millennium
 * @property-read int              $hoursInCentury                                                                    The number of hours contained in the current century
 * @property-read int              $hoursInDay                                                                        The number of hours contained in the current day
 * @property-read int              $hoursInDecade                                                                     The number of hours contained in the current decade
 * @property-read int              $hoursInMillennium                                                                 The number of hours contained in the current millennium
 * @property-read int              $hoursInMonth                                                                      The number of hours contained in the current month
 * @property-read int              $hoursInQuarter                                                                    The number of hours contained in the current quarter
 * @property-read int              $hoursInWeek                                                                       The number of hours contained in the current week
 * @property-read int              $hoursInYear                                                                       The number of hours contained in the current year
 * @property-read int              $microsecondsInCentury                                                             The number of microseconds contained in the current century
 * @property-read int              $microsecondsInDay                                                                 The number of microseconds contained in the current day
 * @property-read int              $microsecondsInDecade                                                              The number of microseconds contained in the current decade
 * @property-read int              $microsecondsInHour                                                                The number of microseconds contained in the current hour
 * @property-read int              $microsecondsInMillennium                                                          The number of microseconds contained in the current millennium
 * @property-read int              $microsecondsInMillisecond                                                         The number of microseconds contained in the current millisecond
 * @property-read int              $microsecondsInMinute                                                              The number of microseconds contained in the current minute
 * @property-read int              $microsecondsInMonth                                                               The number of microseconds contained in the current month
 * @property-read int              $microsecondsInQuarter                                                             The number of microseconds contained in the current quarter
 * @property-read int              $microsecondsInSecond                                                              The number of microseconds contained in the current second
 * @property-read int              $microsecondsInWeek                                                                The number of microseconds contained in the current week
 * @property-read int              $microsecondsInYear                                                                The number of microseconds contained in the current year
 * @property-read int              $millisecondsInCentury                                                             The number of milliseconds contained in the current century
 * @property-read int              $millisecondsInDay                                                                 The number of milliseconds contained in the current day
 * @property-read int              $millisecondsInDecade                                                              The number of milliseconds contained in the current decade
 * @property-read int              $millisecondsInHour                                                                The number of milliseconds contained in the current hour
 * @property-read int              $millisecondsInMillennium                                                          The number of milliseconds contained in the current millennium
 * @property-read int              $millisecondsInMinute                                                              The number of milliseconds contained in the current minute
 * @property-read int              $millisecondsInMonth                                                               The number of milliseconds contained in the current month
 * @property-read int              $millisecondsInQuarter                                                             The number of milliseconds contained in the current quarter
 * @property-read int              $millisecondsInSecond                                                              The number of milliseconds contained in the current second
 * @property-read int              $millisecondsInWeek                                                                The number of milliseconds contained in the current week
 * @property-read int              $millisecondsInYear                                                                The number of milliseconds contained in the current year
 * @property-read int              $minutesInCentury                                                                  The number of minutes contained in the current century
 * @property-read int              $minutesInDay                                                                      The number of minutes contained in the current day
 * @property-read int              $minutesInDecade                                                                   The number of minutes contained in the current decade
 * @property-read int              $minutesInHour                                                                     The number of minutes contained in the current hour
 * @property-read int              $minutesInMillennium                                                               The number of minutes contained in the current millennium
 * @property-read int              $minutesInMonth                                                                    The number of minutes contained in the current month
 * @property-read int              $minutesInQuarter                                                                  The number of minutes contained in the current quarter
 * @property-read int              $minutesInWeek                                                                     The number of minutes contained in the current week
 * @property-read int              $minutesInYear                                                                     The number of minutes contained in the current year
 * @property-read int              $monthsInCentury                                                                   The number of months contained in the current century
 * @property-read int              $monthsInDecade                                                                    The number of months contained in the current decade
 * @property-read int              $monthsInMillennium                                                                The number of months contained in the current millennium
 * @property-read int              $monthsInQuarter                                                                   The number of months contained in the current quarter
 * @property-read int              $monthsInYear                                                                      The number of months contained in the current year
 * @property-read int              $quartersInCentury                                                                 The number of quarters contained in the current century
 * @property-read int              $quartersInDecade                                                                  The number of quarters contained in the current decade
 * @property-read int              $quartersInMillennium                                                              The number of quarters contained in the current millennium
 * @property-read int              $quartersInYear                                                                    The number of quarters contained in the current year
 * @property-read int              $secondsInCentury                                                                  The number of seconds contained in the current century
 * @property-read int              $secondsInDay                                                                      The number of seconds contained in the current day
 * @property-read int              $secondsInDecade                                                                   The number of seconds contained in the current decade
 * @property-read int              $secondsInHour                                                                     The number of seconds contained in the current hour
 * @property-read int              $secondsInMillennium                                                               The number of seconds contained in the current millennium
 * @property-read int              $secondsInMinute                                                                   The number of seconds contained in the current minute
 * @property-read int              $secondsInMonth                                                                    The number of seconds contained in the current month
 * @property-read int              $secondsInQuarter                                                                  The number of seconds contained in the current quarter
 * @property-read int              $secondsInWeek                                                                     The number of seconds contained in the current week
 * @property-read int              $secondsInYear                                                                     The number of seconds contained in the current year
 * @property-read int              $weeksInCentury                                                                    The number of weeks contained in the current century
 * @property-read int              $weeksInDecade                                                                     The number of weeks contained in the current decade
 * @property-read int              $weeksInMillennium                                                                 The number of weeks contained in the current millennium
 * @property-read int              $weeksInMonth                                                                      The number of weeks contained in the current month
 * @property-read int              $weeksInQuarter                                                                    The number of weeks contained in the current quarter
 * @property-read int              $weeksInYear                                                                       51 through 53
 * @property-read int              $yearsInCentury                                                                    The number of years contained in the current century
 * @property-read int              $yearsInDecade                                                                     The number of years contained in the current decade
 * @property-read int              $yearsInMillennium                                                                 The number of years contained in the current millennium
 *
 * @method        bool             isUtc()                                                                            Check if the current instance has UTC timezone. (Both isUtc and isUTC cases are valid.)
 * @method        bool             isLocal()                                                                          Check if the current instance has non-UTC timezone.
 * @method        bool             isValid()                                                                          Check if the current instance is a valid date.
 * @method        bool             isDST()                                                                            Check if the current instance is in a daylight saving time.
 * @method        bool             isSunday()                                                                         Checks if the instance day is sunday.
 * @method        bool             isMonday()                                                                         Checks if the instance day is monday.
 * @method        bool             isTuesday()                                                                        Checks if the instance day is tuesday.
 * @method        bool             isWednesday()                                                                      Checks if the instance day is wednesday.
 * @method        bool             isThursday()                                                                       Checks if the instance day is thursday.
 * @method        bool             isFriday()                                                                         Checks if the instance day is friday.
 * @method        bool             isSaturday()                                                                       Checks if the instance day is saturday.
 * @method        bool             isSameYear(DateTimeInterface|string $date)                                         Checks if the given date is in the same year as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentYear()                                                                    Checks if the instance is in the same year as the current moment.
 * @method        bool             isNextYear()                                                                       Checks if the instance is in the same year as the current moment next year.
 * @method        bool             isLastYear()                                                                       Checks if the instance is in the same year as the current moment last year.
 * @method        bool             isCurrentMonth()                                                                   Checks if the instance is in the same month as the current moment.
 * @method        bool             isNextMonth()                                                                      Checks if the instance is in the same month as the current moment next month.
 * @method        bool             isLastMonth()                                                                      Checks if the instance is in the same month as the current moment last month.
 * @method        bool             isSameWeek(DateTimeInterface|string $date)                                         Checks if the given date is in the same week as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentWeek()                                                                    Checks if the instance is in the same week as the current moment.
 * @method        bool             isNextWeek()                                                                       Checks if the instance is in the same week as the current moment next week.
 * @method        bool             isLastWeek()                                                                       Checks if the instance is in the same week as the current moment last week.
 * @method        bool             isSameDay(DateTimeInterface|string $date)                                          Checks if the given date is in the same day as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDay()                                                                     Checks if the instance is in the same day as the current moment.
 * @method        bool             isNextDay()                                                                        Checks if the instance is in the same day as the current moment next day.
 * @method        bool             isLastDay()                                                                        Checks if the instance is in the same day as the current moment last day.
 * @method        bool             isSameHour(DateTimeInterface|string $date)                                         Checks if the given date is in the same hour as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentHour()                                                                    Checks if the instance is in the same hour as the current moment.
 * @method        bool             isNextHour()                                                                       Checks if the instance is in the same hour as the current moment next hour.
 * @method        bool             isLastHour()                                                                       Checks if the instance is in the same hour as the current moment last hour.
 * @method        bool             isSameMinute(DateTimeInterface|string $date)                                       Checks if the given date is in the same minute as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMinute()                                                                  Checks if the instance is in the same minute as the current moment.
 * @method        bool             isNextMinute()                                                                     Checks if the instance is in the same minute as the current moment next minute.
 * @method        bool             isLastMinute()                                                                     Checks if the instance is in the same minute as the current moment last minute.
 * @method        bool             isSameSecond(DateTimeInterface|string $date)                                       Checks if the given date is in the same second as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentSecond()                                                                  Checks if the instance is in the same second as the current moment.
 * @method        bool             isNextSecond()                                                                     Checks if the instance is in the same second as the current moment next second.
 * @method        bool             isLastSecond()                                                                     Checks if the instance is in the same second as the current moment last second.
 * @method        bool             isSameMilli(DateTimeInterface|string $date)                                        Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMilli()                                                                   Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMilli()                                                                      Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMilli()                                                                      Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMillisecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same millisecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillisecond()                                                             Checks if the instance is in the same millisecond as the current moment.
 * @method        bool             isNextMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment next millisecond.
 * @method        bool             isLastMillisecond()                                                                Checks if the instance is in the same millisecond as the current moment last millisecond.
 * @method        bool             isSameMicro(DateTimeInterface|string $date)                                        Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicro()                                                                   Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicro()                                                                      Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicro()                                                                      Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameMicrosecond(DateTimeInterface|string $date)                                  Checks if the given date is in the same microsecond as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMicrosecond()                                                             Checks if the instance is in the same microsecond as the current moment.
 * @method        bool             isNextMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment next microsecond.
 * @method        bool             isLastMicrosecond()                                                                Checks if the instance is in the same microsecond as the current moment last microsecond.
 * @method        bool             isSameDecade(DateTimeInterface|string $date)                                       Checks if the given date is in the same decade as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentDecade()                                                                  Checks if the instance is in the same decade as the current moment.
 * @method        bool             isNextDecade()                                                                     Checks if the instance is in the same decade as the current moment next decade.
 * @method        bool             isLastDecade()                                                                     Checks if the instance is in the same decade as the current moment last decade.
 * @method        bool             isSameCentury(DateTimeInterface|string $date)                                      Checks if the given date is in the same century as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentCentury()                                                                 Checks if the instance is in the same century as the current moment.
 * @method        bool             isNextCentury()                                                                    Checks if the instance is in the same century as the current moment next century.
 * @method        bool             isLastCentury()                                                                    Checks if the instance is in the same century as the current moment last century.
 * @method        bool             isSameMillennium(DateTimeInterface|string $date)                                   Checks if the given date is in the same millennium as the instance. If null passed, compare to now (with the same timezone).
 * @method        bool             isCurrentMillennium()                                                              Checks if the instance is in the same millennium as the current moment.
 * @method        bool             isNextMillennium()                                                                 Checks if the instance is in the same millennium as the current moment next millennium.
 * @method        bool             isLastMillennium()                                                                 Checks if the instance is in the same millennium as the current moment last millennium.
 * @method        bool             isCurrentQuarter()                                                                 Checks if the instance is in the same quarter as the current moment.
 * @method        bool             isNextQuarter()                                                                    Checks if the instance is in the same quarter as the current moment next quarter.
 * @method        bool             isLastQuarter()                                                                    Checks if the instance is in the same quarter as the current moment last quarter.
 * @method        CarbonInterface  years(int $value)                                                                  Set current instance year to the given value.
 * @method        CarbonInterface  year(int $value)                                                                   Set current instance year to the given value.
 * @method        CarbonInterface  setYears(int $value)                                                               Set current instance year to the given value.
 * @method        CarbonInterface  setYear(int $value)                                                                Set current instance year to the given value.
 * @method        CarbonInterface  months(Month|int $value)                                                           Set current instance month to the given value.
 * @method        CarbonInterface  month(Month|int $value)                                                            Set current instance month to the given value.
 * @method        CarbonInterface  setMonths(Month|int $value)                                                        Set current instance month to the given value.
 * @method        CarbonInterface  setMonth(Month|int $value)                                                         Set current instance month to the given value.
 * @method        CarbonInterface  days(int $value)                                                                   Set current instance day to the given value.
 * @method        CarbonInterface  day(int $value)                                                                    Set current instance day to the given value.
 * @method        CarbonInterface  setDays(int $value)                                                                Set current instance day to the given value.
 * @method        CarbonInterface  setDay(int $value)                                                                 Set current instance day to the given value.
 * @method        CarbonInterface  hours(int $value)                                                                  Set current instance hour to the given value.
 * @method        CarbonInterface  hour(int $value)                                                                   Set current instance hour to the given value.
 * @method        CarbonInterface  setHours(int $value)                                                               Set current instance hour to the given value.
 * @method        CarbonInterface  setHour(int $value)                                                                Set current instance hour to the given value.
 * @method        CarbonInterface  minutes(int $value)                                                                Set current instance minute to the given value.
 * @method        CarbonInterface  minute(int $value)                                                                 Set current instance minute to the given value.
 * @method        CarbonInterface  setMinutes(int $value)                                                             Set current instance minute to the given value.
 * @method        CarbonInterface  setMinute(int $value)                                                              Set current instance minute to the given value.
 * @method        CarbonInterface  seconds(int $value)                                                                Set current instance second to the given value.
 * @method        CarbonInterface  second(int $value)                                                                 Set current instance second to the given value.
 * @method        CarbonInterface  setSeconds(int $value)                                                             Set current instance second to the given value.
 * @method        CarbonInterface  setSecond(int $value)                                                              Set current instance second to the given value.
 * @method        CarbonInterface  millis(int $value)                                                                 Set current instance millisecond to the given value.
 * @method        CarbonInterface  milli(int $value)                                                                  Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMillis(int $value)                                                              Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMilli(int $value)                                                               Set current instance millisecond to the given value.
 * @method        CarbonInterface  milliseconds(int $value)                                                           Set current instance millisecond to the given value.
 * @method        CarbonInterface  millisecond(int $value)                                                            Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMilliseconds(int $value)                                                        Set current instance millisecond to the given value.
 * @method        CarbonInterface  setMillisecond(int $value)                                                         Set current instance millisecond to the given value.
 * @method        CarbonInterface  micros(int $value)                                                                 Set current instance microsecond to the given value.
 * @method        CarbonInterface  micro(int $value)                                                                  Set current instance microsecond to the given value.
 * @method        CarbonInterface  setMicros(int $value)                                                              Set current instance microsecond to the given value.
 * @method        CarbonInterface  setMicro(int $value)                                                               Set current instance microsecond to the given value.
 * @method        CarbonInterface  microseconds(int $value)                                                           Set current instance microsecond to the given value.
 * @method        CarbonInterface  microsecond(int $value)                                                            Set current instance microsecond to the given value.
 * @method        CarbonInterface  setMicroseconds(int $value)                                                        Set current instance microsecond to the given value.
 * @method        self             setMicrosecond(int $value)                                                         Set current instance microsecond to the given value.
 * @method        CarbonInterface  addYears(int|float $value = 1)                                                     Add years (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addYear()                                                                          Add one year to the instance (using date interval).
 * @method        CarbonInterface  subYears(int|float $value = 1)                                                     Sub years (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subYear()                                                                          Sub one year to the instance (using date interval).
 * @method        CarbonInterface  addYearsWithOverflow(int|float $value = 1)                                         Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addYearWithOverflow()                                                              Add one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subYearsWithOverflow(int|float $value = 1)                                         Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subYearWithOverflow()                                                              Sub one year to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addYearsWithoutOverflow(int|float $value = 1)                                      Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearWithoutOverflow()                                                           Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearsWithoutOverflow(int|float $value = 1)                                      Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearWithoutOverflow()                                                           Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearsWithNoOverflow(int|float $value = 1)                                       Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearWithNoOverflow()                                                            Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearsWithNoOverflow(int|float $value = 1)                                       Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearWithNoOverflow()                                                            Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearsNoOverflow(int|float $value = 1)                                           Add years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addYearNoOverflow()                                                                Add one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearsNoOverflow(int|float $value = 1)                                           Sub years (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subYearNoOverflow()                                                                Sub one year to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonths(int|float $value = 1)                                                    Add months (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMonth()                                                                         Add one month to the instance (using date interval).
 * @method        CarbonInterface  subMonths(int|float $value = 1)                                                    Sub months (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMonth()                                                                         Sub one month to the instance (using date interval).
 * @method        CarbonInterface  addMonthsWithOverflow(int|float $value = 1)                                        Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMonthWithOverflow()                                                             Add one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMonthsWithOverflow(int|float $value = 1)                                        Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMonthWithOverflow()                                                             Sub one month to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMonthsWithoutOverflow(int|float $value = 1)                                     Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthWithoutOverflow()                                                          Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthsWithoutOverflow(int|float $value = 1)                                     Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthWithoutOverflow()                                                          Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthsWithNoOverflow(int|float $value = 1)                                      Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthWithNoOverflow()                                                           Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthsWithNoOverflow(int|float $value = 1)                                      Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthWithNoOverflow()                                                           Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthsNoOverflow(int|float $value = 1)                                          Add months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMonthNoOverflow()                                                               Add one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthsNoOverflow(int|float $value = 1)                                          Sub months (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMonthNoOverflow()                                                               Sub one month to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDays(int|float $value = 1)                                                      Add days (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addDay()                                                                           Add one day to the instance (using date interval).
 * @method        CarbonInterface  subDays(int|float $value = 1)                                                      Sub days (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subDay()                                                                           Sub one day to the instance (using date interval).
 * @method        CarbonInterface  addHours(int|float $value = 1)                                                     Add hours (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addHour()                                                                          Add one hour to the instance (using date interval).
 * @method        CarbonInterface  subHours(int|float $value = 1)                                                     Sub hours (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subHour()                                                                          Sub one hour to the instance (using date interval).
 * @method        CarbonInterface  addMinutes(int|float $value = 1)                                                   Add minutes (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMinute()                                                                        Add one minute to the instance (using date interval).
 * @method        CarbonInterface  subMinutes(int|float $value = 1)                                                   Sub minutes (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMinute()                                                                        Sub one minute to the instance (using date interval).
 * @method        CarbonInterface  addSeconds(int|float $value = 1)                                                   Add seconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addSecond()                                                                        Add one second to the instance (using date interval).
 * @method        CarbonInterface  subSeconds(int|float $value = 1)                                                   Sub seconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subSecond()                                                                        Sub one second to the instance (using date interval).
 * @method        CarbonInterface  addMillis(int|float $value = 1)                                                    Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMilli()                                                                         Add one millisecond to the instance (using date interval).
 * @method        CarbonInterface  subMillis(int|float $value = 1)                                                    Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMilli()                                                                         Sub one millisecond to the instance (using date interval).
 * @method        CarbonInterface  addMilliseconds(int|float $value = 1)                                              Add milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMillisecond()                                                                   Add one millisecond to the instance (using date interval).
 * @method        CarbonInterface  subMilliseconds(int|float $value = 1)                                              Sub milliseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMillisecond()                                                                   Sub one millisecond to the instance (using date interval).
 * @method        CarbonInterface  addMicros(int|float $value = 1)                                                    Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMicro()                                                                         Add one microsecond to the instance (using date interval).
 * @method        CarbonInterface  subMicros(int|float $value = 1)                                                    Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMicro()                                                                         Sub one microsecond to the instance (using date interval).
 * @method        CarbonInterface  addMicroseconds(int|float $value = 1)                                              Add microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMicrosecond()                                                                   Add one microsecond to the instance (using date interval).
 * @method        CarbonInterface  subMicroseconds(int|float $value = 1)                                              Sub microseconds (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMicrosecond()                                                                   Sub one microsecond to the instance (using date interval).
 * @method        CarbonInterface  addMillennia(int|float $value = 1)                                                 Add millennia (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addMillennium()                                                                    Add one millennium to the instance (using date interval).
 * @method        CarbonInterface  subMillennia(int|float $value = 1)                                                 Sub millennia (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subMillennium()                                                                    Sub one millennium to the instance (using date interval).
 * @method        CarbonInterface  addMillenniaWithOverflow(int|float $value = 1)                                     Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMillenniumWithOverflow()                                                        Add one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMillenniaWithOverflow(int|float $value = 1)                                     Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subMillenniumWithOverflow()                                                        Sub one millennium to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addMillenniaWithoutOverflow(int|float $value = 1)                                  Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniumWithoutOverflow()                                                     Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniaWithoutOverflow(int|float $value = 1)                                  Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniumWithoutOverflow()                                                     Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniaWithNoOverflow(int|float $value = 1)                                   Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniumWithNoOverflow()                                                      Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniaWithNoOverflow(int|float $value = 1)                                   Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniumWithNoOverflow()                                                      Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniaNoOverflow(int|float $value = 1)                                       Add millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addMillenniumNoOverflow()                                                          Add one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniaNoOverflow(int|float $value = 1)                                       Sub millennia (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subMillenniumNoOverflow()                                                          Sub one millennium to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturies(int|float $value = 1)                                                 Add centuries (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addCentury()                                                                       Add one century to the instance (using date interval).
 * @method        CarbonInterface  subCenturies(int|float $value = 1)                                                 Sub centuries (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subCentury()                                                                       Sub one century to the instance (using date interval).
 * @method        CarbonInterface  addCenturiesWithOverflow(int|float $value = 1)                                     Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addCenturyWithOverflow()                                                           Add one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subCenturiesWithOverflow(int|float $value = 1)                                     Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subCenturyWithOverflow()                                                           Sub one century to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addCenturiesWithoutOverflow(int|float $value = 1)                                  Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturyWithoutOverflow()                                                        Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturiesWithoutOverflow(int|float $value = 1)                                  Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturyWithoutOverflow()                                                        Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturiesWithNoOverflow(int|float $value = 1)                                   Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturyWithNoOverflow()                                                         Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturiesWithNoOverflow(int|float $value = 1)                                   Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturyWithNoOverflow()                                                         Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturiesNoOverflow(int|float $value = 1)                                       Add centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addCenturyNoOverflow()                                                             Add one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturiesNoOverflow(int|float $value = 1)                                       Sub centuries (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subCenturyNoOverflow()                                                             Sub one century to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecades(int|float $value = 1)                                                   Add decades (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addDecade()                                                                        Add one decade to the instance (using date interval).
 * @method        CarbonInterface  subDecades(int|float $value = 1)                                                   Sub decades (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subDecade()                                                                        Sub one decade to the instance (using date interval).
 * @method        CarbonInterface  addDecadesWithOverflow(int|float $value = 1)                                       Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addDecadeWithOverflow()                                                            Add one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subDecadesWithOverflow(int|float $value = 1)                                       Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subDecadeWithOverflow()                                                            Sub one decade to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addDecadesWithoutOverflow(int|float $value = 1)                                    Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadeWithoutOverflow()                                                         Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadesWithoutOverflow(int|float $value = 1)                                    Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadeWithoutOverflow()                                                         Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadesWithNoOverflow(int|float $value = 1)                                     Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadeWithNoOverflow()                                                          Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadesWithNoOverflow(int|float $value = 1)                                     Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadeWithNoOverflow()                                                          Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadesNoOverflow(int|float $value = 1)                                         Add decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addDecadeNoOverflow()                                                              Add one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadesNoOverflow(int|float $value = 1)                                         Sub decades (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subDecadeNoOverflow()                                                              Sub one decade to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarters(int|float $value = 1)                                                  Add quarters (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addQuarter()                                                                       Add one quarter to the instance (using date interval).
 * @method        CarbonInterface  subQuarters(int|float $value = 1)                                                  Sub quarters (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subQuarter()                                                                       Sub one quarter to the instance (using date interval).
 * @method        CarbonInterface  addQuartersWithOverflow(int|float $value = 1)                                      Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addQuarterWithOverflow()                                                           Add one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subQuartersWithOverflow(int|float $value = 1)                                      Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  subQuarterWithOverflow()                                                           Sub one quarter to the instance (using date interval) with overflow explicitly allowed.
 * @method        CarbonInterface  addQuartersWithoutOverflow(int|float $value = 1)                                   Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarterWithoutOverflow()                                                        Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuartersWithoutOverflow(int|float $value = 1)                                   Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuarterWithoutOverflow()                                                        Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuartersWithNoOverflow(int|float $value = 1)                                    Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarterWithNoOverflow()                                                         Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuartersWithNoOverflow(int|float $value = 1)                                    Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuarterWithNoOverflow()                                                         Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuartersNoOverflow(int|float $value = 1)                                        Add quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addQuarterNoOverflow()                                                             Add one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuartersNoOverflow(int|float $value = 1)                                        Sub quarters (the $value count passed in) to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  subQuarterNoOverflow()                                                             Sub one quarter to the instance (using date interval) with overflow explicitly forbidden.
 * @method        CarbonInterface  addWeeks(int|float $value = 1)                                                     Add weeks (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addWeek()                                                                          Add one week to the instance (using date interval).
 * @method        CarbonInterface  subWeeks(int|float $value = 1)                                                     Sub weeks (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subWeek()                                                                          Sub one week to the instance (using date interval).
 * @method        CarbonInterface  addWeekdays(int|float $value = 1)                                                  Add weekdays (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  addWeekday()                                                                       Add one weekday to the instance (using date interval).
 * @method        CarbonInterface  subWeekdays(int|float $value = 1)                                                  Sub weekdays (the $value count passed in) to the instance (using date interval).
 * @method        CarbonInterface  subWeekday()                                                                       Sub one weekday to the instance (using date interval).
 * @method        CarbonInterface  addUTCMicros(int|float $value = 1)                                                 Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMicro()                                                                      Add one microsecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicros(int|float $value = 1)                                                 Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicro()                                                                      Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicros(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        CarbonInterface  addUTCMicroseconds(int|float $value = 1)                                           Add microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMicrosecond()                                                                Add one microsecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicroseconds(int|float $value = 1)                                           Sub microseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMicrosecond()                                                                Sub one microsecond to the instance (using timestamp).
 * @method        CarbonPeriod     microsecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each microsecond or every X microseconds if a factor is given.
 * @method        float            diffInUTCMicroseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of microseconds.
 * @method        CarbonInterface  addUTCMillis(int|float $value = 1)                                                 Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMilli()                                                                      Add one millisecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillis(int|float $value = 1)                                                 Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMilli()                                                                      Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMillis(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        CarbonInterface  addUTCMilliseconds(int|float $value = 1)                                           Add milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMillisecond()                                                                Add one millisecond to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMilliseconds(int|float $value = 1)                                           Sub milliseconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillisecond()                                                                Sub one millisecond to the instance (using timestamp).
 * @method        CarbonPeriod     millisecondsUntil($endDate = null, int|float $factor = 1)                          Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millisecond or every X milliseconds if a factor is given.
 * @method        float            diffInUTCMilliseconds(DateTimeInterface|string|null $date, bool $absolute = false) Convert current and given date in UTC timezone and return a floating number of milliseconds.
 * @method        CarbonInterface  addUTCSeconds(int|float $value = 1)                                                Add seconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCSecond()                                                                     Add one second to the instance (using timestamp).
 * @method        CarbonInterface  subUTCSeconds(int|float $value = 1)                                                Sub seconds (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCSecond()                                                                     Sub one second to the instance (using timestamp).
 * @method        CarbonPeriod     secondsUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each second or every X seconds if a factor is given.
 * @method        float            diffInUTCSeconds(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of seconds.
 * @method        CarbonInterface  addUTCMinutes(int|float $value = 1)                                                Add minutes (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMinute()                                                                     Add one minute to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMinutes(int|float $value = 1)                                                Sub minutes (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMinute()                                                                     Sub one minute to the instance (using timestamp).
 * @method        CarbonPeriod     minutesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each minute or every X minutes if a factor is given.
 * @method        float            diffInUTCMinutes(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of minutes.
 * @method        CarbonInterface  addUTCHours(int|float $value = 1)                                                  Add hours (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCHour()                                                                       Add one hour to the instance (using timestamp).
 * @method        CarbonInterface  subUTCHours(int|float $value = 1)                                                  Sub hours (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCHour()                                                                       Sub one hour to the instance (using timestamp).
 * @method        CarbonPeriod     hoursUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each hour or every X hours if a factor is given.
 * @method        float            diffInUTCHours(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of hours.
 * @method        CarbonInterface  addUTCDays(int|float $value = 1)                                                   Add days (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCDay()                                                                        Add one day to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDays(int|float $value = 1)                                                   Sub days (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDay()                                                                        Sub one day to the instance (using timestamp).
 * @method        CarbonPeriod     daysUntil($endDate = null, int|float $factor = 1)                                  Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each day or every X days if a factor is given.
 * @method        float            diffInUTCDays(DateTimeInterface|string|null $date, bool $absolute = false)         Convert current and given date in UTC timezone and return a floating number of days.
 * @method        CarbonInterface  addUTCWeeks(int|float $value = 1)                                                  Add weeks (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCWeek()                                                                       Add one week to the instance (using timestamp).
 * @method        CarbonInterface  subUTCWeeks(int|float $value = 1)                                                  Sub weeks (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCWeek()                                                                       Sub one week to the instance (using timestamp).
 * @method        CarbonPeriod     weeksUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each week or every X weeks if a factor is given.
 * @method        float            diffInUTCWeeks(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of weeks.
 * @method        CarbonInterface  addUTCMonths(int|float $value = 1)                                                 Add months (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMonth()                                                                      Add one month to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMonths(int|float $value = 1)                                                 Sub months (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMonth()                                                                      Sub one month to the instance (using timestamp).
 * @method        CarbonPeriod     monthsUntil($endDate = null, int|float $factor = 1)                                Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each month or every X months if a factor is given.
 * @method        float            diffInUTCMonths(DateTimeInterface|string|null $date, bool $absolute = false)       Convert current and given date in UTC timezone and return a floating number of months.
 * @method        CarbonInterface  addUTCQuarters(int|float $value = 1)                                               Add quarters (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCQuarter()                                                                    Add one quarter to the instance (using timestamp).
 * @method        CarbonInterface  subUTCQuarters(int|float $value = 1)                                               Sub quarters (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCQuarter()                                                                    Sub one quarter to the instance (using timestamp).
 * @method        CarbonPeriod     quartersUntil($endDate = null, int|float $factor = 1)                              Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each quarter or every X quarters if a factor is given.
 * @method        float            diffInUTCQuarters(DateTimeInterface|string|null $date, bool $absolute = false)     Convert current and given date in UTC timezone and return a floating number of quarters.
 * @method        CarbonInterface  addUTCYears(int|float $value = 1)                                                  Add years (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCYear()                                                                       Add one year to the instance (using timestamp).
 * @method        CarbonInterface  subUTCYears(int|float $value = 1)                                                  Sub years (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCYear()                                                                       Sub one year to the instance (using timestamp).
 * @method        CarbonPeriod     yearsUntil($endDate = null, int|float $factor = 1)                                 Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each year or every X years if a factor is given.
 * @method        float            diffInUTCYears(DateTimeInterface|string|null $date, bool $absolute = false)        Convert current and given date in UTC timezone and return a floating number of years.
 * @method        CarbonInterface  addUTCDecades(int|float $value = 1)                                                Add decades (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCDecade()                                                                     Add one decade to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDecades(int|float $value = 1)                                                Sub decades (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCDecade()                                                                     Sub one decade to the instance (using timestamp).
 * @method        CarbonPeriod     decadesUntil($endDate = null, int|float $factor = 1)                               Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each decade or every X decades if a factor is given.
 * @method        float            diffInUTCDecades(DateTimeInterface|string|null $date, bool $absolute = false)      Convert current and given date in UTC timezone and return a floating number of decades.
 * @method        CarbonInterface  addUTCCenturies(int|float $value = 1)                                              Add centuries (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCCentury()                                                                    Add one century to the instance (using timestamp).
 * @method        CarbonInterface  subUTCCenturies(int|float $value = 1)                                              Sub centuries (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCCentury()                                                                    Sub one century to the instance (using timestamp).
 * @method        CarbonPeriod     centuriesUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each century or every X centuries if a factor is given.
 * @method        float            diffInUTCCenturies(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of centuries.
 * @method        CarbonInterface  addUTCMillennia(int|float $value = 1)                                              Add millennia (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  addUTCMillennium()                                                                 Add one millennium to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillennia(int|float $value = 1)                                              Sub millennia (the $value count passed in) to the instance (using timestamp).
 * @method        CarbonInterface  subUTCMillennium()                                                                 Sub one millennium to the instance (using timestamp).
 * @method        CarbonPeriod     millenniaUntil($endDate = null, int|float $factor = 1)                             Return an iterable period from current date to given end (string, DateTime or Carbon instance) for each millennium or every X millennia if a factor is given.
 * @method        float            diffInUTCMillennia(DateTimeInterface|string|null $date, bool $absolute = false)    Convert current and given date in UTC timezone and return a floating number of millennia.
 * @method        CarbonInterface  roundYear(float $precision = 1, string $function = "round")                        Round the current instance year with given precision using the given function.
 * @method        CarbonInterface  roundYears(float $precision = 1, string $function = "round")                       Round the current instance year with given precision using the given function.
 * @method        CarbonInterface  floorYear(float $precision = 1)                                                    Truncate the current instance year with given precision.
 * @method        CarbonInterface  floorYears(float $precision = 1)                                                   Truncate the current instance year with given precision.
 * @method        CarbonInterface  ceilYear(float $precision = 1)                                                     Ceil the current instance year with given precision.
 * @method        CarbonInterface  ceilYears(float $precision = 1)                                                    Ceil the current instance year with given precision.
 * @method        CarbonInterface  roundMonth(float $precision = 1, string $function = "round")                       Round the current instance month with given precision using the given function.
 * @method        CarbonInterface  roundMonths(float $precision = 1, string $function = "round")                      Round the current instance month with given precision using the given function.
 * @method        CarbonInterface  floorMonth(float $precision = 1)                                                   Truncate the current instance month with given precision.
 * @method        CarbonInterface  floorMonths(float $precision = 1)                                                  Truncate the current instance month with given precision.
 * @method        CarbonInterface  ceilMonth(float $precision = 1)                                                    Ceil the current instance month with given precision.
 * @method        CarbonInterface  ceilMonths(float $precision = 1)                                                   Ceil the current instance month with given precision.
 * @method        CarbonInterface  roundDay(float $precision = 1, string $function = "round")                         Round the current instance day with given precision using the given function.
 * @method        CarbonInterface  roundDays(float $precision = 1, string $function = "round")                        Round the current instance day with given precision using the given function.
 * @method        CarbonInterface  floorDay(float $precision = 1)                                                     Truncate the current instance day with given precision.
 * @method        CarbonInterface  floorDays(float $precision = 1)                                                    Truncate the current instance day with given precision.
 * @method        CarbonInterface  ceilDay(float $precision = 1)                                                      Ceil the current instance day with given precision.
 * @method        CarbonInterface  ceilDays(float $precision = 1)                                                     Ceil the current instance day with given precision.
 * @method        CarbonInterface  roundHour(float $precision = 1, string $function = "round")                        Round the current instance hour with given precision using the given function.
 * @method        CarbonInterface  roundHours(float $precision = 1, string $function = "round")                       Round the current instance hour with given precision using the given function.
 * @method        CarbonInterface  floorHour(float $precision = 1)                                                    Truncate the current instance hour with given precision.
 * @method        CarbonInterface  floorHours(float $precision = 1)                                                   Truncate the current instance hour with given precision.
 * @method        CarbonInterface  ceilHour(float $precision = 1)                                                     Ceil the current instance hour with given precision.
 * @method        CarbonInterface  ceilHours(float $precision = 1)                                                    Ceil the current instance hour with given precision.
 * @method        CarbonInterface  roundMinute(float $precision = 1, string $function = "round")                      Round the current instance minute with given precision using the given function.
 * @method        CarbonInterface  roundMinutes(float $precision = 1, string $function = "round")                     Round the current instance minute with given precision using the given function.
 * @method        CarbonInterface  floorMinute(float $precision = 1)                                                  Truncate the current instance minute with given precision.
 * @method        CarbonInterface  floorMinutes(float $precision = 1)                                                 Truncate the current instance minute with given precision.
 * @method        CarbonInterface  ceilMinute(float $precision = 1)                                                   Ceil the current instance minute with given precision.
 * @method        CarbonInterface  ceilMinutes(float $precision = 1)                                                  Ceil the current instance minute with given precision.
 * @method        CarbonInterface  roundSecond(float $precision = 1, string $function = "round")                      Round the current instance second with given precision using the given function.
 * @method        CarbonInterface  roundSeconds(float $precision = 1, string $function = "round")                     Round the current instance second with given precision using the given function.
 * @method        CarbonInterface  floorSecond(float $precision = 1)                                                  Truncate the current instance second with given precision.
 * @method        CarbonInterface  floorSeconds(float $precision = 1)                                                 Truncate the current instance second with given precision.
 * @method        CarbonInterface  ceilSecond(float $precision = 1)                                                   Ceil the current instance second with given precision.
 * @method        CarbonInterface  ceilSeconds(float $precision = 1)                                                  Ceil the current instance second with given precision.
 * @method        CarbonInterface  roundMillennium(float $precision = 1, string $function = "round")                  Round the current instance millennium with given precision using the given function.
 * @method        CarbonInterface  roundMillennia(float $precision = 1, string $function = "round")                   Round the current instance millennium with given precision using the given function.
 * @method        CarbonInterface  floorMillennium(float $precision = 1)                                              Truncate the current instance millennium with given precision.
 * @method        CarbonInterface  floorMillennia(float $precision = 1)                                               Truncate the current instance millennium with given precision.
 * @method        CarbonInterface  ceilMillennium(float $precision = 1)                                               Ceil the current instance millennium with given precision.
 * @method        CarbonInterface  ceilMillennia(float $precision = 1)                                                Ceil the current instance millennium with given precision.
 * @method        CarbonInterface  roundCentury(float $precision = 1, string $function = "round")                     Round the current instance century with given precision using the given function.
 * @method        CarbonInterface  roundCenturies(float $precision = 1, string $function = "round")                   Round the current instance century with given precision using the given function.
 * @method        CarbonInterface  floorCentury(float $precision = 1)                                                 Truncate the current instance century with given precision.
 * @method        CarbonInterface  floorCenturies(float $precision = 1)                                               Truncate the current instance century with given precision.
 * @method        CarbonInterface  ceilCentury(float $precision = 1)                                                  Ceil the current instance century with given precision.
 * @method        CarbonInterface  ceilCenturies(float $precision = 1)                                                Ceil the current instance century with given precision.
 * @method        CarbonInterface  roundDecade(float $precision = 1, string $function = "round")                      Round the current instance decade with given precision using the given function.
 * @method        CarbonInterface  roundDecades(float $precision = 1, string $function = "round")                     Round the current instance decade with given precision using the given function.
 * @method        CarbonInterface  floorDecade(float $precision = 1)                                                  Truncate the current instance decade with given precision.
 * @method        CarbonInterface  floorDecades(float $precision = 1)                                                 Truncate the current instance decade with given precision.
 * @method        CarbonInterface  ceilDecade(float $precision = 1)                                                   Ceil the current instance decade with given precision.
 * @method        CarbonInterface  ceilDecades(float $precision = 1)                                                  Ceil the current instance decade with given precision.
 * @method        CarbonInterface  roundQuarter(float $precision = 1, string $function = "round")                     Round the current instance quarter with given precision using the given function.
 * @method        CarbonInterface  roundQuarters(float $precision = 1, string $function = "round")                    Round the current instance quarter with given precision using the given function.
 * @method        CarbonInterface  floorQuarter(float $precision = 1)                                                 Truncate the current instance quarter with given precision.
 * @method        CarbonInterface  floorQuarters(float $precision = 1)                                                Truncate the current instance quarter with given precision.
 * @method        CarbonInterface  ceilQuarter(float $precision = 1)                                                  Ceil the current instance quarter with given precision.
 * @method        CarbonInterface  ceilQuarters(float $precision = 1)                                                 Ceil the current instance quarter with given precision.
 * @method        CarbonInterface  roundMillisecond(float $precision = 1, string $function = "round")                 Round the current instance millisecond with given precision using the given function.
 * @method        CarbonInterface  roundMilliseconds(float $precision = 1, string $function = "round")                Round the current instance millisecond with given precision using the given function.
 * @method        CarbonInterface  floorMillisecond(float $precision = 1)                                             Truncate the current instance millisecond with given precision.
 * @method        CarbonInterface  floorMilliseconds(float $precision = 1)                                            Truncate the current instance millisecond with given precision.
 * @method        CarbonInterface  ceilMillisecond(float $precision = 1)                                              Ceil the current instance millisecond with given precision.
 * @method        CarbonInterface  ceilMilliseconds(float $precision = 1)                                             Ceil the current instance millisecond with given precision.
 * @method        CarbonInterface  roundMicrosecond(float $precision = 1, string $function = "round")                 Round the current instance microsecond with given precision using the given function.
 * @method        CarbonInterface  roundMicroseconds(float $precision = 1, string $function = "round")                Round the current instance microsecond with given precision using the given function.
 * @method        CarbonInterface  floorMicrosecond(float $precision = 1)                                             Truncate the current instance microsecond with given precision.
 * @method        CarbonInterface  floorMicroseconds(float $precision = 1)                                            Truncate the current instance microsecond with given precision.
 * @method        CarbonInterface  ceilMicrosecond(float $precision = 1)                                              Ceil the current instance microsecond with given precision.
 * @method        CarbonInterface  ceilMicroseconds(float $precision = 1)                                             Ceil the current instance microsecond with given precision.
 * @method        string           shortAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longAbsoluteDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Absolute' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)        Get the difference (short format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeDiffForHumans(DateTimeInterface $other = null, int $parts = 1)         Get the difference (long format, 'Relative' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)   Get the difference (short format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToNowDiffForHumans(DateTimeInterface $other = null, int $parts = 1)    Get the difference (long format, 'RelativeToNow' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           shortRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1) Get the difference (short format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        string           longRelativeToOtherDiffForHumans(DateTimeInterface $other = null, int $parts = 1)  Get the difference (long format, 'RelativeToOther' mode) in a human readable format in the current locale. ($other and $parts parameters can be swapped.)
 * @method        int              centuriesInMillennium()                                                            Return the number of centuries contained in the current millennium
 * @method        int|static       centuryOfMillennium(?int $century = null)                                          Return the value of the century starting from the beginning of the current millennium when called with no parameters, change the current century when called with an integer value
 * @method        int|static       dayOfCentury(?int $day = null)                                                     Return the value of the day starting from the beginning of the current century when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfDecade(?int $day = null)                                                      Return the value of the day starting from the beginning of the current decade when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMillennium(?int $day = null)                                                  Return the value of the day starting from the beginning of the current millennium when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfMonth(?int $day = null)                                                       Return the value of the day starting from the beginning of the current month when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfQuarter(?int $day = null)                                                     Return the value of the day starting from the beginning of the current quarter when called with no parameters, change the current day when called with an integer value
 * @method        int|static       dayOfWeek(?int $day = null)                                                        Return the value of the day starting from the beginning of the current week when called with no parameters, change the current day when called with an integer value
 * @method        int              daysInCentury()                                                                    Return the number of days contained in the current century
 * @method        int              daysInDecade()                                                                     Return the number of days contained in the current decade
 * @method        int              daysInMillennium()                                                                 Return the number of days contained in the current millennium
 * @method        int              daysInMonth()                                                                      Return the number of days contained in the current month
 * @method        int              daysInQuarter()                                                                    Return the number of days contained in the current quarter
 * @method        int              daysInWeek()                                                                       Return the number of days contained in the current week
 * @method        int              daysInYear()                                                                       Return the number of days contained in the current year
 * @method        int|static       decadeOfCentury(?int $decade = null)                                               Return the value of the decade starting from the beginning of the current century when called with no parameters, change the current decade when called with an integer value
 * @method        int|static       decadeOfMillennium(?int $decade = null)                                            Return the value of the decade starting from the beginning of the current millennium when called with no parameters, change the current decade when called with an integer value
 * @method        int              decadesInCentury()                                                                 Return the number of decades contained in the current century
 * @method        int              decadesInMillennium()                                                              Return the number of decades contained in the current millennium
 * @method        int|static       hourOfCentury(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current century when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDay(?int $hour = null)                                                       Return the value of the hour starting from the beginning of the current day when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfDecade(?int $hour = null)                                                    Return the value of the hour starting from the beginning of the current decade when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMillennium(?int $hour = null)                                                Return the value of the hour starting from the beginning of the current millennium when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfMonth(?int $hour = null)                                                     Return the value of the hour starting from the beginning of the current month when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfQuarter(?int $hour = null)                                                   Return the value of the hour starting from the beginning of the current quarter when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfWeek(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current week when called with no parameters, change the current hour when called with an integer value
 * @method        int|static       hourOfYear(?int $hour = null)                                                      Return the value of the hour starting from the beginning of the current year when called with no parameters, change the current hour when called with an integer value
 * @method        int              hoursInCentury()                                                                   Return the number of hours contained in the current century
 * @method        int              hoursInDay()                                                                       Return the number of hours contained in the current day
 * @method        int              hoursInDecade()                                                                    Return the number of hours contained in the current decade
 * @method        int              hoursInMillennium()                                                                Return the number of hours contained in the current millennium
 * @method        int              hoursInMonth()                                                                     Return the number of hours contained in the current month
 * @method        int              hoursInQuarter()                                                                   Return the number of hours contained in the current quarter
 * @method        int              hoursInWeek()                                                                      Return the number of hours contained in the current week
 * @method        int              hoursInYear()                                                                      Return the number of hours contained in the current year
 * @method        int|static       microsecondOfCentury(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current century when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDay(?int $microsecond = null)                                         Return the value of the microsecond starting from the beginning of the current day when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfDecade(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current decade when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfHour(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current hour when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillennium(?int $microsecond = null)                                  Return the value of the microsecond starting from the beginning of the current millennium when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMillisecond(?int $microsecond = null)                                 Return the value of the microsecond starting from the beginning of the current millisecond when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMinute(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current minute when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfMonth(?int $microsecond = null)                                       Return the value of the microsecond starting from the beginning of the current month when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfQuarter(?int $microsecond = null)                                     Return the value of the microsecond starting from the beginning of the current quarter when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfSecond(?int $microsecond = null)                                      Return the value of the microsecond starting from the beginning of the current second when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfWeek(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current week when called with no parameters, change the current microsecond when called with an integer value
 * @method        int|static       microsecondOfYear(?int $microsecond = null)                                        Return the value of the microsecond starting from the beginning of the current year when called with no parameters, change the current microsecond when called with an integer value
 * @method        int              microsecondsInCentury()                                                            Return the number of microseconds contained in the current century
 * @method        int              microsecondsInDay()                                                                Return the number of microseconds contained in the current day
 * @method        int              microsecondsInDecade()                                                             Return the number of microseconds contained in the current decade
 * @method        int              microsecondsInHour()                                                               Return the number of microseconds contained in the current hour
 * @method        int              microsecondsInMillennium()                                                         Return the number of microseconds contained in the current millennium
 * @method        int              microsecondsInMillisecond()                                                        Return the number of microseconds contained in the current millisecond
 * @method        int              microsecondsInMinute()                                                             Return the number of microseconds contained in the current minute
 * @method        int              microsecondsInMonth()                                                              Return the number of microseconds contained in the current month
 * @method        int              microsecondsInQuarter()                                                            Return the number of microseconds contained in the current quarter
 * @method        int              microsecondsInSecond()                                                             Return the number of microseconds contained in the current second
 * @method        int              microsecondsInWeek()                                                               Return the number of microseconds contained in the current week
 * @method        int              microsecondsInYear()                                                               Return the number of microseconds contained in the current year
 * @method        int|static       millisecondOfCentury(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current century when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDay(?int $millisecond = null)                                         Return the value of the millisecond starting from the beginning of the current day when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfDecade(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current decade when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfHour(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current hour when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMillennium(?int $millisecond = null)                                  Return the value of the millisecond starting from the beginning of the current millennium when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMinute(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current minute when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfMonth(?int $millisecond = null)                                       Return the value of the millisecond starting from the beginning of the current month when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfQuarter(?int $millisecond = null)                                     Return the value of the millisecond starting from the beginning of the current quarter when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfSecond(?int $millisecond = null)                                      Return the value of the millisecond starting from the beginning of the current second when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfWeek(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current week when called with no parameters, change the current millisecond when called with an integer value
 * @method        int|static       millisecondOfYear(?int $millisecond = null)                                        Return the value of the millisecond starting from the beginning of the current year when called with no parameters, change the current millisecond when called with an integer value
 * @method        int              millisecondsInCentury()                                                            Return the number of milliseconds contained in the current century
 * @method        int              millisecondsInDay()                                                                Return the number of milliseconds contained in the current day
 * @method        int              millisecondsInDecade()                                                             Return the number of milliseconds contained in the current decade
 * @method        int              millisecondsInHour()                                                               Return the number of milliseconds contained in the current hour
 * @method        int              millisecondsInMillennium()                                                         Return the number of milliseconds contained in the current millennium
 * @method        int              millisecondsInMinute()                                                             Return the number of milliseconds contained in the current minute
 * @method        int              millisecondsInMonth()                                                              Return the number of milliseconds contained in the current month
 * @method        int              millisecondsInQuarter()                                                            Return the number of milliseconds contained in the current quarter
 * @method        int              millisecondsInSecond()                                                             Return the number of milliseconds contained in the current second
 * @method        int              millisecondsInWeek()                                                               Return the number of milliseconds contained in the current week
 * @method        int              millisecondsInYear()                                                               Return the number of milliseconds contained in the current year
 * @method        int|static       minuteOfCentury(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current century when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDay(?int $minute = null)                                                   Return the value of the minute starting from the beginning of the current day when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfDecade(?int $minute = null)                                                Return the value of the minute starting from the beginning of the current decade when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfHour(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current hour when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMillennium(?int $minute = null)                                            Return the value of the minute starting from the beginning of the current millennium when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfMonth(?int $minute = null)                                                 Return the value of the minute starting from the beginning of the current month when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfQuarter(?int $minute = null)                                               Return the value of the minute starting from the beginning of the current quarter when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfWeek(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current week when called with no parameters, change the current minute when called with an integer value
 * @method        int|static       minuteOfYear(?int $minute = null)                                                  Return the value of the minute starting from the beginning of the current year when called with no parameters, change the current minute when called with an integer value
 * @method        int              minutesInCentury()                                                                 Return the number of minutes contained in the current century
 * @method        int              minutesInDay()                                                                     Return the number of minutes contained in the current day
 * @method        int              minutesInDecade()                                                                  Return the number of minutes contained in the current decade
 * @method        int              minutesInHour()                                                                    Return the number of minutes contained in the current hour
 * @method        int              minutesInMillennium()                                                              Return the number of minutes contained in the current millennium
 * @method        int              minutesInMonth()                                                                   Return the number of minutes contained in the current month
 * @method        int              minutesInQuarter()                                                                 Return the number of minutes contained in the current quarter
 * @method        int              minutesInWeek()                                                                    Return the number of minutes contained in the current week
 * @method        int              minutesInYear()                                                                    Return the number of minutes contained in the current year
 * @method        int|static       monthOfCentury(?int $month = null)                                                 Return the value of the month starting from the beginning of the current century when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfDecade(?int $month = null)                                                  Return the value of the month starting from the beginning of the current decade when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfMillennium(?int $month = null)                                              Return the value of the month starting from the beginning of the current millennium when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfQuarter(?int $month = null)                                                 Return the value of the month starting from the beginning of the current quarter when called with no parameters, change the current month when called with an integer value
 * @method        int|static       monthOfYear(?int $month = null)                                                    Return the value of the month starting from the beginning of the current year when called with no parameters, change the current month when called with an integer value
 * @method        int              monthsInCentury()                                                                  Return the number of months contained in the current century
 * @method        int              monthsInDecade()                                                                   Return the number of months contained in the current decade
 * @method        int              monthsInMillennium()                                                               Return the number of months contained in the current millennium
 * @method        int              monthsInQuarter()                                                                  Return the number of months contained in the current quarter
 * @method        int              monthsInYear()                                                                     Return the number of months contained in the current year
 * @method        int|static       quarterOfCentury(?int $quarter = null)                                             Return the value of the quarter starting from the beginning of the current century when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfDecade(?int $quarter = null)                                              Return the value of the quarter starting from the beginning of the current decade when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfMillennium(?int $quarter = null)                                          Return the value of the quarter starting from the beginning of the current millennium when called with no parameters, change the current quarter when called with an integer value
 * @method        int|static       quarterOfYear(?int $quarter = null)                                                Return the value of the quarter starting from the beginning of the current year when called with no parameters, change the current quarter when called with an integer value
 * @method        int              quartersInCentury()                                                                Return the number of quarters contained in the current century
 * @method        int              quartersInDecade()                                                                 Return the number of quarters contained in the current decade
 * @method        int              quartersInMillennium()                                                             Return the number of quarters contained in the current millennium
 * @method        int              quartersInYear()                                                                   Return the number of quarters contained in the current year
 * @method        int|static       secondOfCentury(?int $second = null)                                               Return the value of the second starting from the beginning of the current century when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDay(?int $second = null)                                                   Return the value of the second starting from the beginning of the current day when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfDecade(?int $second = null)                                                Return the value of the second starting from the beginning of the current decade when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfHour(?int $second = null)                                                  Return the value of the second starting from the beginning of the current hour when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMillennium(?int $second = null)                                            Return the value of the second starting from the beginning of the current millennium when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMinute(?int $second = null)                                                Return the value of the second starting from the beginning of the current minute when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfMonth(?int $second = null)                                                 Return the value of the second starting from the beginning of the current month when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfQuarter(?int $second = null)                                               Return the value of the second starting from the beginning of the current quarter when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfWeek(?int $second = null)                                                  Return the value of the second starting from the beginning of the current week when called with no parameters, change the current second when called with an integer value
 * @method        int|static       secondOfYear(?int $second = null)                                                  Return the value of the second starting from the beginning of the current year when called with no parameters, change the current second when called with an integer value
 * @method        int              secondsInCentury()                                                                 Return the number of seconds contained in the current century
 * @method        int              secondsInDay()                                                                     Return the number of seconds contained in the current day
 * @method        int              secondsInDecade()                                                                  Return the number of seconds contained in the current decade
 * @method        int              secondsInHour()                                                                    Return the number of seconds contained in the current hour
 * @method        int              secondsInMillennium()                                                              Return the number of seconds contained in the current millennium
 * @method        int              secondsInMinute()                                                                  Return the number of seconds contained in the current minute
 * @method        int              secondsInMonth()                                                                   Return the number of seconds contained in the current month
 * @method        int              secondsInQuarter()                                                                 Return the number of seconds contained in the current quarter
 * @method        int              secondsInWeek()                                                                    Return the number of seconds contained in the current week
 * @method        int              secondsInYear()                                                                    Return the number of seconds contained in the current year
 * @method        int|static       weekOfCentury(?int $week = null)                                                   Return the value of the week starting from the beginning of the current century when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfDecade(?int $week = null)                                                    Return the value of the week starting from the beginning of the current decade when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMillennium(?int $week = null)                                                Return the value of the week starting from the beginning of the current millennium when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfMonth(?int $week = null)                                                     Return the value of the week starting from the beginning of the current month when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfQuarter(?int $week = null)                                                   Return the value of the week starting from the beginning of the current quarter when called with no parameters, change the current week when called with an integer value
 * @method        int|static       weekOfYear(?int $week = null)                                                      Return the value of the week starting from the beginning of the current year when called with no parameters, change the current week when called with an integer value
 * @method        int              weeksInCentury()                                                                   Return the number of weeks contained in the current century
 * @method        int              weeksInDecade()                                                                    Return the number of weeks contained in the current decade
 * @method        int              weeksInMillennium()                                                                Return the number of weeks contained in the current millennium
 * @method        int              weeksInMonth()                                                                     Return the number of weeks contained in the current month
 * @method        int              weeksInQuarter()                                                                   Return the number of weeks contained in the current quarter
 * @method        int|static       yearOfCentury(?int $year = null)                                                   Return the value of the year starting from the beginning of the current century when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfDecade(?int $year = null)                                                    Return the value of the year starting from the beginning of the current decade when called with no parameters, change the current year when called with an integer value
 * @method        int|static       yearOfMillennium(?int $year = null)                                                Return the value of the year starting from the beginning of the current millennium when called with no parameters, change the current year when called with an integer value
 * @method        int              yearsInCentury()                                                                   Return the number of years contained in the current century
 * @method        int              yearsInDecade()                                                                    Return the number of years contained in the current decade
 * @method        int              yearsInMillennium()                                                                Return the number of years contained in the current millennium
 *
 * </autodoc>
 *
 * @codeCoverageIgnore
 */
interface CarbonInterface extends DateTimeInterface, JsonSerializable, DiffOptions, Format, TranslationOptions, UnitValue
{
    // <methods>

    /**
     * Dynamically handle calls to the class.
     *
     * @param string $method     magic method name called
     * @param array  $parameters parameters list
     *
     * @throws UnknownMethodException|BadMethodCallException|ReflectionException|Throwable
     */
    public function __call(string $method, array $parameters): mixed;

    /**
     * Dynamically handle calls to the class.
     *
     * @param string $method     magic method name called
     * @param array  $parameters parameters list
     *
     * @throws BadMethodCallException
     */
    public static function __callStatic(string $method, array $parameters): mixed;

    /**
     * Update constructedObjectId on cloned.
     */
    public function __clone(): void;

    /**
     * Create a new Carbon instance.
     *
     * Please see the testing aids section (specifically static::setTestNow())
     * for more on the possibility of this constructor returning a test instance.
     *
     * @throws InvalidFormatException
     */
    public function __construct(DateTimeInterface|WeekDay|Month|string|int|float|null $time = null, DateTimeZone|string|int|null $timezone = null);

    /**
     * Show truthy properties on var_dump().
     */
    public function __debugInfo(): array;

    /**
     * Get a part of the Carbon object.
     *
     * @throws UnknownGetterException
     *
     * @return string|int|bool|DateTimeZone|null
     */
    public function __get(string $name): mixed;

    /**
     * Check if an attribute exists on the object
     *
     * @param string $name
     *
     * @return bool
     */
    public function __isset($name);

    /**
     * Set a part of the Carbon object
     *
     * @param string                  $name
     * @param string|int|DateTimeZone $value
     *
     * @throws UnknownSetterException|ReflectionException
     *
     * @return void
     */
    public function __set($name, $value);

    /**
     * The __set_state handler.
     *
     * @param string|array $dump
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public static function __set_state($dump): static;

    /**
     * Format the instance as a string using the set format
     *
     * @example
     * ```
     * echo Carbon::now(); // Carbon instances can be cast to string
     * ```
     */
    public function __toString();

    /**
     * Add given units or interval to the current instance.
     *
     * @example $date->add('hour', 3)
     * @example $date->add(15, 'days')
     * @example $date->add(CarbonInterval::days(4))
     *
     * @param Unit|int|string|DateInterval|Closure|CarbonConverterInterface $unit
     * @param Unit|int|float|string                                         $value
     * @param bool|null                                                     $overflow
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public function add($unit, $value = 1, ?bool $overflow = null): static;

    /**
     * @deprecated Prefer to use add addUTCUnit() which more accurately defines what it's doing.
     *
     * Add seconds to the instance using timestamp. Positive $value travels
     * forward while negative $value travels into the past.
     *
     * @param string         $unit
     * @param int|float|null $value
     *
     * @return static
     */
    public function addRealUnit(string $unit, $value = 1): static;

    /**
     * Add seconds to the instance using timestamp. Positive $value travels
     * forward while negative $value travels into the past.
     *
     * @param string         $unit
     * @param int|float|null $value
     *
     * @return static
     */
    public function addUTCUnit(string $unit, $value = 1): static;

    /**
     * Add given units to the current instance.
     */
    public function addUnit(Unit|string $unit, $value = 1, ?bool $overflow = null): static;

    /**
     * Add any unit to a new value without overflowing current other unit given.
     *
     * @param string $valueUnit    unit name to modify
     * @param int    $value        amount to add to the input unit
     * @param string $overflowUnit unit name to not overflow
     */
    public function addUnitNoOverflow(string $valueUnit, int $value, string $overflowUnit): static;

    /**
     * Get the difference in a human readable format in the current locale from an other
     * instance given to now
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                           - 'syntax' entry (see below)
     *                           - 'short' entry (see below)
     *                           - 'parts' entry (see below)
     *                           - 'options' entry (see below)
     *                           - 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           if int passed, it add modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: 1: single part)
     * @param int       $options human diff options
     *
     * @return string
     */
    public function ago($syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * Modify the current instance to the average of a given instance (default now) and the current instance
     * (second-precision).
     *
     * @param \Carbon\Carbon|\DateTimeInterface|null $date
     *
     * @return static
     */
    public function average($date = null);

    /**
     * Clone the current instance if it's mutable.
     *
     * This method is convenient to ensure you don't mutate the initial object
     * but avoid to make a useless copy of it if it's already immutable.
     *
     * @return static
     */
    public function avoidMutation(): static;

    /**
     * Determines if the instance is between two others.
     *
     * The third argument allow you to specify if bounds are included or not (true by default)
     * but for when you including/excluding bounds may produce different results in your application,
     * we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->between('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->between('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->between('2018-07-25', '2018-08-01', false); // false
     * ```
     *
     * @param bool $equal Indicates if an equal to comparison should be done
     */
    public function between(DateTimeInterface|string $date1, DateTimeInterface|string $date2, bool $equal = true): bool;

    /**
     * Determines if the instance is between two others, bounds excluded.
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->betweenExcluded('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->betweenExcluded('2018-07-25', '2018-08-01'); // false
     * ```
     */
    public function betweenExcluded(DateTimeInterface|string $date1, DateTimeInterface|string $date2): bool;

    /**
     * Determines if the instance is between two others, bounds included.
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->betweenIncluded('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->betweenIncluded('2018-07-25', '2018-08-01'); // true
     * ```
     */
    public function betweenIncluded(DateTimeInterface|string $date1, DateTimeInterface|string $date2): bool;

    /**
     * Returns either day of week + time (e.g. "Last Friday at 3:30 PM") if reference time is within 7 days,
     * or a calendar date (e.g. "10/29/2017") otherwise.
     *
     * Language, date and time formats will change according to the current locale.
     *
     * @param Carbon|\DateTimeInterface|string|null $referenceTime
     * @param array                                 $formats
     *
     * @return string
     */
    public function calendar($referenceTime = null, array $formats = []);

    /**
     * Checks if the (date)time string is in a given format and valid to create a
     * new instance.
     *
     * @example
     * ```
     * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true
     * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false
     * ```
     */
    public static function canBeCreatedFromFormat(?string $date, string $format): bool;

    /**
     * Return the Carbon instance passed through, a now instance in the same timezone
     * if null given or parse the input if string given.
     *
     * @param Carbon|\Carbon\CarbonPeriod|\Carbon\CarbonInterval|\DateInterval|\DatePeriod|DateTimeInterface|string|null $date
     *
     * @return static
     */
    public function carbonize($date = null);

    /**
     * Cast the current instance into the given class.
     *
     * @template T
     *
     * @param class-string<T> $className The $className::instance() method will be called to cast the current object.
     *
     * @return T
     */
    public function cast(string $className): mixed;

    /**
     * Ceil the current instance second with given precision if specified.
     */
    public function ceil(DateInterval|string|int|float $precision = 1): static;

    /**
     * Ceil the current instance at the given unit with given precision if specified.
     */
    public function ceilUnit(string $unit, DateInterval|string|int|float $precision = 1): static;

    /**
     * Ceil the current instance week.
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     */
    public function ceilWeek(WeekDay|int|null $weekStartsAt = null): static;

    /**
     * Similar to native modify() method of DateTime but can handle more grammars.
     *
     * @example
     * ```
     * echo Carbon::now()->change('next 2pm');
     * ```
     *
     * @link https://php.net/manual/en/datetime.modify.php
     *
     * @param string $modifier
     *
     * @return static
     */
    public function change($modifier);

    /**
     * Cleanup properties attached to the public scope of DateTime when a dump of the date is requested.
     * foreach ($date as $_) {}
     * serializer($date)
     * var_export($date)
     * get_object_vars($date)
     */
    public function cleanupDumpProperties();

    /**
     * @alias copy
     *
     * Get a copy of the instance.
     *
     * @return static
     */
    public function clone();

    /**
     * Get the closest date from the instance (second-precision).
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
     *
     * @return static
     */
    public function closest($date1, $date2);

    /**
     * Get a copy of the instance.
     *
     * @return static
     */
    public function copy();

    /**
     * Create a new Carbon instance from a specific date and time.
     *
     * If any of $year, $month or $day are set to null their now() values will
     * be used.
     *
     * If $hour is null it will be set to its now() value and the default
     * values for $minute and $second will be their now() values.
     *
     * If $hour is not null then the default values for $minute and $second
     * will be 0.
     *
     * @param DateTimeInterface|string|int|null $year
     * @param int|null                          $month
     * @param int|null                          $day
     * @param int|null                          $hour
     * @param int|null                          $minute
     * @param int|null                          $second
     * @param DateTimeZone|string|int|null      $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null): ?static;

    /**
     * Create a Carbon instance from just a date. The time portion is set to now.
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createFromDate($year = null, $month = null, $day = null, $timezone = null);

    /**
     * Create a Carbon instance from a specific format.
     *
     * @param string                       $format   Datetime format
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    #[ReturnTypeWillChange]
    public static function createFromFormat($format, $time, $timezone = null): ?static;

    /**
     * Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()).
     *
     * @param string                       $format     Datetime format
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone   optional timezone
     * @param string|null                  $locale     locale to be used for LTS, LT, LL, LLL, etc. macro-formats (en by fault, unneeded if no such macro-format in use)
     * @param TranslatorInterface|null     $translator optional custom translator to use for macro-formats
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function createFromIsoFormat(string $format, string $time, $timezone = null, ?string $locale = 'en', ?TranslatorInterface $translator = null): ?static;

    /**
     * Create a Carbon instance from a specific format and a string in a given language.
     *
     * @param string                       $format   Datetime format
     * @param string                       $locale
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null): ?static;

    /**
     * Create a Carbon instance from a specific ISO format and a string in a given language.
     *
     * @param string                       $format   Datetime ISO format
     * @param string                       $locale
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null): ?static;

    /**
     * Create a Carbon instance from just a time. The date portion is set to today.
     *
     * @param int|null                     $hour
     * @param int|null                     $minute
     * @param int|null                     $second
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null): static;

    /**
     * Create a Carbon instance from a time string. The date portion is set to today.
     *
     * @throws InvalidFormatException
     */
    public static function createFromTimeString(string $time, DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Create a Carbon instance from a timestamp and set the timezone (UTC by default).
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    #[ReturnTypeWillChange]
    public static function createFromTimestamp(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Create a Carbon instance from a timestamp in milliseconds.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public static function createFromTimestampMs(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Create a Carbon instance from a timestamp in milliseconds.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     *
     * @param float|int|string $timestamp
     *
     * @return static
     */
    public static function createFromTimestampMsUTC($timestamp): static;

    /**
     * Create a Carbon instance from a timestamp keeping the timezone to UTC.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public static function createFromTimestampUTC(string|int|float $timestamp): static;

    /**
     * Create a Carbon instance from just a date. The time portion is set to midnight.
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createMidnightDate($year = null, $month = null, $day = null, $timezone = null);

    /**
     * Create a new safe Carbon instance from a specific date and time.
     *
     * If any of $year, $month or $day are set to null their now() values will
     * be used.
     *
     * If $hour is null it will be set to its now() value and the default
     * values for $minute and $second will be their now() values.
     *
     * If $hour is not null then the default values for $minute and $second
     * will be 0.
     *
     * If one of the set values is not valid, an InvalidDateException
     * will be thrown.
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param int|null                     $hour
     * @param int|null                     $minute
     * @param int|null                     $second
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidDateException
     *
     * @return static|null
     */
    public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null): ?static;

    /**
     * Create a new Carbon instance from a specific date and time using strict validation.
     *
     * @see create()
     *
     * @param int|null                     $year
     * @param int|null                     $month
     * @param int|null                     $day
     * @param int|null                     $hour
     * @param int|null                     $minute
     * @param int|null                     $second
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null): static;

    /**
     * Get/set the day of year.
     *
     * @template T of int|null
     *
     * @param int|null $value new value for day of year if using as setter.
     *
     * @psalm-param T $value
     *
     * @return static|int
     *
     * @psalm-return (T is int ? static : int)
     */
    public function dayOfYear(?int $value = null): static|int;

    /**
     * Get the difference as a CarbonInterval instance.
     * Return relative interval (negative if $absolute flag is not set to true and the given date is before
     * current one).
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return CarbonInterval
     */
    public function diffAsCarbonInterval($date = null, bool $absolute = false, array $skip = []): CarbonInterval;

    /**
     * Get the difference as a DateInterval instance.
     * Return relative interval (negative if $absolute flag is not set to true and the given date is before
     * current one).
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return DateInterval
     */
    public function diffAsDateInterval($date = null, bool $absolute = false): DateInterval;

    /**
     * Get the difference by the given interval using a filter closure.
     *
     * @param CarbonInterval                                         $ci       An interval to traverse by
     * @param Closure                                                $callback
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, bool $absolute = false): int;

    /**
     * Get the difference in a human readable format in the current locale from current instance to an other
     * instance given (or now if null given).
     *
     * @example
     * ```
     * echo Carbon::tomorrow()->diffForHumans() . "\n";
     * echo Carbon::tomorrow()->diffForHumans(['parts' => 2]) . "\n";
     * echo Carbon::tomorrow()->diffForHumans(['parts' => 3, 'join' => true]) . "\n";
     * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday()) . "\n";
     * echo Carbon::tomorrow()->diffForHumans(Carbon::yesterday(), ['short' => true]) . "\n";
     * ```
     *
     * @param Carbon|DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                            if null passed, now will be used as comparison reference;
     *                                                            if any other type, it will be converted to date and used as reference.
     * @param int|array                                  $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                            ⦿ 'syntax' entry (see below)
     *                                                            ⦿ 'short' entry (see below)
     *                                                            ⦿ 'parts' entry (see below)
     *                                                            ⦿ 'options' entry (see below)
     *                                                            ⦿ 'skip' entry, list of units to skip (array of strings or a single string,
     *                                                            ` it can be the unit name (singular or plural) or its shortcut
     *                                                            ` (y, m, w, d, h, min, s, ms, µs).
     *                                                            ⦿ 'aUnit' entry, prefer "an hour" over "1 hour" if true
     *                                                            ⦿ 'altNumbers' entry, use alternative numbers if available
     *                                                            ` (from the current language if true is passed, from the given language(s)
     *                                                            ` if array or string is passed)
     *                                                            ⦿ 'join' entry determines how to join multiple parts of the string
     *                                                            `  - if $join is a string, it's used as a joiner glue
     *                                                            `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                            `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                            `    will be used instead of the glue for the last item
     *                                                            `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                            `  - if $join is missing, a space will be used as glue
     *                                                            ⦿ 'other' entry (see above)
     *                                                            ⦿ 'minimumUnit' entry determines the smallest unit of time to display can be long or
     *                                                            `  short form of the units, e.g. 'hour' or 'h' (default value: s)
     *                                                            ⦿ 'locale' language in which the diff should be output (has no effect if 'translator' key is set)
     *                                                            ⦿ 'translator' a custom translator to use to translator the output.
     *                                                            if int passed, it adds modifiers:
     *                                                            Possible values:
     *                                                            - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                            - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                            - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                            Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                       $short   displays short format of time units
     * @param int                                        $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                        $options human diff options
     */
    public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null): string;

    /**
     * Get the difference in days.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInDays($date = null, bool $absolute = false, bool $utc = false): float;

    /**
     * Get the difference in days using a filter closure.
     *
     * @param Closure                                                $callback
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInDaysFiltered(Closure $callback, $date = null, bool $absolute = false): int;

    /**
     * Get the difference in hours.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInHours($date = null, bool $absolute = false): float;

    /**
     * Get the difference in hours using a filter closure.
     *
     * @param Closure                                                $callback
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInHoursFiltered(Closure $callback, $date = null, bool $absolute = false): int;

    /**
     * Get the difference in microseconds.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInMicroseconds($date = null, bool $absolute = false): float;

    /**
     * Get the difference in milliseconds.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInMilliseconds($date = null, bool $absolute = false): float;

    /**
     * Get the difference in minutes.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInMinutes($date = null, bool $absolute = false): float;

    /**
     * Get the difference in months.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInMonths($date = null, bool $absolute = false, bool $utc = false): float;

    /**
     * Get the difference in quarters.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInQuarters($date = null, bool $absolute = false, bool $utc = false): float;

    /**
     * Get the difference in seconds.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return float
     */
    public function diffInSeconds($date = null, bool $absolute = false): float;

    /**
     * @param Unit|string                                            $unit     microsecond, millisecond, second, minute,
     *                                                                         hour, day, week, month, quarter, year,
     *                                                                         century, millennium
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInUnit(Unit|string $unit, $date = null, bool $absolute = false, bool $utc = false): float;

    /**
     * Get the difference in weekdays.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInWeekdays($date = null, bool $absolute = false): int;

    /**
     * Get the difference in weekend days using a filter.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     *
     * @return int
     */
    public function diffInWeekendDays($date = null, bool $absolute = false): int;

    /**
     * Get the difference in weeks.
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInWeeks($date = null, bool $absolute = false, bool $utc = false): float;

    /**
     * Get the difference in years
     *
     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
     * @param bool                                                   $absolute Get the absolute of the difference
     * @param bool                                                   $utc      Always convert dates to UTC before comparing (if not set, it will do it only if timezones are different)
     *
     * @return float
     */
    public function diffInYears($date = null, bool $absolute = false, bool $utc = false): float;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     */
    public static function disableHumanDiffOption(int $humanDiffOption): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     */
    public static function enableHumanDiffOption(int $humanDiffOption): void;

    /**
     * Modify to end of current given unit.
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOf(Unit::Month)
     *   ->endOf(Unit::Week, Carbon::FRIDAY);
     * ```
     */
    public function endOf(Unit|string $unit, mixed ...$params): static;

    /**
     * Resets the date to end of the century and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfCentury();
     * ```
     *
     * @return static
     */
    public function endOfCentury();

    /**
     * Resets the time to 23:59:59.999999 end of day
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfDay();
     * ```
     *
     * @return static
     */
    public function endOfDay();

    /**
     * Resets the date to end of the decade and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfDecade();
     * ```
     *
     * @return static
     */
    public function endOfDecade();

    /**
     * Modify to end of current hour, minutes and seconds become 59
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfHour();
     * ```
     */
    public function endOfHour(): static;

    /**
     * Resets the date to end of the millennium and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfMillennium();
     * ```
     *
     * @return static
     */
    public function endOfMillennium();

    /**
     * Modify to end of current millisecond, microseconds such as 12345 become 123999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->endOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function endOfMillisecond(): static;

    /**
     * Modify to end of current minute, seconds become 59
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfMinute();
     * ```
     */
    public function endOfMinute(): static;

    /**
     * Resets the date to end of the month and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfMonth();
     * ```
     *
     * @return static
     */
    public function endOfMonth();

    /**
     * Resets the date to end of the quarter and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfQuarter();
     * ```
     *
     * @return static
     */
    public function endOfQuarter();

    /**
     * Modify to end of current second, microseconds become 999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->endOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function endOfSecond(): static;

    /**
     * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->endOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfWeek(Carbon::SATURDAY) . "\n";
     * ```
     *
     * @param WeekDay|int|null $weekEndsAt optional end allow you to specify the day of week to use to end the week
     *
     * @return static
     */
    public function endOfWeek(WeekDay|int|null $weekEndsAt = null): static;

    /**
     * Resets the date to end of the year and time to 23:59:59.999999
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->endOfYear();
     * ```
     *
     * @return static
     */
    public function endOfYear();

    /**
     * Determines if the instance is equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->eq(Carbon::parse('2018-07-25 12:45:16')); // true
     * Carbon::parse('2018-07-25 12:45:16')->eq('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see equalTo()
     */
    public function eq(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->equalTo(Carbon::parse('2018-07-25 12:45:16')); // true
     * Carbon::parse('2018-07-25 12:45:16')->equalTo('2018-07-25 12:45:17'); // false
     * ```
     */
    public function equalTo(DateTimeInterface|string $date): bool;

    /**
     * Set the current locale to the given, execute the passed function, reset the locale to previous one,
     * then return the result of the closure (or null if the closure was void).
     *
     * @param string   $locale locale ex. en
     * @param callable $func
     *
     * @return mixed
     */
    public static function executeWithLocale(string $locale, callable $func): mixed;

    /**
     * Get the farthest date from the instance (second-precision).
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
     *
     * @return static
     */
    public function farthest($date1, $date2);

    /**
     * Modify to the first occurrence of a given day of the week
     * in the current month. If no dayOfWeek is provided, modify to the
     * first day of the current month.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek
     *
     * @return static
     */
    public function firstOfMonth($dayOfWeek = null);

    /**
     * Modify to the first occurrence of a given day of the week
     * in the current quarter. If no dayOfWeek is provided, modify to the
     * first day of the current quarter.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function firstOfQuarter($dayOfWeek = null);

    /**
     * Modify to the first occurrence of a given day of the week
     * in the current year. If no dayOfWeek is provided, modify to the
     * first day of the current year.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function firstOfYear($dayOfWeek = null);

    /**
     * Round the current instance second with given precision if specified.
     */
    public function floor(DateInterval|string|int|float $precision = 1): static;

    /**
     * Truncate the current instance at the given unit with given precision if specified.
     */
    public function floorUnit(string $unit, DateInterval|string|int|float $precision = 1): static;

    /**
     * Truncate the current instance week.
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     */
    public function floorWeek(WeekDay|int|null $weekStartsAt = null): static;

    /**
     * @alias diffForHumans
     *
     * Get the difference in a human readable format in the current locale from current instance to an other
     * instance given (or now if null given).
     *
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                             if null passed, now will be used as comparison reference;
     *                                                             if any other type, it will be converted to date and used as reference.
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                             - 'syntax' entry (see below)
     *                                                             - 'short' entry (see below)
     *                                                             - 'parts' entry (see below)
     *                                                             - 'options' entry (see below)
     *                                                             - 'join' entry determines how to join multiple parts of the string
     *                                                             `  - if $join is a string, it's used as a joiner glue
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                             `    will be used instead of the glue for the last item
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                             `  - if $join is missing, a space will be used as glue
     *                                                             - 'other' entry (see above)
     *                                                             if int passed, it add modifiers:
     *                                                             Possible values:
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                        $short   displays short format of time units
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                         $options human diff options
     *
     * @return string
     */
    public function from($other = null, $syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * Get the difference in a human readable format in the current locale from current
     * instance to now.
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                           - 'syntax' entry (see below)
     *                           - 'short' entry (see below)
     *                           - 'parts' entry (see below)
     *                           - 'options' entry (see below)
     *                           - 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           if int passed, it add modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int       $options human diff options
     *
     * @return string
     */
    public function fromNow($syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * Create an instance from a serialized string.
     *
     * If $value is not from a trusted source, consider using the allowed_classes option to limit
     * the types of objects that can be built, for instance:
     *
     * @example
     * ```php
     * $object = Carbon::fromSerialized($value, ['allowed_classes' => [Carbon::class, CarbonImmutable::class]]);
     * ```
     *
     * @param \Stringable|string $value
     * @param array              $options example: ['allowed_classes' => [CarbonImmutable::class]]
     *
     * @throws InvalidFormatException
     *
     * @return static
     */
    public static function fromSerialized($value, array $options = []): static;

    /**
     * Register a custom macro.
     *
     * @param callable $macro
     * @param int      $priority marco with higher priority is tried first
     *
     * @return void
     */
    public static function genericMacro(callable $macro, int $priority = 0): void;

    /**
     * Get a part of the Carbon object.
     *
     * @throws UnknownGetterException
     *
     * @return string|int|bool|DateTimeZone
     */
    public function get(Unit|string $name): mixed;

    /**
     * Returns the alternative number for a given date property if available in the current locale.
     *
     * @param string $key date property
     */
    public function getAltNumber(string $key): string;

    /**
     * Returns the list of internally available locales and already loaded custom locales.
     * (It will ignore custom translator dynamic loading.)
     *
     * @return array
     */
    public static function getAvailableLocales();

    /**
     * Returns list of Language object for each available locale. This object allow you to get the ISO name, native
     * name, region and variant of the locale.
     *
     * @return Language[]
     */
    public static function getAvailableLocalesInfo();

    /**
     * Returns list of calendar formats for ISO formatting.
     *
     * @param string|null $locale current locale used if null
     */
    public function getCalendarFormats(?string $locale = null): array;

    public function getClock(): ?WrapperClock;

    /**
     * Get the days of the week.
     */
    public static function getDays(): array;

    /**
     * Return the number of days since the start of the week (using the current locale or the first parameter
     * if explicitly given).
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week,
     *                                       if not provided, start of week is inferred from the locale
     *                                       (Sunday for en_US, Monday for de_DE, etc.)
     */
    public function getDaysFromStartOfWeek(WeekDay|int|null $weekStartsAt = null): int;

    /**
     * Get the fallback locale.
     *
     * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
     */
    public static function getFallbackLocale(): ?string;

    /**
     * List of replacements from date() format to isoFormat().
     */
    public static function getFormatsToIsoReplacements(): array;

    /**
     * Return default humanDiff() options (merged flags as integer).
     */
    public static function getHumanDiffOptions(): int;

    /**
     * Returns list of locale formats for ISO formatting.
     *
     * @param string|null $locale current locale used if null
     */
    public function getIsoFormats(?string $locale = null): array;

    /**
     * Returns list of locale units for ISO formatting.
     */
    public static function getIsoUnits(): array;

    /**
     * {@inheritdoc}
     */
    public static function getLastErrors(): array|false;

    /**
     * Get the raw callable macro registered globally or locally for a given name.
     */
    public function getLocalMacro(string $name): ?callable;

    /**
     * Get the translator of the current instance or the default if none set.
     */
    public function getLocalTranslator(): TranslatorInterface;

    /**
     * Get the current translator locale.
     *
     * @return string
     */
    public static function getLocale(): string;

    /**
     * Get the raw callable macro registered globally for a given name.
     */
    public static function getMacro(string $name): ?callable;

    /**
     * get midday/noon hour
     *
     * @return int
     */
    public static function getMidDayAt();

    /**
     * Returns the offset hour and minute formatted with +/- and a given separator (":" by default).
     * For example, if the time zone is 9 hours 30 minutes, you'll get "+09:30", with "@@" as first
     * argument, "+09@@30", with "" as first argument, "+0930". Negative offset will return something
     * like "-12:00".
     *
     * @param string $separator string to place between hours and minutes (":" by default)
     */
    public function getOffsetString(string $separator = ':'): string;

    /**
     * Returns a unit of the instance padded with 0 by default or any other string if specified.
     *
     * @param string $unit      Carbon unit name
     * @param int    $length    Length of the output (2 by default)
     * @param string $padString String to use for padding ("0" by default)
     * @param int    $padType   Side(s) to pad (STR_PAD_LEFT by default)
     */
    public function getPaddedUnit($unit, $length = 2, $padString = '0', $padType = 0): string;

    /**
     * Returns a timestamp rounded with the given precision (6 by default).
     *
     * @example getPreciseTimestamp()   1532087464437474 (microsecond maximum precision)
     * @example getPreciseTimestamp(6)  1532087464437474
     * @example getPreciseTimestamp(5)  153208746443747  (1/100000 second precision)
     * @example getPreciseTimestamp(4)  15320874644375   (1/10000 second precision)
     * @example getPreciseTimestamp(3)  1532087464437    (millisecond precision)
     * @example getPreciseTimestamp(2)  153208746444     (1/100 second precision)
     * @example getPreciseTimestamp(1)  15320874644      (1/10 second precision)
     * @example getPreciseTimestamp(0)  1532087464       (second precision)
     * @example getPreciseTimestamp(-1) 153208746        (10 second precision)
     * @example getPreciseTimestamp(-2) 15320875         (100 second precision)
     *
     * @param int $precision
     *
     * @return float
     */
    public function getPreciseTimestamp($precision = 6): float;

    /**
     * Returns current local settings.
     */
    public function getSettings(): array;

    /**
     * Get the Carbon instance (real or mock) to be returned when a "now"
     * instance is created.
     *
     * @return Closure|self|null the current instance used for testing
     */
    public static function getTestNow(): Closure|self|null;

    /**
     * Return a format from H:i to H:i:s.u according to given unit precision.
     *
     * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond"
     */
    public static function getTimeFormatByPrecision(string $unitPrecision): string;

    /**
     * Returns the timestamp with millisecond precision.
     *
     * @return int
     */
    public function getTimestampMs(): int;

    /**
     * Get the translation of the current week day name (with context for languages with multiple forms).
     *
     * @param string|null $context      whole format string
     * @param string      $keySuffix    "", "_short" or "_min"
     * @param string|null $defaultValue default value if translation missing
     */
    public function getTranslatedDayName(?string $context = null, string $keySuffix = '', ?string $defaultValue = null): string;

    /**
     * Get the translation of the current abbreviated week day name (with context for languages with multiple forms).
     *
     * @param string|null $context whole format string
     */
    public function getTranslatedMinDayName(?string $context = null): string;

    /**
     * Get the translation of the current month day name (with context for languages with multiple forms).
     *
     * @param string|null $context      whole format string
     * @param string      $keySuffix    "" or "_short"
     * @param string|null $defaultValue default value if translation missing
     */
    public function getTranslatedMonthName(?string $context = null, string $keySuffix = '', ?string $defaultValue = null): string;

    /**
     * Get the translation of the current short week day name (with context for languages with multiple forms).
     *
     * @param string|null $context whole format string
     */
    public function getTranslatedShortDayName(?string $context = null): string;

    /**
     * Get the translation of the current short month day name (with context for languages with multiple forms).
     *
     * @param string|null $context whole format string
     */
    public function getTranslatedShortMonthName(?string $context = null): string;

    /**
     * Returns raw translation message for a given key.
     *
     * @param string              $key        key to find
     * @param string|null         $locale     current locale used if null
     * @param string|null         $default    default value if translation returns the key
     * @param TranslatorInterface $translator an optional translator to use
     *
     * @return string
     */
    public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null);

    /**
     * Returns raw translation message for a given key.
     *
     * @param TranslatorInterface|null $translator the translator to use
     * @param string                   $key        key to find
     * @param string|null              $locale     current locale used if null
     * @param string|null              $default    default value if translation returns the key
     *
     * @return string|Closure|null
     */
    public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null);

    /**
     * Initialize the default translator instance if necessary.
     */
    public static function getTranslator(): TranslatorInterface;

    /**
     * Get the last day of week.
     *
     * @param string $locale local to consider the last day of week.
     *
     * @return int
     */
    public static function getWeekEndsAt(?string $locale = null): int;

    /**
     * Get the first day of week.
     *
     * @return int
     */
    public static function getWeekStartsAt(?string $locale = null): int;

    /**
     * Get weekend days
     */
    public static function getWeekendDays(): array;

    /**
     * Determines if the instance is greater (after) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->greaterThan('2018-07-25 12:45:17'); // false
     * ```
     */
    public function greaterThan(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is greater (after) than or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->greaterThanOrEqualTo('2018-07-25 12:45:17'); // false
     * ```
     */
    public function greaterThanOrEqualTo(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is greater (after) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->gt('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see greaterThan()
     */
    public function gt(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is greater (after) than or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->gte('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see greaterThanOrEqualTo()
     */
    public function gte(DateTimeInterface|string $date): bool;

    /**
     * Checks if the (date)time string is in a given format.
     *
     * @example
     * ```
     * Carbon::hasFormat('11:12:45', 'h:i:s'); // true
     * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
     * ```
     */
    public static function hasFormat(string $date, string $format): bool;

    /**
     * Checks if the (date)time string is in a given format.
     *
     * @example
     * ```
     * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true
     * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false
     * ```
     *
     * @param string $date
     * @param string $format
     *
     * @return bool
     */
    public static function hasFormatWithModifiers(?string $date, string $format): bool;

    /**
     * Checks if macro is registered globally or locally.
     */
    public function hasLocalMacro(string $name): bool;

    /**
     * Return true if the current instance has its own translator.
     */
    public function hasLocalTranslator(): bool;

    /**
     * Checks if macro is registered globally.
     *
     * @param string $name
     *
     * @return bool
     */
    public static function hasMacro(string $name): bool;

    /**
     * Determine if a time string will produce a relative date.
     *
     * @return bool true if time match a relative date, false if absolute or invalid time string
     */
    public static function hasRelativeKeywords(?string $time): bool;

    /**
     * Determine if there is a valid test instance set. A valid test instance
     * is anything that is not null.
     *
     * @return bool true if there is a test instance, otherwise false
     */
    public static function hasTestNow(): bool;

    /**
     * Create a Carbon instance from a DateTime one.
     */
    public static function instance(DateTimeInterface $date): static;

    /**
     * Returns true if the current date matches the given string.
     *
     * @example
     * ```
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2018')); // false
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('06-02')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('2019-06-02')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('Sunday')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('June')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:45')); // true
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12:23:00')); // false
     * var_dump(Carbon::parse('2019-06-02 12:23:45')->is('12h')); // true
     * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3pm')); // true
     * var_dump(Carbon::parse('2019-06-02 15:23:45')->is('3am')); // false
     * ```
     *
     * @param string $tester day name, month name, hour, date, etc. as string
     */
    public function is(WeekDay|Month|string $tester): bool;

    /**
     * Determines if the instance is greater (after) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:15'); // true
     * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->isAfter('2018-07-25 12:45:17'); // false
     * ```
     *
     * @see greaterThan()
     */
    public function isAfter(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is less (before) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->isBefore('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see lessThan()
     */
    public function isBefore(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is between two others
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25')->isBetween('2018-07-14', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->isBetween('2018-08-01', '2018-08-20'); // false
     * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01'); // true
     * Carbon::parse('2018-07-25')->isBetween('2018-07-25', '2018-08-01', false); // false
     * ```
     *
     * @param bool $equal Indicates if an equal to comparison should be done
     */
    public function isBetween(DateTimeInterface|string $date1, DateTimeInterface|string $date2, bool $equal = true): bool;

    /**
     * Check if its the birthday. Compares the date/month values of the two dates.
     *
     * @example
     * ```
     * Carbon::now()->subYears(5)->isBirthday(); // true
     * Carbon::now()->subYears(5)->subDay()->isBirthday(); // false
     * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-05')); // true
     * Carbon::parse('2019-06-05')->isBirthday(Carbon::parse('2001-06-06')); // false
     * ```
     *
     * @param DateTimeInterface|string|null $date The instance to compare with or null to use current day.
     *
     * @return bool
     */
    public function isBirthday(DateTimeInterface|string|null $date = null): bool;

    /**
     * Determines if the instance is in the current unit given.
     *
     * @example
     * ```
     * Carbon::now()->isCurrentUnit('hour'); // true
     * Carbon::now()->subHours(2)->isCurrentUnit('hour'); // false
     * ```
     *
     * @param string $unit The unit to test.
     *
     * @throws BadMethodCallException
     */
    public function isCurrentUnit(string $unit): bool;

    /**
     * Checks if this day is a specific day of the week.
     *
     * @example
     * ```
     * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::WEDNESDAY); // true
     * Carbon::parse('2019-07-17')->isDayOfWeek(Carbon::FRIDAY); // false
     * Carbon::parse('2019-07-17')->isDayOfWeek('Wednesday'); // true
     * Carbon::parse('2019-07-17')->isDayOfWeek('Friday'); // false
     * ```
     *
     * @param int|string $dayOfWeek
     *
     * @return bool
     */
    public function isDayOfWeek($dayOfWeek): bool;

    /**
     * Determines if the instance is end of century (last day by default but interval can be customized).
     */
    public function isEndOfCentury(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Check if the instance is end of day.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(); // true
     * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(); // true
     * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(); // true
     * Carbon::parse('2019-02-28 23:59:58.999999')->isEndOfDay(); // false
     * Carbon::parse('2019-02-28 23:59:59.999999')->isEndOfDay(true); // true
     * Carbon::parse('2019-02-28 23:59:59.123456')->isEndOfDay(true); // false
     * Carbon::parse('2019-02-28 23:59:59')->isEndOfDay(true); // false
     * ```
     *
     * @param bool                                                           $checkMicroseconds check time at microseconds precision
     * @param Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval          if an interval is specified it will be used as precision
     *                                                                                          for instance with "15 minutes", it checks if current date-time
     *                                                                                          is in the last 15 minutes of the day, with Unit::Hour, it
     *                                                                                          checks if it's in the last hour of the day.
     */
    public function isEndOfDay(Unit|DateInterval|Closure|CarbonConverterInterface|string|bool $checkMicroseconds = false, Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of decade (last day by default but interval can be customized).
     */
    public function isEndOfDecade(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of hour (last microsecond by default but interval can be customized).
     */
    public function isEndOfHour(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of millennium (last day by default but interval can be customized).
     */
    public function isEndOfMillennium(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of millisecond (last microsecond by default but interval can be customized).
     */
    public function isEndOfMillisecond(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of minute (last microsecond by default but interval can be customized).
     */
    public function isEndOfMinute(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of month (last day by default but interval can be customized).
     */
    public function isEndOfMonth(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of quarter (last day by default but interval can be customized).
     */
    public function isEndOfQuarter(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is end of second (last microsecond by default but interval can be customized).
     */
    public function isEndOfSecond(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Returns true if the date was created using CarbonImmutable::endOfTime()
     *
     * @return bool
     */
    public function isEndOfTime(): bool;

    /**
     * Check if the instance is end of a given unit (tolerating a given interval).
     *
     * @example
     * ```
     * // Check if a date-time is the last 15 minutes of the hour it's in
     * Carbon::parse('2019-02-28 20:13:00')->isEndOfUnit(Unit::Hour, '15 minutes'); // false
     * ```
     */
    public function isEndOfUnit(Unit $unit, Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null, mixed ...$params): bool;

    /**
     * Determines if the instance is end of week (last day by default but interval can be customized).
     *
     * @example
     * ```
     * Carbon::parse('2024-08-31')->endOfWeek()->isEndOfWeek(); // true
     * Carbon::parse('2024-08-31')->isEndOfWeek(); // false
     * ```
     */
    public function isEndOfWeek(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null, WeekDay|int|null $weekEndsAt = null): bool;

    /**
     * Determines if the instance is end of year (last day by default but interval can be customized).
     */
    public function isEndOfYear(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is in the future, ie. greater (after) than now.
     *
     * @example
     * ```
     * Carbon::now()->addHours(5)->isFuture(); // true
     * Carbon::now()->subHours(5)->isFuture(); // false
     * ```
     */
    public function isFuture(): bool;

    /**
     * Returns true if the current class/instance is immutable.
     */
    public static function isImmutable(): bool;

    /**
     * Check if today is the last day of the Month
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28')->isLastOfMonth(); // true
     * Carbon::parse('2019-03-28')->isLastOfMonth(); // false
     * Carbon::parse('2019-03-30')->isLastOfMonth(); // false
     * Carbon::parse('2019-03-31')->isLastOfMonth(); // true
     * Carbon::parse('2019-04-30')->isLastOfMonth(); // true
     * ```
     */
    public function isLastOfMonth(): bool;

    /**
     * Determines if the instance is a leap year.
     *
     * @example
     * ```
     * Carbon::parse('2020-01-01')->isLeapYear(); // true
     * Carbon::parse('2019-01-01')->isLeapYear(); // false
     * ```
     */
    public function isLeapYear(): bool;

    /**
     * Determines if the instance is a long year (using ISO 8601 year).
     *
     * @example
     * ```
     * Carbon::parse('2015-01-01')->isLongIsoYear(); // true
     * Carbon::parse('2016-01-01')->isLongIsoYear(); // true
     * Carbon::parse('2016-01-03')->isLongIsoYear(); // false
     * Carbon::parse('2019-12-29')->isLongIsoYear(); // false
     * Carbon::parse('2019-12-30')->isLongIsoYear(); // true
     * ```
     *
     * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
     */
    public function isLongIsoYear(): bool;

    /**
     * Determines if the instance is a long year (using calendar year).
     *
     * ⚠️ This method completely ignores month and day to use the numeric year number,
     * it's not correct if the exact date matters. For instance as `2019-12-30` is already
     * in the first week of the 2020 year, if you want to know from this date if ISO week
     * year 2020 is a long year, use `isLongIsoYear` instead.
     *
     * @example
     * ```
     * Carbon::create(2015)->isLongYear(); // true
     * Carbon::create(2016)->isLongYear(); // false
     * ```
     *
     * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
     */
    public function isLongYear(): bool;

    /**
     * Check if the instance is midday.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 11:59:59.999999')->isMidday(); // false
     * Carbon::parse('2019-02-28 12:00:00')->isMidday(); // true
     * Carbon::parse('2019-02-28 12:00:00.999999')->isMidday(); // true
     * Carbon::parse('2019-02-28 12:00:01')->isMidday(); // false
     * ```
     */
    public function isMidday(): bool;

    /**
     * Check if the instance is start of day / midnight.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 00:00:00')->isMidnight(); // true
     * Carbon::parse('2019-02-28 00:00:00.999999')->isMidnight(); // true
     * Carbon::parse('2019-02-28 00:00:01')->isMidnight(); // false
     * ```
     */
    public function isMidnight(): bool;

    /**
     * Returns true if a property can be changed via setter.
     *
     * @param string $unit
     *
     * @return bool
     */
    public static function isModifiableUnit($unit): bool;

    /**
     * Returns true if the current class/instance is mutable.
     */
    public static function isMutable(): bool;

    /**
     * Determines if the instance is now or in the future, ie. greater (after) than or equal to now.
     *
     * @example
     * ```
     * Carbon::now()->isNowOrFuture(); // true
     * Carbon::now()->addHours(5)->isNowOrFuture(); // true
     * Carbon::now()->subHours(5)->isNowOrFuture(); // false
     * ```
     */
    public function isNowOrFuture(): bool;

    /**
     * Determines if the instance is now or in the past, ie. less (before) than or equal to now.
     *
     * @example
     * ```
     * Carbon::now()->isNowOrPast(); // true
     * Carbon::now()->subHours(5)->isNowOrPast(); // true
     * Carbon::now()->addHours(5)->isNowOrPast(); // false
     * ```
     */
    public function isNowOrPast(): bool;

    /**
     * Determines if the instance is in the past, ie. less (before) than now.
     *
     * @example
     * ```
     * Carbon::now()->subHours(5)->isPast(); // true
     * Carbon::now()->addHours(5)->isPast(); // false
     * ```
     */
    public function isPast(): bool;

    /**
     * Compares the formatted values of the two dates.
     *
     * @example
     * ```
     * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-12-13')); // true
     * Carbon::parse('2019-06-13')->isSameAs('Y-d', Carbon::parse('2019-06-14')); // false
     * ```
     *
     * @param string                   $format date formats to compare.
     * @param DateTimeInterface|string $date   instance to compare with or null to use current day.
     */
    public function isSameAs(string $format, DateTimeInterface|string $date): bool;

    /**
     * Checks if the passed in date is in the same month as the instance´s month.
     *
     * @example
     * ```
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-01-01')); // true
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2019-02-01')); // false
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01')); // false
     * Carbon::parse('2019-01-12')->isSameMonth(Carbon::parse('2018-01-01'), false); // true
     * ```
     *
     * @param DateTimeInterface|string $date       The instance to compare with or null to use the current date.
     * @param bool                     $ofSameYear Check if it is the same month in the same year.
     *
     * @return bool
     */
    public function isSameMonth(DateTimeInterface|string $date, bool $ofSameYear = true): bool;

    /**
     * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
     *
     * @example
     * ```
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-03-01')); // true
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2019-04-01')); // false
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01')); // false
     * Carbon::parse('2019-01-12')->isSameQuarter(Carbon::parse('2018-03-01'), false); // true
     * ```
     *
     * @param DateTimeInterface|string $date       The instance to compare with or null to use current day.
     * @param bool                     $ofSameYear Check if it is the same month in the same year.
     *
     * @return bool
     */
    public function isSameQuarter(DateTimeInterface|string $date, bool $ofSameYear = true): bool;

    /**
     * Determines if the instance is in the current unit given.
     *
     * @example
     * ```
     * Carbon::parse('2019-01-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // true
     * Carbon::parse('2018-12-13')->isSameUnit('year', Carbon::parse('2019-12-25')); // false
     * ```
     *
     * @param string                   $unit singular unit string
     * @param DateTimeInterface|string $date instance to compare with or null to use current day.
     *
     * @throws BadComparisonUnitException
     *
     * @return bool
     */
    public function isSameUnit(string $unit, DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is start of century (first day by default but interval can be customized).
     */
    public function isStartOfCentury(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Check if the instance is start of day / midnight.
     *
     * @example
     * ```
     * Carbon::parse('2019-02-28 00:00:00')->isStartOfDay(); // true
     * Carbon::parse('2019-02-28 00:00:00.999999')->isStartOfDay(); // true
     * Carbon::parse('2019-02-28 00:00:01')->isStartOfDay(); // false
     * Carbon::parse('2019-02-28 00:00:00.000000')->isStartOfDay(true); // true
     * Carbon::parse('2019-02-28 00:00:00.000012')->isStartOfDay(true); // false
     * ```
     *
     * @param bool                                                           $checkMicroseconds check time at microseconds precision
     * @param Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval          if an interval is specified it will be used as precision
     *                                                                                          for instance with "15 minutes", it checks if current date-time
     *                                                                                          is in the last 15 minutes of the day, with Unit::Hour, it
     *                                                                                          checks if it's in the last hour of the day.
     */
    public function isStartOfDay(Unit|DateInterval|Closure|CarbonConverterInterface|string|bool $checkMicroseconds = false, Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of decade (first day by default but interval can be customized).
     */
    public function isStartOfDecade(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of hour (first microsecond by default but interval can be customized).
     */
    public function isStartOfHour(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of millennium (first day by default but interval can be customized).
     */
    public function isStartOfMillennium(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of millisecond (first microsecond by default but interval can be customized).
     */
    public function isStartOfMillisecond(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of minute (first microsecond by default but interval can be customized).
     */
    public function isStartOfMinute(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of month (first day by default but interval can be customized).
     */
    public function isStartOfMonth(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of quarter (first day by default but interval can be customized).
     */
    public function isStartOfQuarter(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Determines if the instance is start of second (first microsecond by default but interval can be customized).
     */
    public function isStartOfSecond(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Returns true if the date was created using CarbonImmutable::startOfTime()
     *
     * @return bool
     */
    public function isStartOfTime(): bool;

    /**
     * Check if the instance is start of a given unit (tolerating a given interval).
     *
     * @example
     * ```
     * // Check if a date-time is the first 15 minutes of the hour it's in
     * Carbon::parse('2019-02-28 20:13:00')->isStartOfUnit(Unit::Hour, '15 minutes'); // true
     * ```
     */
    public function isStartOfUnit(Unit $unit, Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null, mixed ...$params): bool;

    /**
     * Determines if the instance is start of week (first day by default but interval can be customized).
     *
     * @example
     * ```
     * Carbon::parse('2024-08-31')->startOfWeek()->isStartOfWeek(); // true
     * Carbon::parse('2024-08-31')->isStartOfWeek(); // false
     * ```
     */
    public function isStartOfWeek(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null, WeekDay|int|null $weekStartsAt = null): bool;

    /**
     * Determines if the instance is start of year (first day by default but interval can be customized).
     */
    public function isStartOfYear(Unit|DateInterval|Closure|CarbonConverterInterface|string|null $interval = null): bool;

    /**
     * Returns true if the strict mode is globally in use, false else.
     * (It can be overridden in specific instances.)
     *
     * @return bool
     */
    public static function isStrictModeEnabled(): bool;

    /**
     * Determines if the instance is today.
     *
     * @example
     * ```
     * Carbon::today()->isToday(); // true
     * Carbon::tomorrow()->isToday(); // false
     * ```
     */
    public function isToday(): bool;

    /**
     * Determines if the instance is tomorrow.
     *
     * @example
     * ```
     * Carbon::tomorrow()->isTomorrow(); // true
     * Carbon::yesterday()->isTomorrow(); // false
     * ```
     */
    public function isTomorrow(): bool;

    /**
     * Determines if the instance is a weekday.
     *
     * @example
     * ```
     * Carbon::parse('2019-07-14')->isWeekday(); // false
     * Carbon::parse('2019-07-15')->isWeekday(); // true
     * ```
     */
    public function isWeekday(): bool;

    /**
     * Determines if the instance is a weekend day.
     *
     * @example
     * ```
     * Carbon::parse('2019-07-14')->isWeekend(); // true
     * Carbon::parse('2019-07-15')->isWeekend(); // false
     * ```
     */
    public function isWeekend(): bool;

    /**
     * Determines if the instance is yesterday.
     *
     * @example
     * ```
     * Carbon::yesterday()->isYesterday(); // true
     * Carbon::tomorrow()->isYesterday(); // false
     * ```
     */
    public function isYesterday(): bool;

    /**
     * Format in the current language using ISO replacement patterns.
     *
     * @param string|null $originalFormat provide context if a chunk has been passed alone
     */
    public function isoFormat(string $format, ?string $originalFormat = null): string;

    /**
     * Get/set the week number using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $week
     * @param int|null $dayOfWeek
     * @param int|null $dayOfYear
     *
     * @return int|static
     */
    public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null);

    /**
     * Set/get the week number of year using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $year      if null, act as a getter, if not null, set the year and return current instance.
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int|static
     */
    public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null);

    /**
     * Get/set the ISO weekday from 1 (Monday) to 7 (Sunday).
     *
     * @param WeekDay|int|null $value new value for weekday if using as setter.
     */
    public function isoWeekday(WeekDay|int|null $value = null): static|int;

    /**
     * Get the number of weeks of the current week-year using given first day of week and first
     * day of year included in the first week. Or use ISO format if no settings
     * given.
     *
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int
     */
    public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null);

    /**
     * Prepare the object for JSON serialization.
     */
    public function jsonSerialize(): mixed;

    /**
     * Modify to the last occurrence of a given day of the week
     * in the current month. If no dayOfWeek is provided, modify to the
     * last day of the current month.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek
     *
     * @return static
     */
    public function lastOfMonth($dayOfWeek = null);

    /**
     * Modify to the last occurrence of a given day of the week
     * in the current quarter. If no dayOfWeek is provided, modify to the
     * last day of the current quarter.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function lastOfQuarter($dayOfWeek = null);

    /**
     * Modify to the last occurrence of a given day of the week
     * in the current year. If no dayOfWeek is provided, modify to the
     * last day of the current year.  Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int|null $dayOfWeek day of the week default null
     *
     * @return static
     */
    public function lastOfYear($dayOfWeek = null);

    /**
     * Determines if the instance is less (before) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lessThan('2018-07-25 12:45:17'); // true
     * ```
     */
    public function lessThan(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is less (before) or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->lessThanOrEqualTo('2018-07-25 12:45:17'); // true
     * ```
     */
    public function lessThanOrEqualTo(DateTimeInterface|string $date): bool;

    /**
     * Get/set the locale for the current instance.
     *
     * @param string|null $locale
     * @param string      ...$fallbackLocales
     *
     * @return $this|string
     */
    public function locale(?string $locale = null, string ...$fallbackLocales): static|string;

    /**
     * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
     * Support is considered enabled if the 3 words are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasDiffOneDayWords(string $locale): bool;

    /**
     * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
     * Support is considered enabled if the 4 sentences are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasDiffSyntax(string $locale): bool;

    /**
     * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
     * Support is considered enabled if the 2 words are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasDiffTwoDayWords(string $locale): bool;

    /**
     * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
     * Support is considered enabled if the 4 sentences are translated in the given locale.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasPeriodSyntax($locale);

    /**
     * Returns true if the given locale is internally supported and has short-units support.
     * Support is considered enabled if either year, day or hour has a short variant translated.
     *
     * @param string $locale locale ex. en
     *
     * @return bool
     */
    public static function localeHasShortUnits(string $locale): bool;

    /**
     * Determines if the instance is less (before) than another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lt('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see lessThan()
     */
    public function lt(DateTimeInterface|string $date): bool;

    /**
     * Determines if the instance is less (before) or equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:15'); // false
     * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:16'); // true
     * Carbon::parse('2018-07-25 12:45:16')->lte('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see lessThanOrEqualTo()
     */
    public function lte(DateTimeInterface|string $date): bool;

    /**
     * Register a custom macro.
     *
     * Pass null macro to remove it.
     *
     * @example
     * ```
     * $userSettings = [
     *   'locale' => 'pt',
     *   'timezone' => 'America/Sao_Paulo',
     * ];
     * Carbon::macro('userFormat', function () use ($userSettings) {
     *   return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar();
     * });
     * echo Carbon::yesterday()->hours(11)->userFormat();
     * ```
     *
     * @param-closure-this static $macro
     */
    public static function macro(string $name, ?callable $macro): void;

    /**
     * Make a Carbon instance from given variable if possible.
     *
     * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
     * and recurrences). Throw an exception for invalid format, but otherwise return null.
     *
     * @param mixed $var
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function make($var, DateTimeZone|string|null $timezone = null): ?static;

    /**
     * Get the maximum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @return static
     */
    public function max($date = null);

    /**
     * Get the maximum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @see max()
     *
     * @return static
     */
    public function maximum($date = null);

    /**
     * Return the meridiem of the current time in the current locale.
     *
     * @param bool $isLower if true, returns lowercase variant if available in the current locale.
     */
    public function meridiem(bool $isLower = false): string;

    /**
     * Modify to midday, default to self::$midDayAt
     *
     * @return static
     */
    public function midDay();

    /**
     * Get the minimum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @return static
     */
    public function min($date = null);

    /**
     * Get the minimum instance between a given instance (default now) and the current instance.
     *
     * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
     *
     * @see min()
     *
     * @return static
     */
    public function minimum($date = null);

    /**
     * Mix another object into the class.
     *
     * @example
     * ```
     * Carbon::mixin(new class {
     *   public function addMoon() {
     *     return function () {
     *       return $this->addDays(30);
     *     };
     *   }
     *   public function subMoon() {
     *     return function () {
     *       return $this->subDays(30);
     *     };
     *   }
     * });
     * $fullMoon = Carbon::create('2018-12-22');
     * $nextFullMoon = $fullMoon->addMoon();
     * $blackMoon = Carbon::create('2019-01-06');
     * $previousBlackMoon = $blackMoon->subMoon();
     * echo "$nextFullMoon\n";
     * echo "$previousBlackMoon\n";
     * ```
     *
     * @throws ReflectionException
     */
    public static function mixin(object|string $mixin): void;

    /**
     * Calls \DateTime::modify if mutable or \DateTimeImmutable::modify else.
     *
     * @see https://php.net/manual/en/datetime.modify.php
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public function modify($modify);

    /**
     * Determines if the instance is not equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->ne(Carbon::parse('2018-07-25 12:45:16')); // false
     * Carbon::parse('2018-07-25 12:45:16')->ne('2018-07-25 12:45:17'); // true
     * ```
     *
     * @see notEqualTo()
     */
    public function ne(DateTimeInterface|string $date): bool;

    /**
     * Modify to the next occurrence of a given modifier such as a day of
     * the week. If no modifier is provided, modify to the next occurrence
     * of the current day of the week. Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param string|int|null $modifier
     *
     * @return static
     */
    public function next($modifier = null);

    /**
     * Go forward to the next weekday.
     *
     * @return static
     */
    public function nextWeekday();

    /**
     * Go forward to the next weekend day.
     *
     * @return static
     */
    public function nextWeekendDay();

    /**
     * Determines if the instance is not equal to another
     *
     * @example
     * ```
     * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:16'); // false
     * Carbon::parse('2018-07-25 12:45:16')->notEqualTo(Carbon::parse('2018-07-25 12:45:16')); // false
     * Carbon::parse('2018-07-25 12:45:16')->notEqualTo('2018-07-25 12:45:17'); // true
     * ```
     */
    public function notEqualTo(DateTimeInterface|string $date): bool;

    /**
     * Get a Carbon instance for the current date and time.
     */
    public static function now(DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Returns a present instance in the same timezone.
     *
     * @return static
     */
    public function nowWithSameTz(): static;

    /**
     * Modify to the given occurrence of a given day of the week
     * in the current month. If the calculated occurrence is outside the scope
     * of the current month, then return false and no modifications are made.
     * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int $nth
     * @param int $dayOfWeek
     *
     * @return mixed
     */
    public function nthOfMonth($nth, $dayOfWeek);

    /**
     * Modify to the given occurrence of a given day of the week
     * in the current quarter. If the calculated occurrence is outside the scope
     * of the current quarter, then return false and no modifications are made.
     * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int $nth
     * @param int $dayOfWeek
     *
     * @return mixed
     */
    public function nthOfQuarter($nth, $dayOfWeek);

    /**
     * Modify to the given occurrence of a given day of the week
     * in the current year. If the calculated occurrence is outside the scope
     * of the current year, then return false and no modifications are made.
     * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param int $nth
     * @param int $dayOfWeek
     *
     * @return mixed
     */
    public function nthOfYear($nth, $dayOfWeek);

    /**
     * Return a property with its ordinal.
     */
    public function ordinal(string $key, ?string $period = null): string;

    /**
     * Create a carbon instance from a string.
     *
     * This is an alias for the constructor that allows better fluent syntax
     * as it allows you to do Carbon::parse('Monday next week')->fn() rather
     * than (new Carbon('Monday next week'))->fn().
     *
     * @throws InvalidFormatException
     */
    public static function parse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.).
     *
     * @param string                       $time     date/time string in the given language (may also contain English).
     * @param string|null                  $locale   if locale is null or not specified, current global locale will be
     *                                               used instead.
     * @param DateTimeZone|string|int|null $timezone optional timezone for the new instance.
     *
     * @throws InvalidFormatException
     */
    public static function parseFromLocale(string $time, ?string $locale = null, DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Returns standardized plural of a given singular/plural unit name (in English).
     */
    public static function pluralUnit(string $unit): string;

    /**
     * Modify to the previous occurrence of a given modifier such as a day of
     * the week. If no dayOfWeek is provided, modify to the previous occurrence
     * of the current day of the week. Use the supplied constants
     * to indicate the desired dayOfWeek, ex. static::MONDAY.
     *
     * @param string|int|null $modifier
     *
     * @return static
     */
    public function previous($modifier = null);

    /**
     * Go backward to the previous weekday.
     *
     * @return static
     */
    public function previousWeekday();

    /**
     * Go backward to the previous weekend day.
     *
     * @return static
     */
    public function previousWeekendDay();

    /**
     * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
     *
     * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end      period end date
     * @param int|\DateInterval|string|null                  $interval period default interval or number of the given $unit
     * @param string|null                                    $unit     if specified, $interval must be an integer
     */
    public function range($end = null, $interval = null, $unit = null): CarbonPeriod;

    /**
     * Call native PHP DateTime/DateTimeImmutable add() method.
     *
     * @param DateInterval $interval
     *
     * @return static
     */
    public function rawAdd(DateInterval $interval): static;

    /**
     * Create a Carbon instance from a specific format.
     *
     * @param string                       $format   Datetime format
     * @param string                       $time
     * @param DateTimeZone|string|int|null $timezone
     *
     * @throws InvalidFormatException
     *
     * @return static|null
     */
    public static function rawCreateFromFormat(string $format, string $time, $timezone = null): ?static;

    /**
     * @see https://php.net/manual/en/datetime.format.php
     */
    public function rawFormat(string $format): string;

    /**
     * Create a carbon instance from a string.
     *
     * This is an alias for the constructor that allows better fluent syntax
     * as it allows you to do Carbon::parse('Monday next week')->fn() rather
     * than (new Carbon('Monday next week'))->fn().
     *
     * @throws InvalidFormatException
     */
    public static function rawParse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Call native PHP DateTime/DateTimeImmutable sub() method.
     */
    public function rawSub(DateInterval $interval): static;

    /**
     * Remove all macros and generic macros.
     */
    public static function resetMacros(): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Reset the month overflow behavior.
     *
     * @return void
     */
    public static function resetMonthsOverflow(): void;

    /**
     * Reset the format used to the default when type juggling a Carbon instance to a string
     *
     * @return void
     */
    public static function resetToStringFormat(): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Reset the month overflow behavior.
     *
     * @return void
     */
    public static function resetYearsOverflow(): void;

    /**
     * Round the current instance second with given precision if specified.
     */
    public function round(DateInterval|string|int|float $precision = 1, callable|string $function = 'round'): static;

    /**
     * Round the current instance at the given unit with given precision if specified and the given function.
     */
    public function roundUnit(string $unit, DateInterval|string|int|float $precision = 1, callable|string $function = 'round'): static;

    /**
     * Round the current instance week.
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     */
    public function roundWeek(WeekDay|int|null $weekStartsAt = null): static;

    /**
     * The number of seconds since midnight.
     *
     * @return float
     */
    public function secondsSinceMidnight(): float;

    /**
     * The number of seconds until 23:59:59.
     *
     * @return float
     */
    public function secondsUntilEndOfDay(): float;

    /**
     * Return a serialized string of the instance.
     */
    public function serialize(): string;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather transform Carbon object before the serialization.
     *
     * JSON serialize all Carbon instances using the given callback.
     */
    public static function serializeUsing(callable|string|null $format): void;

    /**
     * Set a part of the Carbon object.
     *
     * @throws ImmutableException|UnknownSetterException
     *
     * @return $this
     */
    public function set(Unit|array|string $name, DateTimeZone|Month|string|int|float|null $value = null): static;

    /**
     * Set the date with gregorian year, month and day numbers.
     *
     * @see https://php.net/manual/en/datetime.setdate.php
     */
    public function setDate(int $year, int $month, int $day): static;

    /**
     * Set the year, month, and date for this instance to that of the passed instance.
     */
    public function setDateFrom(DateTimeInterface|string $date): static;

    /**
     * Set the date and time all together.
     */
    public function setDateTime(int $year, int $month, int $day, int $hour, int $minute, int $second = 0, int $microseconds = 0): static;

    /**
     * Set the date and time for this instance to that of the passed instance.
     */
    public function setDateTimeFrom(DateTimeInterface|string $date): static;

    /**
     * Set the day (keeping the current time) to the start of the week + the number of days passed as the first
     * parameter. First day of week is driven by the locale unless explicitly set with the second parameter.
     *
     * @param int              $numberOfDays number of days to add after the start of the current week
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week,
     *                                       if not provided, start of week is inferred from the locale
     *                                       (Sunday for en_US, Monday for de_DE, etc.)
     */
    public function setDaysFromStartOfWeek(int $numberOfDays, WeekDay|int|null $weekStartsAt = null): static;

    /**
     * Set the fallback locale.
     *
     * @see https://symfony.com/doc/current/components/translation.html#fallback-locales
     *
     * @param string $locale
     */
    public static function setFallbackLocale(string $locale): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     */
    public static function setHumanDiffOptions(int $humanDiffOptions): void;

    /**
     * Set a date according to the ISO 8601 standard - using weeks and day offsets rather than specific dates.
     *
     * @see https://php.net/manual/en/datetime.setisodate.php
     */
    public function setISODate(int $year, int $week, int $day = 1): static;

    /**
     * Set the translator for the current instance.
     */
    public function setLocalTranslator(TranslatorInterface $translator);

    /**
     * Set the current translator locale and indicate if the source locale file exists.
     * Pass 'auto' as locale to use the closest language to the current LC_TIME locale.
     *
     * @param string $locale locale ex. en
     */
    public static function setLocale(string $locale): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather consider mid-day is always 12pm, then if you need to test if it's an other
     *             hour, test it explicitly:
     *                 $date->format('G') == 13
     *             or to set explicitly to a given hour:
     *                 $date->setTime(13, 0, 0, 0)
     *
     * Set midday/noon hour
     *
     * @param int $hour midday hour
     *
     * @return void
     */
    public static function setMidDayAt($hour);

    /**
     * Set a Carbon instance (real or mock) to be returned when a "now"
     * instance is created.  The provided instance will be returned
     * specifically under the following conditions:
     *   - A call to the static now() method, ex. Carbon::now()
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
     *   - When a string containing the desired time is passed to Carbon::parse().
     *
     * Note the timezone parameter was left out of the examples above and
     * has no affect as the mock value will be returned regardless of its value.
     *
     * Only the moment is mocked with setTestNow(), the timezone will still be the one passed
     * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()).
     *
     * To clear the test instance call this method using the default
     * parameter of null.
     *
     * /!\ Use this method for unit tests only.
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
     */
    public static function setTestNow(mixed $testNow = null): void;

    /**
     * Set a Carbon instance (real or mock) to be returned when a "now"
     * instance is created.  The provided instance will be returned
     * specifically under the following conditions:
     *   - A call to the static now() method, ex. Carbon::now()
     *   - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
     *   - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
     *   - When a string containing the desired time is passed to Carbon::parse().
     *
     * It will also align default timezone (e.g. call date_default_timezone_set()) with
     * the second argument or if null, with the timezone of the given date object.
     *
     * To clear the test instance call this method using the default
     * parameter of null.
     *
     * /!\ Use this method for unit tests only.
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance
     */
    public static function setTestNowAndTimezone($testNow = null, $timezone = null): void;

    /**
     * Resets the current time of the DateTime object to a different time.
     *
     * @see https://php.net/manual/en/datetime.settime.php
     */
    public function setTime(int $hour, int $minute, int $second = 0, int $microseconds = 0): static;

    /**
     * Set the hour, minute, second and microseconds for this instance to that of the passed instance.
     */
    public function setTimeFrom(DateTimeInterface|string $date): static;

    /**
     * Set the time by time string.
     */
    public function setTimeFromTimeString(string $time): static;

    /**
     * Set the instance's timestamp.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public function setTimestamp(string|int|float $timestamp): static;

    /**
     * Set the instance's timezone from a string or object.
     */
    public function setTimezone(DateTimeZone|string|int $timeZone): static;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather let Carbon object being cast to string with DEFAULT_TO_STRING_FORMAT, and
     *             use other method or custom format passed to format() method if you need to dump another string
     *             format.
     *
     * Set the default format used when type juggling a Carbon instance to a string.
     *
     * @param string|Closure|null $format
     *
     * @return void
     */
    public static function setToStringFormat(Closure|string|null $format): void;

    /**
     * Set the default translator instance to use.
     *
     * @param TranslatorInterface $translator
     *
     * @return void
     */
    public static function setTranslator(TranslatorInterface $translator): void;

    /**
     * Set specified unit to new given value.
     *
     * @param string    $unit  year, month, day, hour, minute, second or microsecond
     * @param Month|int $value new value for given unit
     */
    public function setUnit(string $unit, Month|int|float|null $value = null): static;

    /**
     * Set any unit to a new value without overflowing current other unit given.
     *
     * @param string $valueUnit    unit name to modify
     * @param int    $value        new value for the input unit
     * @param string $overflowUnit unit name to not overflow
     */
    public function setUnitNoOverflow(string $valueUnit, int $value, string $overflowUnit): static;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather consider week-end is always saturday and sunday, and if you have some custom
     *             week-end days to handle, give to those days an other name and create a macro for them:
     *
     *             ```
     *             Carbon::macro('isDayOff', function ($date) {
     *                 return $date->isSunday() || $date->isMonday();
     *             });
     *             Carbon::macro('isNotDayOff', function ($date) {
     *                 return !$date->isDayOff();
     *             });
     *             if ($someDate->isDayOff()) ...
     *             if ($someDate->isNotDayOff()) ...
     *             // Add 5 not-off days
     *             $count = 5;
     *             while ($someDate->isDayOff() || ($count-- > 0)) {
     *                 $someDate->addDay();
     *             }
     *             ```
     *
     * Set weekend days
     */
    public static function setWeekendDays(array $days): void;

    /**
     * Set specific options.
     *  - strictMode: true|false|null
     *  - monthOverflow: true|false|null
     *  - yearOverflow: true|false|null
     *  - humanDiffOptions: int|null
     *  - toStringFormat: string|Closure|null
     *  - toJsonFormat: string|Closure|null
     *  - locale: string|null
     *  - timezone: \DateTimeZone|string|int|null
     *  - macros: array|null
     *  - genericMacros: array|null
     *
     * @param array $settings
     *
     * @return $this|static
     */
    public function settings(array $settings): static;

    /**
     * Set the instance's timezone from a string or object and add/subtract the offset difference.
     */
    public function shiftTimezone(DateTimeZone|string $value): static;

    /**
     * Get the month overflow global behavior (can be overridden in specific instances).
     *
     * @return bool
     */
    public static function shouldOverflowMonths(): bool;

    /**
     * Get the month overflow global behavior (can be overridden in specific instances).
     *
     * @return bool
     */
    public static function shouldOverflowYears(): bool;

    /**
     * @alias diffForHumans
     *
     * Get the difference in a human readable format in the current locale from current instance to an other
     * instance given (or now if null given).
     */
    public function since($other = null, $syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * Returns standardized singular of a given singular/plural unit name (in English).
     */
    public static function singularUnit(string $unit): string;

    public static function sleep(int|float $seconds): void;

    /**
     * Modify to start of current given unit.
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOf(Unit::Month)
     *   ->endOf(Unit::Week, Carbon::FRIDAY);
     * ```
     */
    public function startOf(Unit|string $unit, mixed ...$params): static;

    /**
     * Resets the date to the first day of the century and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfCentury();
     * ```
     *
     * @return static
     */
    public function startOfCentury();

    /**
     * Resets the time to 00:00:00 start of day
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfDay();
     * ```
     *
     * @return static
     */
    public function startOfDay();

    /**
     * Resets the date to the first day of the decade and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfDecade();
     * ```
     *
     * @return static
     */
    public function startOfDecade();

    /**
     * Modify to start of current hour, minutes and seconds become 0
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfHour();
     * ```
     */
    public function startOfHour(): static;

    /**
     * Resets the date to the first day of the millennium and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfMillennium();
     * ```
     *
     * @return static
     */
    public function startOfMillennium();

    /**
     * Modify to start of current millisecond, microseconds such as 12345 become 123000
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function startOfMillisecond(): static;

    /**
     * Modify to start of current minute, seconds become 0
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfMinute();
     * ```
     */
    public function startOfMinute(): static;

    /**
     * Resets the date to the first day of the month and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfMonth();
     * ```
     *
     * @return static
     */
    public function startOfMonth();

    /**
     * Resets the date to the first day of the quarter and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfQuarter();
     * ```
     *
     * @return static
     */
    public function startOfQuarter();

    /**
     * Modify to start of current second, microseconds become 0
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16.334455')
     *   ->startOfSecond()
     *   ->format('H:i:s.u');
     * ```
     */
    public function startOfSecond(): static;

    /**
     * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->locale('ar')->startOfWeek() . "\n";
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfWeek(Carbon::SUNDAY) . "\n";
     * ```
     *
     * @param WeekDay|int|null $weekStartsAt optional start allow you to specify the day of week to use to start the week
     *
     * @return static
     */
    public function startOfWeek(WeekDay|int|null $weekStartsAt = null): static;

    /**
     * Resets the date to the first day of the year and the time to 00:00:00
     *
     * @example
     * ```
     * echo Carbon::parse('2018-07-25 12:45:16')->startOfYear();
     * ```
     *
     * @return static
     */
    public function startOfYear();

    /**
     * Subtract given units or interval to the current instance.
     *
     * @example $date->sub('hour', 3)
     * @example $date->sub(15, 'days')
     * @example $date->sub(CarbonInterval::days(4))
     *
     * @param Unit|int|string|DateInterval|Closure|CarbonConverterInterface $unit
     * @param Unit|int|float|string                                         $value
     * @param bool|null                                                     $overflow
     *
     * @return static
     */
    #[ReturnTypeWillChange]
    public function sub($unit, $value = 1, ?bool $overflow = null): static;

    /**
     * @deprecated Prefer to use add subUTCUnit() which more accurately defines what it's doing.
     *
     * Subtract seconds to the instance using timestamp. Positive $value travels
     * into the past while negative $value travels forward.
     *
     * @param string $unit
     * @param int    $value
     *
     * @return static
     */
    public function subRealUnit($unit, $value = 1): static;

    /**
     * Subtract seconds to the instance using timestamp. Positive $value travels
     * into the past while negative $value travels forward.
     *
     * @param string $unit
     * @param int    $value
     *
     * @return static
     */
    public function subUTCUnit($unit, $value = 1): static;

    /**
     * Subtract given units to the current instance.
     */
    public function subUnit(Unit|string $unit, $value = 1, ?bool $overflow = null): static;

    /**
     * Subtract any unit to a new value without overflowing current other unit given.
     *
     * @param string $valueUnit    unit name to modify
     * @param int    $value        amount to subtract to the input unit
     * @param string $overflowUnit unit name to not overflow
     */
    public function subUnitNoOverflow(string $valueUnit, int $value, string $overflowUnit): static;

    /**
     * Subtract given units or interval to the current instance.
     *
     * @see sub()
     *
     * @param Unit|int|string|DateInterval $unit
     * @param Unit|int|float|string        $value
     * @param bool|null                    $overflow
     *
     * @return static
     */
    public function subtract($unit, $value = 1, ?bool $overflow = null): static;

    /**
     * Get the difference in a human-readable format in the current locale from current instance to another
     * instance given (or now if null given).
     *
     * @return string
     */
    public function timespan($other = null, $timezone = null): string;

    /**
     * Set the instance's timestamp.
     *
     * Timestamp input can be given as int, float or a string containing one or more numbers.
     */
    public function timestamp(string|int|float $timestamp): static;

    /**
     * @alias setTimezone
     */
    public function timezone(DateTimeZone|string|int $value): static;

    /**
     * Get the difference in a human readable format in the current locale from an other
     * instance given (or now if null given) to current instance.
     *
     * When comparing a value in the past to default now:
     * 1 hour from now
     * 5 months from now
     *
     * When comparing a value in the future to default now:
     * 1 hour ago
     * 5 months ago
     *
     * When comparing a value in the past to another value:
     * 1 hour after
     * 5 months after
     *
     * When comparing a value in the future to another value:
     * 1 hour before
     * 5 months before
     *
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                             if null passed, now will be used as comparison reference;
     *                                                             if any other type, it will be converted to date and used as reference.
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                             - 'syntax' entry (see below)
     *                                                             - 'short' entry (see below)
     *                                                             - 'parts' entry (see below)
     *                                                             - 'options' entry (see below)
     *                                                             - 'join' entry determines how to join multiple parts of the string
     *                                                             `  - if $join is a string, it's used as a joiner glue
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                             `    will be used instead of the glue for the last item
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                             `  - if $join is missing, a space will be used as glue
     *                                                             - 'other' entry (see above)
     *                                                             if int passed, it add modifiers:
     *                                                             Possible values:
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                        $short   displays short format of time units
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                         $options human diff options
     *
     * @return string
     */
    public function to($other = null, $syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * Get default array representation.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toArray());
     * ```
     */
    public function toArray(): array;

    /**
     * Format the instance as ATOM
     *
     * @example
     * ```
     * echo Carbon::now()->toAtomString();
     * ```
     */
    public function toAtomString(): string;

    /**
     * Format the instance as COOKIE
     *
     * @example
     * ```
     * echo Carbon::now()->toCookieString();
     * ```
     */
    public function toCookieString(): string;

    /**
     * @alias toDateTime
     *
     * Return native DateTime PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDate());
     * ```
     */
    public function toDate(): DateTime;

    /**
     * Format the instance as date
     *
     * @example
     * ```
     * echo Carbon::now()->toDateString();
     * ```
     */
    public function toDateString(): string;

    /**
     * Return native DateTime PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDateTime());
     * ```
     */
    public function toDateTime(): DateTime;

    /**
     * Return native toDateTimeImmutable PHP object matching the current instance.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toDateTimeImmutable());
     * ```
     */
    public function toDateTimeImmutable(): DateTimeImmutable;

    /**
     * Format the instance as date and time T-separated with no timezone
     *
     * @example
     * ```
     * echo Carbon::now()->toDateTimeLocalString();
     * echo "\n";
     * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond
     * ```
     */
    public function toDateTimeLocalString(string $unitPrecision = 'second'): string;

    /**
     * Format the instance as date and time
     *
     * @example
     * ```
     * echo Carbon::now()->toDateTimeString();
     * ```
     */
    public function toDateTimeString(string $unitPrecision = 'second'): string;

    /**
     * Format the instance with day, date and time
     *
     * @example
     * ```
     * echo Carbon::now()->toDayDateTimeString();
     * ```
     */
    public function toDayDateTimeString(): string;

    /**
     * Format the instance as a readable date
     *
     * @example
     * ```
     * echo Carbon::now()->toFormattedDateString();
     * ```
     */
    public function toFormattedDateString(): string;

    /**
     * Format the instance with the day, and a readable date
     *
     * @example
     * ```
     * echo Carbon::now()->toFormattedDayDateString();
     * ```
     */
    public function toFormattedDayDateString(): string;

    /**
     * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
     * 1977-04-22T01:00:00-05:00).
     *
     * @example
     * ```
     * echo Carbon::now('America/Toronto')->toISOString() . "\n";
     * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
     * ```
     *
     * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
     */
    public function toISOString(bool $keepOffset = false): ?string;

    /**
     * Return a immutable copy of the instance.
     *
     * @return CarbonImmutable
     */
    public function toImmutable();

    /**
     * Format the instance as ISO8601
     *
     * @example
     * ```
     * echo Carbon::now()->toIso8601String();
     * ```
     */
    public function toIso8601String(): string;

    /**
     * Convert the instance to UTC and return as Zulu ISO8601
     *
     * @example
     * ```
     * echo Carbon::now()->toIso8601ZuluString();
     * ```
     */
    public function toIso8601ZuluString(string $unitPrecision = 'second'): string;

    /**
     * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
     *
     * @example
     * ```
     * echo Carbon::now('America/Toronto')->toJSON();
     * ```
     */
    public function toJSON(): ?string;

    /**
     * Return a mutable copy of the instance.
     *
     * @return Carbon
     */
    public function toMutable();

    /**
     * Get the difference in a human readable format in the current locale from an other
     * instance given to now
     *
     * @param int|array $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                           - 'syntax' entry (see below)
     *                           - 'short' entry (see below)
     *                           - 'parts' entry (see below)
     *                           - 'options' entry (see below)
     *                           - 'join' entry determines how to join multiple parts of the string
     *                           `  - if $join is a string, it's used as a joiner glue
     *                           `  - if $join is a callable/closure, it get the list of string and should return a string
     *                           `  - if $join is an array, the first item will be the default glue, and the second item
     *                           `    will be used instead of the glue for the last item
     *                           `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                           `  - if $join is missing, a space will be used as glue
     *                           if int passed, it add modifiers:
     *                           Possible values:
     *                           - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                           - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                           - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                           Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool      $short   displays short format of time units
     * @param int       $parts   maximum number of parts to display (default value: 1: single part)
     * @param int       $options human diff options
     *
     * @return string
     */
    public function toNow($syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * Get default object representation.
     *
     * @example
     * ```
     * var_dump(Carbon::now()->toObject());
     * ```
     */
    public function toObject(): object;

    /**
     * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
     *
     * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end      period end date or recurrences count if int
     * @param int|\DateInterval|string|null                      $interval period default interval or number of the given $unit
     * @param string|null                                        $unit     if specified, $interval must be an integer
     */
    public function toPeriod($end = null, $interval = null, $unit = null): CarbonPeriod;

    /**
     * Format the instance as RFC1036
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc1036String();
     * ```
     */
    public function toRfc1036String(): string;

    /**
     * Format the instance as RFC1123
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc1123String();
     * ```
     */
    public function toRfc1123String(): string;

    /**
     * Format the instance as RFC2822
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc2822String();
     * ```
     */
    public function toRfc2822String(): string;

    /**
     * Format the instance as RFC3339.
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc3339String() . "\n";
     * echo Carbon::now()->toRfc3339String(true) . "\n";
     * ```
     */
    public function toRfc3339String(bool $extended = false): string;

    /**
     * Format the instance as RFC7231
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc7231String();
     * ```
     */
    public function toRfc7231String(): string;

    /**
     * Format the instance as RFC822
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc822String();
     * ```
     */
    public function toRfc822String(): string;

    /**
     * Format the instance as RFC850
     *
     * @example
     * ```
     * echo Carbon::now()->toRfc850String();
     * ```
     */
    public function toRfc850String(): string;

    /**
     * Format the instance as RSS
     *
     * @example
     * ```
     * echo Carbon::now()->toRssString();
     * ```
     */
    public function toRssString(): string;

    /**
     * Returns english human-readable complete date string.
     *
     * @example
     * ```
     * echo Carbon::now()->toString();
     * ```
     */
    public function toString(): string;

    /**
     * Format the instance as time
     *
     * @example
     * ```
     * echo Carbon::now()->toTimeString();
     * ```
     */
    public function toTimeString(string $unitPrecision = 'second'): string;

    /**
     * Format the instance as W3C
     *
     * @example
     * ```
     * echo Carbon::now()->toW3cString();
     * ```
     */
    public function toW3cString(): string;

    /**
     * Create a Carbon instance for today.
     */
    public static function today(DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Create a Carbon instance for tomorrow.
     */
    public static function tomorrow(DateTimeZone|string|int|null $timezone = null): static;

    /**
     * Translate using translation string or callback available.
     *
     * @param string                   $key        key to find
     * @param array                    $parameters replacement parameters
     * @param string|int|float|null    $number     number if plural
     * @param TranslatorInterface|null $translator an optional translator to use
     * @param bool                     $altNumbers pass true to use alternative numbers
     *
     * @return string
     */
    public function translate(string $key, array $parameters = [], string|int|float|null $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string;

    /**
     * Returns the alternative number for a given integer if available in the current locale.
     *
     * @param int $number
     *
     * @return string
     */
    public function translateNumber(int $number): string;

    /**
     * Translate a time string from a locale to an other.
     *
     * @param string      $timeString date/time/duration string to translate (may also contain English)
     * @param string|null $from       input locale of the $timeString parameter (`Carbon::getLocale()` by default)
     * @param string|null $to         output locale of the result returned (`"en"` by default)
     * @param int         $mode       specify what to translate with options:
     *                                - self::TRANSLATE_ALL (default)
     *                                - CarbonInterface::TRANSLATE_MONTHS
     *                                - CarbonInterface::TRANSLATE_DAYS
     *                                - CarbonInterface::TRANSLATE_UNITS
     *                                - CarbonInterface::TRANSLATE_MERIDIEM
     *                                You can use pipe to group: CarbonInterface::TRANSLATE_MONTHS | CarbonInterface::TRANSLATE_DAYS
     *
     * @return string
     */
    public static function translateTimeString(string $timeString, ?string $from = null, ?string $to = null, int $mode = self::TRANSLATE_ALL): string;

    /**
     * Translate a time string from the current locale (`$date->locale()`) to another one.
     *
     * @param string      $timeString time string to translate
     * @param string|null $to         output locale of the result returned ("en" by default)
     *
     * @return string
     */
    public function translateTimeStringTo(string $timeString, ?string $to = null): string;

    /**
     * Translate using translation string or callback available.
     *
     * @param TranslatorInterface $translator an optional translator to use
     * @param string              $key        key to find
     * @param array               $parameters replacement parameters
     * @param int|float|null      $number     number if plural
     *
     * @return string
     */
    public static function translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string;

    /**
     * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
     * but translate words whenever possible (months, day names, etc.) using the current locale.
     */
    public function translatedFormat(string $format): string;

    /**
     * Set the timezone or returns the timezone name if no arguments passed.
     *
     * @return ($value is null ? string : static)
     */
    public function tz(DateTimeZone|string|int|null $value = null): static|string;

    /**
     * @alias getTimestamp
     *
     * Returns the UNIX timestamp for the current date.
     *
     * @return int
     */
    public function unix(): int;

    /**
     * @alias to
     *
     * Get the difference in a human readable format in the current locale from an other
     * instance given (or now if null given) to current instance.
     *
     * @param Carbon|\DateTimeInterface|string|array|null $other   if array passed, will be used as parameters array, see $syntax below;
     *                                                             if null passed, now will be used as comparison reference;
     *                                                             if any other type, it will be converted to date and used as reference.
     * @param int|array                                   $syntax  if array passed, parameters will be extracted from it, the array may contains:
     *                                                             - 'syntax' entry (see below)
     *                                                             - 'short' entry (see below)
     *                                                             - 'parts' entry (see below)
     *                                                             - 'options' entry (see below)
     *                                                             - 'join' entry determines how to join multiple parts of the string
     *                                                             `  - if $join is a string, it's used as a joiner glue
     *                                                             `  - if $join is a callable/closure, it get the list of string and should return a string
     *                                                             `  - if $join is an array, the first item will be the default glue, and the second item
     *                                                             `    will be used instead of the glue for the last item
     *                                                             `  - if $join is true, it will be guessed from the locale ('list' translation file entry)
     *                                                             `  - if $join is missing, a space will be used as glue
     *                                                             - 'other' entry (see above)
     *                                                             if int passed, it add modifiers:
     *                                                             Possible values:
     *                                                             - CarbonInterface::DIFF_ABSOLUTE          no modifiers
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_NOW   add ago/from now modifier
     *                                                             - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
     *                                                             Default value: CarbonInterface::DIFF_ABSOLUTE
     * @param bool                                        $short   displays short format of time units
     * @param int                                         $parts   maximum number of parts to display (default value: 1: single unit)
     * @param int                                         $options human diff options
     *
     * @return string
     */
    public function until($other = null, $syntax = null, $short = false, $parts = 1, $options = null);

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Indicates if months should be calculated with overflow.
     *
     * @param bool $monthsOverflow
     *
     * @return void
     */
    public static function useMonthsOverflow(bool $monthsOverflow = true): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     * @see settings
     *
     * Enable the strict mode (or disable with passing false).
     *
     * @param bool $strictModeEnabled
     */
    public static function useStrictMode(bool $strictModeEnabled = true): void;

    /**
     * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
     *             You should rather use the ->settings() method.
     *             Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
     *             are available for quarters, years, decade, centuries, millennia (singular and plural forms).
     * @see settings
     *
     * Indicates if years should be calculated with overflow.
     *
     * @param bool $yearsOverflow
     *
     * @return void
     */
    public static function useYearsOverflow(bool $yearsOverflow = true): void;

    /**
     * Set the instance's timezone to UTC.
     */
    public function utc(): static;

    /**
     * Returns the minutes offset to UTC if no arguments passed, else set the timezone with given minutes shift passed.
     */
    public function utcOffset(?int $minuteOffset = null): static|int;

    /**
     * Returns the milliseconds timestamps used amongst other by Date javascript objects.
     *
     * @return float
     */
    public function valueOf(): float;

    /**
     * Get/set the week number using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $week
     * @param int|null $dayOfWeek
     * @param int|null $dayOfYear
     *
     * @return int|static
     */
    public function week($week = null, $dayOfWeek = null, $dayOfYear = null);

    /**
     * Set/get the week number of year using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $year      if null, act as a getter, if not null, set the year and return current instance.
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int|static
     */
    public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null);

    /**
     * Get/set the weekday from 0 (Sunday) to 6 (Saturday).
     *
     * @param WeekDay|int|null $value new value for weekday if using as setter.
     */
    public function weekday(WeekDay|int|null $value = null): static|int;

    /**
     * Get the number of weeks of the current week-year using given first day of week and first
     * day of year included in the first week. Or use US format if no settings
     * given (Sunday / Jan 6).
     *
     * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday)
     * @param int|null $dayOfYear first day of year included in the week #1
     *
     * @return int
     */
    public function weeksInYear($dayOfWeek = null, $dayOfYear = null);

    /**
     * Temporarily sets a static date to be used within the callback.
     * Using setTestNow to set the date, executing the callback, then
     * clearing the test instance.
     *
     * /!\ Use this method for unit tests only.
     *
     * @template T
     *
     * @param DateTimeInterface|Closure|static|string|false|null $testNow  real or mock Carbon instance
     * @param Closure(): T                                       $callback
     *
     * @return T
     */
    public static function withTestNow(mixed $testNow, callable $callback): mixed;

    /**
     * Create a Carbon instance for yesterday.
     */
    public static function yesterday(DateTimeZone|string|int|null $timezone = null): static;

    // </methods>
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidPeriodParameterException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use RuntimeException as BaseRuntimeException;
use Throwable;

class ImmutableException extends BaseRuntimeException implements RuntimeException
{
    /**
     * The value.
     *
     * @var string
     */
    protected $value;

    /**
     * Constructor.
     *
     * @param string         $value    the immutable type/value
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($value, $code = 0, ?Throwable $previous = null)
    {
        $this->value = $value;
        parent::__construct("$value is immutable.", $code, $previous);
    }

    /**
     * Get the value.
     *
     * @return string
     */
    public function getValue(): string
    {
        return $this->value;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidFormatException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidCastException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

class InvalidDateException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    /**
     * The invalid field.
     *
     * @var string
     */
    private $field;

    /**
     * The invalid value.
     *
     * @var mixed
     */
    private $value;

    /**
     * Constructor.
     *
     * @param string         $field
     * @param mixed          $value
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($field, $value, $code = 0, ?Throwable $previous = null)
    {
        $this->field = $field;
        $this->value = $value;
        parent::__construct($field.' : '.$value.' is not a valid value.', $code, $previous);
    }

    /**
     * Get the invalid field.
     *
     * @return string
     */
    public function getField()
    {
        return $this->field;
    }

    /**
     * Get the invalid value.
     *
     * @return mixed
     */
    public function getValue()
    {
        return $this->value;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use Throwable;

class UnknownUnitException extends UnitException
{
    /**
     * The unit.
     *
     * @var string
     */
    protected $unit;

    /**
     * Constructor.
     *
     * @param string         $unit
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($unit, $code = 0, ?Throwable $previous = null)
    {
        $this->unit = $unit;

        parent::__construct("Unknown unit '$unit'.", $code, $previous);
    }

    /**
     * Get the unit.
     *
     * @return string
     */
    public function getUnit(): string
    {
        return $this->unit;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use RuntimeException as BaseRuntimeException;

class UnreachableException extends BaseRuntimeException implements RuntimeException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use BadMethodCallException as BaseBadMethodCallException;
use Throwable;

class BadFluentSetterException extends BaseBadMethodCallException implements BadMethodCallException
{
    /**
     * The setter.
     *
     * @var string
     */
    protected $setter;

    /**
     * Constructor.
     *
     * @param string         $setter
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($setter, $code = 0, ?Throwable $previous = null)
    {
        $this->setter = $setter;

        parent::__construct(\sprintf("Unknown fluent setter '%s'", $setter), $code, $previous);
    }

    /**
     * Get the setter.
     *
     * @return string
     */
    public function getSetter(): string
    {
        return $this->setter;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidIntervalException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidPeriodDateException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

interface BadMethodCallException extends Exception
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidTypeException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use Throwable;

class BadComparisonUnitException extends UnitException
{
    /**
     * The unit.
     *
     * @var string
     */
    protected $unit;

    /**
     * Constructor.
     *
     * @param string         $unit
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($unit, $code = 0, ?Throwable $previous = null)
    {
        $this->unit = $unit;

        parent::__construct("Bad comparison unit: '$unit'", $code, $previous);
    }

    /**
     * Get the unit.
     *
     * @return string
     */
    public function getUnit(): string
    {
        return $this->unit;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

interface Exception
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class InvalidTimeZoneException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

interface InvalidArgumentException extends Exception
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use BadMethodCallException as BaseBadMethodCallException;
use Throwable;

class UnknownMethodException extends BaseBadMethodCallException implements BadMethodCallException
{
    /**
     * The method.
     *
     * @var string
     */
    protected $method;

    /**
     * Constructor.
     *
     * @param string         $method
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($method, $code = 0, ?Throwable $previous = null)
    {
        $this->method = $method;

        parent::__construct("Method $method does not exist.", $code, $previous);
    }

    /**
     * Get the method.
     *
     * @return string
     */
    public function getMethod(): string
    {
        return $this->method;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

class NotLocaleAwareException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    /**
     * Constructor.
     *
     * @param mixed          $object
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($object, $code = 0, ?Throwable $previous = null)
    {
        $dump = \is_object($object) ? \get_class($object) : \gettype($object);

        parent::__construct("$dump does neither implements Symfony\Contracts\Translation\LocaleAwareInterface nor getLocale() method.", $code, $previous);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use Carbon\CarbonInterface;
use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

class NotACarbonClassException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    /**
     * The className.
     *
     * @var string
     */
    protected $className;

    /**
     * Constructor.
     *
     * @param string         $className
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($className, $code = 0, ?Throwable $previous = null)
    {
        $this->className = $className;

        parent::__construct(\sprintf(
            'Given class does not implement %s: %s',
            CarbonInterface::class,
            $className,
        ), $code, $previous);
    }

    /**
     * Get the className.
     *
     * @return string
     */
    public function getClassName(): string
    {
        return $this->className;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

// This will extends OutOfRangeException instead of InvalidArgumentException since 3.0.0
// use OutOfRangeException as BaseOutOfRangeException;

class OutOfRangeException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    /**
     * The unit or name of the value.
     *
     * @var string
     */
    private $unit;

    /**
     * The range minimum.
     *
     * @var mixed
     */
    private $min;

    /**
     * The range maximum.
     *
     * @var mixed
     */
    private $max;

    /**
     * The invalid value.
     *
     * @var mixed
     */
    private $value;

    /**
     * Constructor.
     *
     * @param string         $unit
     * @param mixed          $min
     * @param mixed          $max
     * @param mixed          $value
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($unit, $min, $max, $value, $code = 0, ?Throwable $previous = null)
    {
        $this->unit = $unit;
        $this->min = $min;
        $this->max = $max;
        $this->value = $value;

        parent::__construct("$unit must be between $min and $max, $value given", $code, $previous);
    }

    /**
     * @return mixed
     */
    public function getMax()
    {
        return $this->max;
    }

    /**
     * @return mixed
     */
    public function getMin()
    {
        return $this->min;
    }

    /**
     * @return mixed
     */
    public function getUnit()
    {
        return $this->unit;
    }

    /**
     * @return mixed
     */
    public function getValue()
    {
        return $this->value;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class NotAPeriodException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use RuntimeException as BaseRuntimeException;

final class EndLessPeriodException extends BaseRuntimeException implements RuntimeException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;

class UnitException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

class UnknownSetterException extends BaseInvalidArgumentException implements BadMethodCallException
{
    /**
     * The setter.
     *
     * @var string
     */
    protected $setter;

    /**
     * Constructor.
     *
     * @param string         $setter   setter name
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($setter, $code = 0, ?Throwable $previous = null)
    {
        $this->setter = $setter;

        parent::__construct("Unknown setter '$setter'", $code, $previous);
    }

    /**
     * Get the setter.
     *
     * @return string
     */
    public function getSetter(): string
    {
        return $this->setter;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

class ParseErrorException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    /**
     * The expected.
     *
     * @var string
     */
    protected $expected;

    /**
     * The actual.
     *
     * @var string
     */
    protected $actual;

    /**
     * The help message.
     *
     * @var string
     */
    protected $help;

    /**
     * Constructor.
     *
     * @param string         $expected
     * @param string         $actual
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($expected, $actual, $help = '', $code = 0, ?Throwable $previous = null)
    {
        $this->expected = $expected;
        $this->actual = $actual;
        $this->help = $help;

        $actual = $actual === '' ? 'data is missing' : "get '$actual'";

        parent::__construct(trim("Format expected $expected but $actual\n$help"), $code, $previous);
    }

    /**
     * Get the expected.
     *
     * @return string
     */
    public function getExpected(): string
    {
        return $this->expected;
    }

    /**
     * Get the actual.
     *
     * @return string
     */
    public function getActual(): string
    {
        return $this->actual;
    }

    /**
     * Get the help message.
     *
     * @return string
     */
    public function getHelp(): string
    {
        return $this->help;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use InvalidArgumentException as BaseInvalidArgumentException;
use Throwable;

class UnknownGetterException extends BaseInvalidArgumentException implements InvalidArgumentException
{
    /**
     * The getter.
     *
     * @var string
     */
    protected $getter;

    /**
     * Constructor.
     *
     * @param string         $getter   getter name
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($getter, $code = 0, ?Throwable $previous = null)
    {
        $this->getter = $getter;

        parent::__construct("Unknown getter '$getter'", $code, $previous);
    }

    /**
     * Get the getter.
     *
     * @return string
     */
    public function getGetter(): string
    {
        return $this->getter;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use Exception;

/**
 * @codeCoverageIgnore
 */
class UnsupportedUnitException extends UnitException
{
    public function __construct(string $unit, int $code = 0, ?Exception $previous = null)
    {
        parent::__construct("Unsupported unit '$unit'", $code, $previous);
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

interface RuntimeException extends Exception
{
    //
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use BadMethodCallException as BaseBadMethodCallException;
use Throwable;

class BadFluentConstructorException extends BaseBadMethodCallException implements BadMethodCallException
{
    /**
     * The method.
     *
     * @var string
     */
    protected $method;

    /**
     * Constructor.
     *
     * @param string         $method
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($method, $code = 0, ?Throwable $previous = null)
    {
        $this->method = $method;

        parent::__construct(\sprintf("Unknown fluent constructor '%s'.", $method), $code, $previous);
    }

    /**
     * Get the method.
     *
     * @return string
     */
    public function getMethod(): string
    {
        return $this->method;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\Exceptions;

use Throwable;

class UnitNotConfiguredException extends UnitException
{
    /**
     * The unit.
     *
     * @var string
     */
    protected $unit;

    /**
     * Constructor.
     *
     * @param string         $unit
     * @param int            $code
     * @param Throwable|null $previous
     */
    public function __construct($unit, $code = 0, ?Throwable $previous = null)
    {
        $this->unit = $unit;

        parent::__construct("Unit $unit have no configuration to get total from other units.", $code, $previous);
    }

    /**
     * Get the unit.
     *
     * @return string
     */
    public function getUnit(): string
    {
        return $this->unit;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\PHPStan;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Type;

use function preg_match;

class MacroMethodReflection implements MethodReflection
{
    private ClassReflection $declaringClass;
    private string $methodName;
    private ParametersAcceptor $macroClosureType;
    private bool $static;
    private bool $final;
    private bool $deprecated;
    private ?string $docComment;

    public function __construct(
        ClassReflection $declaringClass,
        string $methodName,
        ParametersAcceptor $macroClosureType,
        bool $static,
        bool $final,
        bool $deprecated,
        ?string $docComment
    ) {
        $this->declaringClass = $declaringClass;
        $this->methodName = $methodName;
        $this->macroClosureType = $macroClosureType;
        $this->static = $static;
        $this->final = $final;
        $this->deprecated = $deprecated;
        $this->docComment = $docComment;
    }

    public function getDeclaringClass(): ClassReflection
    {
        return $this->declaringClass;
    }

    public function isStatic(): bool
    {
        return $this->static;
    }

    public function isPrivate(): bool
    {
        return false;
    }

    public function isPublic(): bool
    {
        return true;
    }

    public function getDocComment(): ?string
    {
        return $this->docComment;
    }

    public function getName(): string
    {
        return $this->methodName;
    }

    public function getPrototype(): \PHPStan\Reflection\ClassMemberReflection
    {
        return $this;
    }

    public function getVariants(): array
    {
        return [$this->macroClosureType];
    }

    public function isDeprecated(): TrinaryLogic
    {
        return TrinaryLogic::createFromBoolean(
            $this->deprecated ||
            preg_match('/@deprecated/i', $this->getDocComment() ?: '')
        );
    }

    public function getDeprecatedDescription(): ?string
    {
        return null;
    }

    public function isFinal(): TrinaryLogic
    {
        return TrinaryLogic::createFromBoolean($this->final);
    }

    public function isInternal(): TrinaryLogic
    {
        return TrinaryLogic::createNo();
    }

    public function getThrowType(): ?Type
    {
        return null;
    }

    public function hasSideEffects(): TrinaryLogic
    {
        return TrinaryLogic::createMaybe();
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon\PHPStan;

use Carbon\CarbonInterface;
use Carbon\FactoryImmutable;
use Closure;
use InvalidArgumentException;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ClosureTypeFactory;
use ReflectionFunction;
use ReflectionMethod;
use stdClass;
use Throwable;

/**
 * Class MacroExtension.
 *
 * @codeCoverageIgnore Pure PHPStan wrapper.
 */
final class MacroExtension implements MethodsClassReflectionExtension
{
    /**
     * @var ReflectionProvider
     */
    protected $reflectionProvider;

    /**
     * @var ClosureTypeFactory
     */
    protected $closureTypeFactory;

    /**
     * Extension constructor.
     *
     * @param ReflectionProvider $reflectionProvider
     * @param ClosureTypeFactory $closureTypeFactory
     */
    public function __construct(
        ReflectionProvider $reflectionProvider,
        ClosureTypeFactory $closureTypeFactory
    ) {
        $this->reflectionProvider = $reflectionProvider;
        $this->closureTypeFactory = $closureTypeFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function hasMethod(ClassReflection $classReflection, string $methodName): bool
    {
        if (
            $classReflection->getName() !== CarbonInterface::class &&
            !$classReflection->isSubclassOf(CarbonInterface::class)
        ) {
            return false;
        }

        $className = $classReflection->getName();

        return \is_callable([$className, 'hasMacro']) &&
            $className::hasMacro($methodName);
    }

    /**
     * {@inheritdoc}
     */
    public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
    {
        $macros = FactoryImmutable::getDefaultInstance()->getSettings()['macros'] ?? [];
        $macro = $macros[$methodName] ?? throw new InvalidArgumentException("Macro '$methodName' not found");
        $static = false;
        $final = false;
        $deprecated = false;
        $docComment = null;

        if (\is_array($macro) && \count($macro) === 2 && \is_string($macro[1])) {
            \assert($macro[1] !== '');

            $reflection = new ReflectionMethod($macro[0], $macro[1]);
            $closure = \is_object($macro[0]) ? $reflection->getClosure($macro[0]) : $reflection->getClosure();

            $static = $reflection->isStatic();
            $final = $reflection->isFinal();
            $deprecated = $reflection->isDeprecated();
            $docComment = $reflection->getDocComment() ?: null;
        } elseif (\is_string($macro)) {
            $reflection = new ReflectionFunction($macro);
            $closure = $reflection->getClosure();
            $deprecated = $reflection->isDeprecated();
            $docComment = $reflection->getDocComment() ?: null;
        } elseif ($macro instanceof Closure) {
            $closure = $macro;

            try {
                $boundClosure = Closure::bind($closure, new stdClass());
                $static = (!$boundClosure || (new ReflectionFunction($boundClosure))->getClosureThis() === null);
            } catch (Throwable) {
                $static = true;
            }

            $reflection = new ReflectionFunction($macro);
            $deprecated = $reflection->isDeprecated();
            $docComment = $reflection->getDocComment() ?: null;
        }

        if (!isset($closure)) {
            throw new InvalidArgumentException('Could not create reflection from the spec given'); // @codeCoverageIgnore
        }

        $closureType = $this->closureTypeFactory->fromClosureObject($closure);

        return new MacroMethodReflection(
            $classReflection,
            $methodName,
            $closureType,
            $static,
            $final,
            $deprecated,
            $docComment,
        );
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

class CarbonPeriodImmutable extends CarbonPeriod
{
    /**
     * Default date class of iteration items.
     *
     * @var string
     */
    protected const DEFAULT_DATE_CLASS = CarbonImmutable::class;

    /**
     * Date class of iteration items.
     */
    protected string $dateClass = CarbonImmutable::class;

    /**
     * Prepare the instance to be set (self if mutable to be mutated,
     * copy if immutable to generate a new instance).
     */
    protected function copyIfImmutable(): static
    {
        return $this->constructed ? clone $this : $this;
    }
}
<?php

declare(strict_types=1);

/**
 * This file is part of the Carbon package.
 *
 * (c) Brian Nesbitt <brian@nesbot.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Carbon;

use Carbon\MessageFormatter\MessageFormatterMapper;
use Closure;
use ReflectionException;
use ReflectionFunction;
use ReflectionProperty;
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\Translator as SymfonyTranslator;
use Throwable;

abstract class AbstractTranslator extends SymfonyTranslator
{
    public const REGION_CODE_LENGTH = 2;

    /**
     * Translator singletons for each language.
     *
     * @var array
     */
    protected static array $singletons = [];

    /**
     * List of custom localized messages.
     *
     * @var array
     */
    protected array $messages = [];

    /**
     * List of custom directories that contain translation files.
     *
     * @var string[]
     */
    protected array $directories = [];

    /**
     * Set to true while constructing.
     */
    protected bool $initializing = false;

    /**
     * List of locales aliases.
     *
     * @var array<string, string>
     */
    protected array $aliases = [
        'me' => 'sr_Latn_ME',
        'scr' => 'sh',
    ];

    /**
     * Return a singleton instance of Translator.
     *
     * @param string|null $locale optional initial locale ("en" - english by default)
     *
     * @return static
     */
    public static function get(?string $locale = null): static
    {
        $locale = $locale ?: 'en';
        $key = static::class === Translator::class ? $locale : static::class.'|'.$locale;
        $count = \count(static::$singletons);

        // Remember only the last 10 translators created
        if ($count > 10) {
            foreach (\array_slice(array_keys(static::$singletons), 0, $count - 10) as $index) {
                unset(static::$singletons[$index]);
            }
        }

        static::$singletons[$key] ??= new static($locale);

        return static::$singletons[$key];
    }

    public function __construct($locale, ?MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false)
    {
        $this->initialize($locale, $formatter, $cacheDir, $debug);
    }

    /**
     * Returns the list of directories translation files are searched in.
     */
    public function getDirectories(): array
    {
        return $this->directories;
    }

    /**
     * Set list of directories translation files are searched in.
     *
     * @param array $directories new directories list
     *
     * @return $this
     */
    public function setDirectories(array $directories): static
    {
        $this->directories = $directories;

        return $this;
    }

    /**
     * Add a directory to the list translation files are searched in.
     *
     * @param string $directory new directory
     *
     * @return $this
     */
    public function addDirectory(string $directory): static
    {
        $this->directories[] = $directory;

        return $this;
    }

    /**
     * Remove a directory from the list translation files are searched in.
     *
     * @param string $directory directory path
     *
     * @return $this
     */
    public function removeDirectory(string $directory): static
    {
        $search = rtrim(strtr($directory, '\\', '/'), '/');

        return $this->setDirectories(array_filter(
            $this->getDirectories(),
            static fn ($item) => rtrim(strtr($item, '\\', '/'), '/') !== $search,
        ));
    }

    /**
     * Reset messages of a locale (all locale if no locale passed).
     * Remove custom messages and reload initial messages from matching
     * file in Lang directory.
     */
    public function resetMessages(?string $locale = null): bool
    {
        if ($locale === null) {
            $this->messages = [];
            $this->catalogues = [];
            $this->modifyResources(static function (array $resources): array {
                foreach ($resources as &$list) {
                    array_splice($list, 1);
                }

                return $resources;
            });

            return true;
        }

        $this->assertValidLocale($locale);

        foreach ($this->getDirectories() as $directory) {
            $file = \sprintf('%s/%s.php', rtrim($directory, '\\/'), $locale);
            $data = @include $file;

            if ($data !== false) {
                $this->messages[$locale] = $data;
                unset($this->catalogues[$locale]);
                $this->modifyResources(static function (array $resources) use ($locale): array {
                    unset($resources[$locale]);

                    return $resources;
                });
                $this->addResource('array', $this->messages[$locale], $locale);

                return true;
            }
        }

        return false;
    }

    /**
     * Returns the list of files matching a given locale prefix (or all if empty).
     *
     * @param string $prefix prefix required to filter result
     *
     * @return array
     */
    public function getLocalesFiles(string $prefix = ''): array
    {
        $files = [];

        foreach ($this->getDirectories() as $directory) {
            foreach (self::getPhpFilesInDirectory(rtrim($directory, '\\/'), $prefix) as $file) {
                $files[] = $file;
            }
        }

        return array_unique($files);
    }

    /**
     * Returns the list of internally available locales and already loaded custom locales.
     * (It will ignore custom translator dynamic loading.)
     *
     * @param string $prefix prefix required to filter result
     *
     * @return array
     */
    public function getAvailableLocales(string $prefix = ''): array
    {
        return array_unique(array_merge(
            array_map(
                static fn (string $file) => substr($file, strrpos($file, '/') + 1, -4),
                $this->getLocalesFiles($prefix),
            ),
            array_keys($this->messages),
        ));
    }

    protected function translate(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        $domain ??= 'messages';
        $catalogue = $this->getCatalogue($locale);
        $format = $this instanceof TranslatorStrongTypeInterface
            ? $this->getFromCatalogue($catalogue, (string) $id, $domain)
            : $this->getCatalogue($locale)->get((string) $id, $domain); // @codeCoverageIgnore

        if ($format instanceof Closure) {
            // @codeCoverageIgnoreStart
            try {
                $count = (new ReflectionFunction($format))->getNumberOfRequiredParameters();
            } catch (ReflectionException) {
                $count = 0;
            }
            // @codeCoverageIgnoreEnd

            return $format(
                ...array_values($parameters),
                ...array_fill(0, max(0, $count - \count($parameters)), null)
            );
        }

        return parent::trans($id, $parameters, $domain, $locale);
    }

    /**
     * Init messages language from matching file in Lang directory.
     *
     * @param string $locale
     *
     * @return bool
     */
    protected function loadMessagesFromFile(string $locale): bool
    {
        return isset($this->messages[$locale]) || $this->resetMessages($locale);
    }

    /**
     * Set messages of a locale and take file first if present.
     *
     * @param string $locale
     * @param array  $messages
     *
     * @return $this
     */
    public function setMessages(string $locale, array $messages): static
    {
        $this->loadMessagesFromFile($locale);
        $this->addResource('array', $messages, $locale);
        $this->messages[$locale] = array_merge(
            $this->messages[$locale] ?? [],
            $messages
        );

        return $this;
    }

    /**
     * Set messages of the current locale and take file first if present.
     *
     * @param array $messages
     *
     * @return $this
     */
    public function setTranslations(array $messages): static
    {
        return $this->setMessages($this->getLocale(), $messages);
    }

    /**
     * Get messages of a locale, if none given, return all the
     * languages.
     */
    public function getMessages(?string $locale = null): array
    {
        return $locale === null ? $this->messages : $this->messages[$locale];
    }

    /**
     * Set the current translator locale and indicate if the source locale file exists
     *
     * @param string $locale locale ex. en
     */
    public function setLocale($locale): void
    {
        $locale = preg_replace_callback('/[-_]([a-z]{2,}|\d{2,})/', function ($matches) {
            // _2-letters or YUE is a region, _3+-letters is a variant
            $upper = strtoupper($matches[1]);

            if ($upper === 'YUE' || $upper === 'ISO' || \strlen($upper) <= static::REGION_CODE_LENGTH) {
                return "_$upper";
            }

            return '_'.ucfirst($matches[1]);
        }, strtolower($locale));

        $previousLocale = $this->getLocale();

        if ($previousLocale === $locale && isset($this->messages[$locale])) {
            return;
        }

        unset(static::$singletons[$previousLocale]);

        if ($locale === 'auto') {
            $completeLocale = setlocale(LC_TIME, '0');
            $locale = preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale);
            $locales = $this->getAvailableLocales($locale);

            $completeLocaleChunks = preg_split('/[_.-]+/', $completeLocale);

            $getScore = static fn ($language) => self::compareChunkLists(
                $completeLocaleChunks,
                preg_split('/[_.-]+/', $language),
            );

            usort($locales, static fn ($first, $second) => $getScore($second) <=> $getScore($first));

            $locale = $locales[0] ?? 'en';
        }

        if (isset($this->aliases[$locale])) {
            $locale = $this->aliases[$locale];
        }

        // If the language is not provided by a Carbon file
        // and the tag contains a region (ex: en_CA), then
        // first load the macro (ex: en) to have a fallback
        if (
            str_contains($locale, '_')
            && !\in_array($locale, self::getInternallySupportedLocales(), true)
            && $this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
        ) {
            parent::setLocale($macroLocale);
        }

        if (!$this->loadMessagesFromFile($locale) && !$this->initializing) {
            return;
        }

        parent::setLocale($locale);
    }

    /**
     * Show locale on var_dump().
     *
     * @return array
     */
    public function __debugInfo()
    {
        return [
            'locale' => $this->getLocale(),
        ];
    }

    public function __serialize(): array
    {
        return [
            'locale' => $this->getLocale(),
        ];
    }

    public function __unserialize(array $data): void
    {
        $this->initialize($data['locale'] ?? 'en');
    }

    private function initialize($locale, ?MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false): void
    {
        parent::setLocale($locale);
        $this->initializing = true;
        $this->directories = [self::getDefaultLangDirectory()];
        $this->addLoader('array', new ArrayLoader());
        parent::__construct($locale, new MessageFormatterMapper($formatter), $cacheDir, $debug);
        $this->initializing = false;
    }

    private static function compareChunkLists($referenceChunks, $chunks)
    {
        $score = 0;

        foreach ($referenceChunks as $index => $chunk) {
            if (!isset($chunks[$index])) {
                $score++;

                continue;
            }

            if (strtolower($chunks[$index]) === strtolower($chunk)) {
                $score += 10;
            }
        }

        return $score;
    }

    /** @codeCoverageIgnore */
    private function modifyResources(callable $callback): void
    {
        try {
            $resourcesProperty = new ReflectionProperty(SymfonyTranslator::class, 'resources');
            $resources = $resourcesProperty->getValue($this);
            $resourcesProperty->setValue($this, $callback($resources));
        } catch (Throwable) {
            // Clear resources if available, if not, then nothing to clean
        }
    }

    private static function getPhpFilesInDirectory(string $directory, string $prefix): array
    {
        if ($directory !== self::getDefaultLangDirectory()) {
            return glob("$directory/$prefix*.php") ?: [];
        }

        // If it's the internal Carbon directory we use a static list
        // which is faster than scanning the folder with glob()
        $locales = self::getInternallySupportedLocales();

        if ($prefix !== '') {
            $locales = array_values(array_filter(
                self::getInternallySupportedLocales(),
                static fn (string $locale) => str_starts_with($locale, $prefix),
            ));
        }

        return array_map(
            static fn (string $locale) => "$directory/$locale.php",
            $locales,
        );
    }

    private static function getDefaultLangDirectory(): string
    {
        return __DIR__.'/Lang';
    }

    /** @return list<string> */
    private static function getInternallySupportedLocales(): array
    {
        return [
            'aa',
            'aa_DJ',
            'aa_ER',
            'aa_ER@saaho',
            'aa_ET',
            'af',
            'af_NA',
            'af_ZA',
            'agq',
            'agr',
            'agr_PE',
            'ak',
            'ak_GH',
            'am',
            'am_ET',
            'an',
            'an_ES',
            'anp',
            'anp_IN',
            'ar',
            'ar_AE',
            'ar_BH',
            'ar_DJ',
            'ar_DZ',
            'ar_EG',
            'ar_EH',
            'ar_ER',
            'ar_IL',
            'ar_IN',
            'ar_IQ',
            'ar_JO',
            'ar_KM',
            'ar_KW',
            'ar_LB',
            'ar_LY',
            'ar_MA',
            'ar_MR',
            'ar_OM',
            'ar_PS',
            'ar_QA',
            'ar_SA',
            'ar_SD',
            'ar_SO',
            'ar_SS',
            'ar_SY',
            'ar_Shakl',
            'ar_TD',
            'ar_TN',
            'ar_YE',
            'as',
            'as_IN',
            'asa',
            'ast',
            'ast_ES',
            'ayc',
            'ayc_PE',
            'az',
            'az_AZ',
            'az_Arab',
            'az_Cyrl',
            'az_IR',
            'az_Latn',
            'bas',
            'be',
            'be_BY',
            'be_BY@latin',
            'bem',
            'bem_ZM',
            'ber',
            'ber_DZ',
            'ber_MA',
            'bez',
            'bg',
            'bg_BG',
            'bhb',
            'bhb_IN',
            'bho',
            'bho_IN',
            'bi',
            'bi_VU',
            'bm',
            'bn',
            'bn_BD',
            'bn_IN',
            'bo',
            'bo_CN',
            'bo_IN',
            'br',
            'br_FR',
            'brx',
            'brx_IN',
            'bs',
            'bs_BA',
            'bs_Cyrl',
            'bs_Latn',
            'byn',
            'byn_ER',
            'ca',
            'ca_AD',
            'ca_ES',
            'ca_ES_Valencia',
            'ca_FR',
            'ca_IT',
            'ccp',
            'ccp_IN',
            'ce',
            'ce_RU',
            'cgg',
            'chr',
            'chr_US',
            'ckb',
            'cmn',
            'cmn_TW',
            'crh',
            'crh_UA',
            'cs',
            'cs_CZ',
            'csb',
            'csb_PL',
            'cu',
            'cv',
            'cv_RU',
            'cy',
            'cy_GB',
            'da',
            'da_DK',
            'da_GL',
            'dav',
            'de',
            'de_AT',
            'de_BE',
            'de_CH',
            'de_DE',
            'de_IT',
            'de_LI',
            'de_LU',
            'dje',
            'doi',
            'doi_IN',
            'dsb',
            'dsb_DE',
            'dua',
            'dv',
            'dv_MV',
            'dyo',
            'dz',
            'dz_BT',
            'ebu',
            'ee',
            'ee_TG',
            'el',
            'el_CY',
            'el_GR',
            'en',
            'en_001',
            'en_150',
            'en_AG',
            'en_AI',
            'en_AS',
            'en_AT',
            'en_AU',
            'en_BB',
            'en_BE',
            'en_BI',
            'en_BM',
            'en_BS',
            'en_BW',
            'en_BZ',
            'en_CA',
            'en_CC',
            'en_CH',
            'en_CK',
            'en_CM',
            'en_CX',
            'en_CY',
            'en_DE',
            'en_DG',
            'en_DK',
            'en_DM',
            'en_ER',
            'en_FI',
            'en_FJ',
            'en_FK',
            'en_FM',
            'en_GB',
            'en_GD',
            'en_GG',
            'en_GH',
            'en_GI',
            'en_GM',
            'en_GU',
            'en_GY',
            'en_HK',
            'en_IE',
            'en_IL',
            'en_IM',
            'en_IN',
            'en_IO',
            'en_ISO',
            'en_JE',
            'en_JM',
            'en_KE',
            'en_KI',
            'en_KN',
            'en_KY',
            'en_LC',
            'en_LR',
            'en_LS',
            'en_MG',
            'en_MH',
            'en_MO',
            'en_MP',
            'en_MS',
            'en_MT',
            'en_MU',
            'en_MW',
            'en_MY',
            'en_NA',
            'en_NF',
            'en_NG',
            'en_NL',
            'en_NR',
            'en_NU',
            'en_NZ',
            'en_PG',
            'en_PH',
            'en_PK',
            'en_PN',
            'en_PR',
            'en_PW',
            'en_RW',
            'en_SB',
            'en_SC',
            'en_SD',
            'en_SE',
            'en_SG',
            'en_SH',
            'en_SI',
            'en_SL',
            'en_SS',
            'en_SX',
            'en_SZ',
            'en_TC',
            'en_TK',
            'en_TO',
            'en_TT',
            'en_TV',
            'en_TZ',
            'en_UG',
            'en_UM',
            'en_US',
            'en_US_Posix',
            'en_VC',
            'en_VG',
            'en_VI',
            'en_VU',
            'en_WS',
            'en_ZA',
            'en_ZM',
            'en_ZW',
            'eo',
            'es',
            'es_419',
            'es_AR',
            'es_BO',
            'es_BR',
            'es_BZ',
            'es_CL',
            'es_CO',
            'es_CR',
            'es_CU',
            'es_DO',
            'es_EA',
            'es_EC',
            'es_ES',
            'es_GQ',
            'es_GT',
            'es_HN',
            'es_IC',
            'es_MX',
            'es_NI',
            'es_PA',
            'es_PE',
            'es_PH',
            'es_PR',
            'es_PY',
            'es_SV',
            'es_US',
            'es_UY',
            'es_VE',
            'et',
            'et_EE',
            'eu',
            'eu_ES',
            'ewo',
            'fa',
            'fa_AF',
            'fa_IR',
            'ff',
            'ff_CM',
            'ff_GN',
            'ff_MR',
            'ff_SN',
            'fi',
            'fi_FI',
            'fil',
            'fil_PH',
            'fo',
            'fo_DK',
            'fo_FO',
            'fr',
            'fr_BE',
            'fr_BF',
            'fr_BI',
            'fr_BJ',
            'fr_BL',
            'fr_CA',
            'fr_CD',
            'fr_CF',
            'fr_CG',
            'fr_CH',
            'fr_CI',
            'fr_CM',
            'fr_DJ',
            'fr_DZ',
            'fr_FR',
            'fr_GA',
            'fr_GF',
            'fr_GN',
            'fr_GP',
            'fr_GQ',
            'fr_HT',
            'fr_KM',
            'fr_LU',
            'fr_MA',
            'fr_MC',
            'fr_MF',
            'fr_MG',
            'fr_ML',
            'fr_MQ',
            'fr_MR',
            'fr_MU',
            'fr_NC',
            'fr_NE',
            'fr_PF',
            'fr_PM',
            'fr_RE',
            'fr_RW',
            'fr_SC',
            'fr_SN',
            'fr_SY',
            'fr_TD',
            'fr_TG',
            'fr_TN',
            'fr_VU',
            'fr_WF',
            'fr_YT',
            'fur',
            'fur_IT',
            'fy',
            'fy_DE',
            'fy_NL',
            'ga',
            'ga_IE',
            'gd',
            'gd_GB',
            'gez',
            'gez_ER',
            'gez_ET',
            'gl',
            'gl_ES',
            'gom',
            'gom_Latn',
            'gsw',
            'gsw_CH',
            'gsw_FR',
            'gsw_LI',
            'gu',
            'gu_IN',
            'guz',
            'gv',
            'gv_GB',
            'ha',
            'ha_GH',
            'ha_NE',
            'ha_NG',
            'hak',
            'hak_TW',
            'haw',
            'he',
            'he_IL',
            'hi',
            'hi_IN',
            'hif',
            'hif_FJ',
            'hne',
            'hne_IN',
            'hr',
            'hr_BA',
            'hr_HR',
            'hsb',
            'hsb_DE',
            'ht',
            'ht_HT',
            'hu',
            'hu_HU',
            'hy',
            'hy_AM',
            'i18n',
            'ia',
            'ia_FR',
            'id',
            'id_ID',
            'ig',
            'ig_NG',
            'ii',
            'ik',
            'ik_CA',
            'in',
            'is',
            'is_IS',
            'it',
            'it_CH',
            'it_IT',
            'it_SM',
            'it_VA',
            'iu',
            'iu_CA',
            'iw',
            'ja',
            'ja_JP',
            'jgo',
            'jmc',
            'jv',
            'ka',
            'ka_GE',
            'kab',
            'kab_DZ',
            'kam',
            'kde',
            'kea',
            'khq',
            'ki',
            'kk',
            'kk_KZ',
            'kkj',
            'kl',
            'kl_GL',
            'kln',
            'km',
            'km_KH',
            'kn',
            'kn_IN',
            'ko',
            'ko_KP',
            'ko_KR',
            'kok',
            'kok_IN',
            'ks',
            'ks_IN',
            'ks_IN@devanagari',
            'ksb',
            'ksf',
            'ksh',
            'ku',
            'ku_TR',
            'kw',
            'kw_GB',
            'ky',
            'ky_KG',
            'lag',
            'lb',
            'lb_LU',
            'lg',
            'lg_UG',
            'li',
            'li_NL',
            'lij',
            'lij_IT',
            'lkt',
            'ln',
            'ln_AO',
            'ln_CD',
            'ln_CF',
            'ln_CG',
            'lo',
            'lo_LA',
            'lrc',
            'lrc_IQ',
            'lt',
            'lt_LT',
            'lu',
            'luo',
            'luy',
            'lv',
            'lv_LV',
            'lzh',
            'lzh_TW',
            'mag',
            'mag_IN',
            'mai',
            'mai_IN',
            'mas',
            'mas_TZ',
            'mer',
            'mfe',
            'mfe_MU',
            'mg',
            'mg_MG',
            'mgh',
            'mgo',
            'mhr',
            'mhr_RU',
            'mi',
            'mi_NZ',
            'miq',
            'miq_NI',
            'mjw',
            'mjw_IN',
            'mk',
            'mk_MK',
            'ml',
            'ml_IN',
            'mn',
            'mn_MN',
            'mni',
            'mni_IN',
            'mo',
            'mr',
            'mr_IN',
            'ms',
            'ms_BN',
            'ms_MY',
            'ms_SG',
            'mt',
            'mt_MT',
            'mua',
            'my',
            'my_MM',
            'mzn',
            'nan',
            'nan_TW',
            'nan_TW@latin',
            'naq',
            'nb',
            'nb_NO',
            'nb_SJ',
            'nd',
            'nds',
            'nds_DE',
            'nds_NL',
            'ne',
            'ne_IN',
            'ne_NP',
            'nhn',
            'nhn_MX',
            'niu',
            'niu_NU',
            'nl',
            'nl_AW',
            'nl_BE',
            'nl_BQ',
            'nl_CW',
            'nl_NL',
            'nl_SR',
            'nl_SX',
            'nmg',
            'nn',
            'nn_NO',
            'nnh',
            'no',
            'nr',
            'nr_ZA',
            'nso',
            'nso_ZA',
            'nus',
            'nyn',
            'oc',
            'oc_FR',
            'om',
            'om_ET',
            'om_KE',
            'or',
            'or_IN',
            'os',
            'os_RU',
            'pa',
            'pa_Arab',
            'pa_Guru',
            'pa_IN',
            'pa_PK',
            'pap',
            'pap_AW',
            'pap_CW',
            'pl',
            'pl_PL',
            'prg',
            'ps',
            'ps_AF',
            'pt',
            'pt_AO',
            'pt_BR',
            'pt_CH',
            'pt_CV',
            'pt_GQ',
            'pt_GW',
            'pt_LU',
            'pt_MO',
            'pt_MZ',
            'pt_PT',
            'pt_ST',
            'pt_TL',
            'qu',
            'qu_BO',
            'qu_EC',
            'quz',
            'quz_PE',
            'raj',
            'raj_IN',
            'rm',
            'rn',
            'ro',
            'ro_MD',
            'ro_RO',
            'rof',
            'ru',
            'ru_BY',
            'ru_KG',
            'ru_KZ',
            'ru_MD',
            'ru_RU',
            'ru_UA',
            'rw',
            'rw_RW',
            'rwk',
            'sa',
            'sa_IN',
            'sah',
            'sah_RU',
            'saq',
            'sat',
            'sat_IN',
            'sbp',
            'sc',
            'sc_IT',
            'sd',
            'sd_IN',
            'sd_IN@devanagari',
            'se',
            'se_FI',
            'se_NO',
            'se_SE',
            'seh',
            'ses',
            'sg',
            'sgs',
            'sgs_LT',
            'sh',
            'shi',
            'shi_Latn',
            'shi_Tfng',
            'shn',
            'shn_MM',
            'shs',
            'shs_CA',
            'si',
            'si_LK',
            'sid',
            'sid_ET',
            'sk',
            'sk_SK',
            'sl',
            'sl_SI',
            'sm',
            'sm_WS',
            'smn',
            'sn',
            'so',
            'so_DJ',
            'so_ET',
            'so_KE',
            'so_SO',
            'sq',
            'sq_AL',
            'sq_MK',
            'sq_XK',
            'sr',
            'sr_Cyrl',
            'sr_Cyrl_BA',
            'sr_Cyrl_ME',
            'sr_Cyrl_XK',
            'sr_Latn',
            'sr_Latn_BA',
            'sr_Latn_ME',
            'sr_Latn_XK',
            'sr_ME',
            'sr_RS',
            'sr_RS@latin',
            'ss',
            'ss_ZA',
            'st',
            'st_ZA',
            'sv',
            'sv_AX',
            'sv_FI',
            'sv_SE',
            'sw',
            'sw_CD',
            'sw_KE',
            'sw_TZ',
            'sw_UG',
            'szl',
            'szl_PL',
            'ta',
            'ta_IN',
            'ta_LK',
            'ta_MY',
            'ta_SG',
            'tcy',
            'tcy_IN',
            'te',
            'te_IN',
            'teo',
            'teo_KE',
            'tet',
            'tg',
            'tg_TJ',
            'th',
            'th_TH',
            'the',
            'the_NP',
            'ti',
            'ti_ER',
            'ti_ET',
            'tig',
            'tig_ER',
            'tk',
            'tk_TM',
            'tl',
            'tl_PH',
            'tlh',
            'tn',
            'tn_ZA',
            'to',
            'to_TO',
            'tpi',
            'tpi_PG',
            'tr',
            'tr_CY',
            'tr_TR',
            'ts',
            'ts_ZA',
            'tt',
            'tt_RU',
            'tt_RU@iqtelif',
            'twq',
            'tzl',
            'tzm',
            'tzm_Latn',
            'ug',
            'ug_CN',
            'uk',
            'uk_UA',
            'unm',
            'unm_US',
            'ur',
            'ur_IN',
            'ur_PK',
            'uz',
            'uz_Arab',
            'uz_Cyrl',
            'uz_Latn',
            'uz_UZ',
            'uz_UZ@cyrillic',
            'vai',
            'vai_Latn',
            'vai_Vaii',
            've',
            've_ZA',
            'vi',
            'vi_VN',
            'vo',
            'vun',
            'wa',
            'wa_BE',
            'wae',
            'wae_CH',
            'wal',
            'wal_ET',
            'wo',
            'wo_SN',
            'xh',
            'xh_ZA',
            'xog',
            'yav',
            'yi',
            'yi_US',
            'yo',
            'yo_BJ',
            'yo_NG',
            'yue',
            'yue_HK',
            'yue_Hans',
            'yue_Hant',
            'yuw',
            'yuw_PG',
            'zgh',
            'zh',
            'zh_CN',
            'zh_HK',
            'zh_Hans',
            'zh_Hans_HK',
            'zh_Hans_MO',
            'zh_Hans_SG',
            'zh_Hant',
            'zh_Hant_HK',
            'zh_Hant_MO',
            'zh_Hant_TW',
            'zh_MO',
            'zh_SG',
            'zh_TW',
            'zh_YUE',
            'zu',
            'zu_ZA',
        ];
    }
}
Copyright (C) Brian Nesbitt

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
parameters:
    bootstrapFiles:
        - lazy/Carbon/UnprotectedDatePeriod.php

services:
    -
        class: Carbon\PHPStan\MacroExtension
        tags:
            - phpstan.broker.methodsClassReflectionExtension
@ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/carbon
php "%BIN_TARGET%" %*
#!/usr/bin/env php
<?php

use Carbon\Cli\Invoker;

$dir = __DIR__.'/..';

if (!file_exists($dir.'/autoload.php')) {
    $dir = __DIR__.'/../vendor';
}

if (!file_exists($dir.'/autoload.php')) {
    $dir = __DIR__.'/../../..';
}

if (!file_exists($dir.'/autoload.php')) {
    echo 'Autoload not found.';
    exit(1);
}

require $dir.'/autoload.php';

exit((new Invoker())(...$argv) ? 0 : 1);
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Intl\Grapheme;

\define('SYMFONY_GRAPHEME_CLUSTER_RX', ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39) ? '\X' : Grapheme::GRAPHEME_CLUSTER_RX);

/**
 * Partial intl implementation in pure PHP.
 *
 * Implemented:
 * - grapheme_extract  - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8
 * - grapheme_stripos  - Find position (in grapheme units) of first occurrence of a case-insensitive string
 * - grapheme_stristr  - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack
 * - grapheme_strlen   - Get string length in grapheme units
 * - grapheme_strpos   - Find position (in grapheme units) of first occurrence of a string
 * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string
 * - grapheme_strrpos  - Find position (in grapheme units) of last occurrence of a string
 * - grapheme_strstr   - Returns part of haystack string from the first occurrence of needle to the end of haystack
 * - grapheme_substr   - Return part of a string
 * - grapheme_str_split - Splits a string into an array of individual or chunks of graphemes
 * - grapheme_levenshtein - Calculate the grapheme-unit Levenshtein distance between two strings
 * - grapheme_strrev - Reverse a string by grapheme clusters
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Grapheme
{
    // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control])
    // This regular expression is a work around for http://bugs.exim.org/1279
    public const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';

    private const CASE_FOLD = [
        ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
        ['μ', 's', 'ι',        'σ', 'β',        'θ',        'φ',        'π',        'κ',        'ρ',        'ε',        "\xE1\xB9\xA1", 'ι'],
    ];

    public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0)
    {
        if (0 > $start) {
            $start = \strlen($s) + $start;
        }

        if (!\is_scalar($s)) {
            $hasError = false;
            set_error_handler(static function () use (&$hasError) { $hasError = true; });
            $next = substr($s, $start);
            restore_error_handler();
            if ($hasError) {
                substr($s, $start);
                $s = '';
            } else {
                $s = $next;
            }
        } else {
            $s = substr($s, $start);
        }
        $size = (int) $size;
        $type = (int) $type;
        $start = (int) $start;

        if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) {
            if (80000 > \PHP_VERSION_ID) {
                return false;
            }

            throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS');
        }

        if (!isset($s[0]) || 0 > $size || 0 > $start) {
            return false;
        }
        if (0 === $size) {
            return '';
        }

        $next = $start;

        $s = preg_split('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', "\r\n".$s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE);

        if (!isset($s[1])) {
            return false;
        }

        $i = 1;
        $ret = '';

        do {
            if (\GRAPHEME_EXTR_COUNT === $type) {
                --$size;
            } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) {
                $size -= \strlen($s[$i]);
            } else {
                $size -= iconv_strlen($s[$i], 'UTF-8//IGNORE');
            }

            if ($size >= 0) {
                $ret .= $s[$i];
            }
        } while (isset($s[++$i]) && $size > 0);

        $next += \strlen($ret);

        return $ret;
    }

    public static function grapheme_strlen($s)
    {
        preg_replace('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', '', $s, -1, $len);

        return 0 === $len && '' !== $s ? null : $len;
    }

    public static function grapheme_substr($s, $start, $len = null)
    {
        if (null === $len) {
            $len = 2147483647;
        }

        preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s, $s);

        $slen = \count($s[0]);
        $start = (int) $start;

        if (0 > $start) {
            $start += $slen;
        }
        if (0 > $start) {
            if (\PHP_VERSION_ID < 80000) {
                return false;
            }

            $start = 0;
        }
        if ($start >= $slen) {
            return \PHP_VERSION_ID >= 80000 ? '' : false;
        }

        $rem = $slen - $start;

        if (0 > $len) {
            $len += $rem;
        }
        if (0 === $len) {
            return '';
        }
        if (0 > $len) {
            return \PHP_VERSION_ID >= 80000 ? '' : false;
        }
        if ($len > $rem) {
            $len = $rem;
        }

        return implode('', \array_slice($s[0], $start, $len));
    }

    public static function grapheme_strpos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 0);
    }

    public static function grapheme_stripos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 1);
    }

    public static function grapheme_strrpos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 2);
    }

    public static function grapheme_strripos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 3);
    }

    public static function grapheme_stristr($s, $needle, $beforeNeedle = false)
    {
        return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8');
    }

    public static function grapheme_strstr($s, $needle, $beforeNeedle = false)
    {
        return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8');
    }

    public static function grapheme_str_split($s, $len = 1)
    {
        if (0 > $len || 1073741823 < $len) {
            if (80000 > \PHP_VERSION_ID) {
                return false;
            }

            throw new \ValueError('grapheme_str_split(): Argument #2 ($length) must be greater than 0 and less than or equal to 1073741823.');
        }

        if ('' === $s) {
            return [];
        }

        if (!preg_match_all('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', $s, $matches)) {
            return false;
        }

        if (1 === $len) {
            return $matches[0];
        }

        $chunks = array_chunk($matches[0], $len);

        foreach ($chunks as &$chunk) {
            $chunk = implode('', $chunk);
        }

        return $chunks;
    }

    public static function grapheme_levenshtein($s1, $s2, $insertion_cost = 1, $replacement_cost = 1, $deletion_cost = 1)
    {
        if (!preg_match('//u', $s1) || !preg_match('//u', $s2)) {
            return false;
        }

        if (0 > $insertion_cost || 0 > $replacement_cost || 0 > $deletion_cost) {
            if (80000 > \PHP_VERSION_ID) {
                return false;
            }

            throw new \ValueError('grapheme_levenshtein(): Argument #3 ($insertion_cost), #4 ($replacement_cost), and #5 ($deletion_cost) must be greater than or equal to 0');
        }

        preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s1, $s1);
        preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s2, $s2);

        $s1 = $s1[0];
        $s2 = $s2[0];
        $l1 = \count($s1);
        $l2 = \count($s2);

        if (0 === $l1) {
            return $l2 * $insertion_cost;
        }
        if (0 === $l2) {
            return $l1 * $deletion_cost;
        }

        $dp = array_fill(0, $l1 + 1, array_fill(0, $l2 + 1, 0));

        for ($i = 1; $i <= $l1; ++$i) {
            $dp[$i][0] = $dp[$i - 1][0] + $deletion_cost;
        }
        for ($j = 1; $j <= $l2; ++$j) {
            $dp[0][$j] = $dp[0][$j - 1] + $insertion_cost;
        }

        for ($i = 1; $i <= $l1; ++$i) {
            for ($j = 1; $j <= $l2; ++$j) {
                $cost = ($s1[$i - 1] === $s2[$j - 1]) ? 0 : $replacement_cost;
                $dp[$i][$j] = min($dp[$i - 1][$j] + $deletion_cost, $dp[$i][$j - 1] + $insertion_cost, $dp[$i - 1][$j - 1] + $cost);
            }
        }

        return $dp[$l1][$l2];
    }

    private static function grapheme_position($s, $needle, $offset, $mode)
    {
        $needle = (string) $needle;
        if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) {
            return false;
        }
        $s = (string) $s;
        if (!preg_match('/./us', $s)) {
            return false;
        }
        if ($offset > 0) {
            $s = self::grapheme_substr($s, $offset);
        } elseif ($offset < 0) {
            if (2 > $mode) {
                $offset += self::grapheme_strlen($s);
                $s = self::grapheme_substr($s, $offset);
                if (0 > $offset) {
                    $offset = 0;
                }
            } elseif (0 > $offset += self::grapheme_strlen($needle)) {
                $s = self::grapheme_substr($s, 0, $offset);
                $offset = 0;
            } else {
                $offset = 0;
            }
        }

        // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8,
        // we can use normal binary string functions here. For case-insensitive searches,
        // case fold the strings first.
        $caseInsensitive = $mode & 1;
        $reverse = $mode & 2;
        if ($caseInsensitive) {
            // Use the same case folding mode as mbstring does for mb_stripos().
            // Stick to SIMPLE case folding to avoid changing the length of the string, which
            // might result in offsets being shifted.
            $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER;
            $s = mb_convert_case($s, $mode, 'UTF-8');
            $needle = mb_convert_case($needle, $mode, 'UTF-8');

            if (!\defined('MB_CASE_FOLD_SIMPLE')) {
                $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle);
            }
        }
        if ($reverse) {
            $needlePos = strrpos($s, $needle);
        } else {
            $needlePos = strpos($s, $needle);
        }

        return false !== $needlePos ? self::grapheme_strlen(substr($s, 0, $needlePos)) + $offset : false;
    }

    public static function grapheme_strrev(string $string)
    {
        $units = grapheme_str_split($string);

        if (false === $units) {
            return false;
        }

        return implode('', array_reverse($units));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Grapheme as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!defined('GRAPHEME_EXTR_COUNT')) {
    define('GRAPHEME_EXTR_COUNT', 0);
}
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
    define('GRAPHEME_EXTR_MAXBYTES', 1);
}
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
    define('GRAPHEME_EXTR_MAXCHARS', 2);
}

if (!function_exists('grapheme_extract')) {
    function grapheme_extract($haystack, $size, $type = 0, $start = 0, &$next = 0) { return p\Grapheme::grapheme_extract($haystack, $size, $type, $start, $next); }
}
if (!function_exists('grapheme_stripos')) {
    function grapheme_stripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_stripos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_stristr')) {
    function grapheme_stristr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_stristr($haystack, $needle, $beforeNeedle); }
}
if (!function_exists('grapheme_strlen')) {
    function grapheme_strlen($input) { return p\Grapheme::grapheme_strlen($input); }
}
if (!function_exists('grapheme_strpos')) {
    function grapheme_strpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strpos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_strripos')) {
    function grapheme_strripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strripos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_strrpos')) {
    function grapheme_strrpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strrpos($haystack, $needle, $offset); }
}
if (!function_exists('grapheme_strstr')) {
    function grapheme_strstr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_strstr($haystack, $needle, $beforeNeedle); }
}
if (!function_exists('grapheme_substr')) {
    function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); }
}
if (!function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1) { return p\Grapheme::grapheme_str_split($string, $length); }
}
if (!function_exists('grapheme_levenshtein')) {
    function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = '') { return p\Php85::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); }
}
if (!function_exists('grapheme_strrev')) {
    function grapheme_strrev(string $string) { return p\Grapheme::grapheme_strrev($string); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Grapheme as p;

if (!function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1): array|false { return p\Grapheme::grapheme_str_split($string, $length); }
}
if (!function_exists('grapheme_levenshtein')) {
    function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = ''): int|false { return p\Grapheme::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); }
}
if (!function_exists('grapheme_strrev')) {
    function grapheme_strrev(string $string): string|false { return p\Grapheme::grapheme_strrev($string); }
}

if (extension_loaded('intl')) {
    return;
}

if (!defined('GRAPHEME_EXTR_COUNT')) {
    define('GRAPHEME_EXTR_COUNT', 0);
}
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
    define('GRAPHEME_EXTR_MAXBYTES', 1);
}
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
    define('GRAPHEME_EXTR_MAXCHARS', 2);
}

if (!function_exists('grapheme_extract')) {
    function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null): string|false { return p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next); }
}
if (!function_exists('grapheme_stripos')) {
    function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_stristr')) {
    function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle); }
}
if (!function_exists('grapheme_strlen')) {
    function grapheme_strlen(?string $string): int|false|null { return p\Grapheme::grapheme_strlen((string) $string); }
}
if (!function_exists('grapheme_strpos')) {
    function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_strripos')) {
    function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_strrpos')) {
    function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset); }
}
if (!function_exists('grapheme_strstr')) {
    function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle); }
}
if (!function_exists('grapheme_substr')) {
    function grapheme_substr(?string $string, ?int $offset, ?int $length = null): string|false { return p\Grapheme::grapheme_substr((string) $string, (int) $offset, $length); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

final class StaticMessage implements TranslatableInterface
{
    public function __construct(
        private string $message,
    ) {
    }

    public function getMessage(): string
    {
        return $this->message;
    }

    public function trans(TranslatorInterface $translator, ?string $locale = null): string
    {
        return $this->getMessage();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * This translator should only be used in a development environment.
 */
final class PseudoLocalizationTranslator implements TranslatorInterface, TranslatorBagInterface
{
    private const EXPANSION_CHARACTER = '~';

    private bool $accents;
    private float $expansionFactor;
    private bool $brackets;
    private bool $parseHTML;

    /**
     * @var string[]
     */
    private array $localizableHTMLAttributes;

    /**
     * Available options:
     *  * accents:
     *      type: boolean
     *      default: true
     *      description: replace ASCII characters of the translated string with accented versions or similar characters
     *      example: if true, "foo" => "ƒöö".
     *
     *  * expansion_factor:
     *      type: float
     *      default: 1
     *      validation: it must be greater than or equal to 1
     *      description: expand the translated string by the given factor with spaces and tildes
     *      example: if 2, "foo" => "~foo ~"
     *
     *  * brackets:
     *      type: boolean
     *      default: true
     *      description: wrap the translated string with brackets
     *      example: if true, "foo" => "[foo]"
     *
     *  * parse_html:
     *      type: boolean
     *      default: false
     *      description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand or when it contains HTML
     *      warning: unclosed tags are unsupported, they will be fixed (closed) by the parser - eg, "foo <div>bar" => "foo <div>bar</div>"
     *
     *  * localizable_html_attributes:
     *      type: string[]
     *      default: []
     *      description: the list of HTML attributes whose values can be altered - it is only useful when the "parse_html" option is set to true
     *      example: if ["title"], and with the "accents" option set to true, "<a href="#" title="Go to your profile">Profile</a>" => "<a href="#" title="Ĝö ţö ýöûŕ þŕöƒîļé">Þŕöƒîļé</a>" - if "title" was not in the "localizable_html_attributes" list, the title attribute data would be left unchanged.
     */
    public function __construct(
        private TranslatorInterface $translator,
        array $options = [],
    ) {
        $this->translator = $translator;
        $this->accents = $options['accents'] ?? true;

        if (1.0 > ($this->expansionFactor = $options['expansion_factor'] ?? 1.0)) {
            throw new \InvalidArgumentException('The expansion factor must be greater than or equal to 1.');
        }

        $this->brackets = $options['brackets'] ?? true;

        $this->parseHTML = $options['parse_html'] ?? false;
        if ($this->parseHTML && !$this->accents && 1.0 === $this->expansionFactor) {
            $this->parseHTML = false;
        }

        $this->localizableHTMLAttributes = $options['localizable_html_attributes'] ?? [];
    }

    public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        $trans = '';
        $visibleText = '';

        foreach ($this->getParts($this->translator->trans($id, $parameters, $domain, $locale)) as [$visible, $localizable, $text]) {
            if ($visible) {
                $visibleText .= $text;
            }

            if (!$localizable) {
                $trans .= $text;

                continue;
            }

            $this->addAccents($trans, $text);
        }

        $this->expand($trans, $visibleText);

        $this->addBrackets($trans);

        return $trans;
    }

    public function getLocale(): string
    {
        return $this->translator->getLocale();
    }

    public function getCatalogue(?string $locale = null): MessageCatalogueInterface
    {
        if (!$this->translator instanceof TranslatorBagInterface) {
            throw new LogicException(\sprintf('The "%s()" method cannot be called as the wrapped translator class "%s" does not implement the "%s".', __METHOD__, $this->translator::class, TranslatorBagInterface::class));
        }

        return $this->translator->getCatalogue($locale);
    }

    public function getCatalogues(): array
    {
        if (!$this->translator instanceof TranslatorBagInterface) {
            throw new LogicException(\sprintf('The "%s()" method cannot be called as the wrapped translator class "%s" does not implement the "%s".', __METHOD__, $this->translator::class, TranslatorBagInterface::class));
        }

        return $this->translator->getCatalogues();
    }

    private function getParts(string $originalTrans): array
    {
        if (!$this->parseHTML) {
            return [[true, true, $originalTrans]];
        }

        $html = mb_encode_numericentity($originalTrans, [0x80, 0x10FFFF, 0, 0x1FFFFF], mb_detect_encoding($originalTrans, null, true) ?: 'UTF-8');

        $useInternalErrors = libxml_use_internal_errors(true);

        $dom = new \DOMDocument();
        $dom->loadHTML('<trans>'.$html.'</trans>');

        libxml_clear_errors();
        libxml_use_internal_errors($useInternalErrors);

        return $this->parseNode($dom->childNodes->item(1)->childNodes->item(0)->childNodes->item(0));
    }

    private function parseNode(\DOMNode $node): array
    {
        $parts = [];

        foreach ($node->childNodes as $childNode) {
            if (!$childNode instanceof \DOMElement) {
                $parts[] = [true, true, $childNode->nodeValue];

                continue;
            }

            $parts[] = [false, false, '<'.$childNode->tagName];

            foreach ($childNode->attributes as $attribute) {
                $parts[] = [false, false, ' '.$attribute->nodeName.'="'];

                $localizableAttribute = \in_array($attribute->nodeName, $this->localizableHTMLAttributes, true);
                foreach (preg_split('/(&(?:amp|quot|#039|lt|gt);+)/', htmlspecialchars($attribute->nodeValue, \ENT_QUOTES, 'UTF-8'), -1, \PREG_SPLIT_DELIM_CAPTURE) as $i => $match) {
                    if ('' === $match) {
                        continue;
                    }

                    $parts[] = [false, $localizableAttribute && 0 === $i % 2, $match];
                }

                $parts[] = [false, false, '"'];
            }

            $parts[] = [false, false, '>'];

            $parts = array_merge($parts, $this->parseNode($childNode));

            $parts[] = [false, false, '</'.$childNode->tagName.'>'];
        }

        return $parts;
    }

    private function addAccents(string &$trans, string $text): void
    {
        $trans .= $this->accents ? strtr($text, [
            ' ' => ' ',
            '!' => '¡',
            '"' => '″',
            '#' => '♯',
            '$' => '€',
            '%' => '‰',
            '&' => '⅋',
            '\'' => '´',
            '(' => '{',
            ')' => '}',
            '*' => '⁎',
            '+' => '⁺',
            ',' => '،',
            '-' => '‐',
            '.' => '·',
            '/' => '⁄',
            '0' => '⓪',
            '1' => '①',
            '2' => '②',
            '3' => '③',
            '4' => '④',
            '5' => '⑤',
            '6' => '⑥',
            '7' => '⑦',
            '8' => '⑧',
            '9' => '⑨',
            ':' => '∶',
            ';' => '⁏',
            '<' => '≤',
            '=' => '≂',
            '>' => '≥',
            '?' => '¿',
            '@' => '՞',
            'A' => 'Å',
            'B' => 'Ɓ',
            'C' => 'Ç',
            'D' => 'Ð',
            'E' => 'É',
            'F' => 'Ƒ',
            'G' => 'Ĝ',
            'H' => 'Ĥ',
            'I' => 'Î',
            'J' => 'Ĵ',
            'K' => 'Ķ',
            'L' => 'Ļ',
            'M' => 'Ṁ',
            'N' => 'Ñ',
            'O' => 'Ö',
            'P' => 'Þ',
            'Q' => 'Ǫ',
            'R' => 'Ŕ',
            'S' => 'Š',
            'T' => 'Ţ',
            'U' => 'Û',
            'V' => 'Ṽ',
            'W' => 'Ŵ',
            'X' => 'Ẋ',
            'Y' => 'Ý',
            'Z' => 'Ž',
            '[' => '⁅',
            '\\' => '∖',
            ']' => '⁆',
            '^' => '˄',
            '_' => '‿',
            '`' => '‵',
            'a' => 'å',
            'b' => 'ƀ',
            'c' => 'ç',
            'd' => 'ð',
            'e' => 'é',
            'f' => 'ƒ',
            'g' => 'ĝ',
            'h' => 'ĥ',
            'i' => 'î',
            'j' => 'ĵ',
            'k' => 'ķ',
            'l' => 'ļ',
            'm' => 'ɱ',
            'n' => 'ñ',
            'o' => 'ö',
            'p' => 'þ',
            'q' => 'ǫ',
            'r' => 'ŕ',
            's' => 'š',
            't' => 'ţ',
            'u' => 'û',
            'v' => 'ṽ',
            'w' => 'ŵ',
            'x' => 'ẋ',
            'y' => 'ý',
            'z' => 'ž',
            '{' => '(',
            '|' => '¦',
            '}' => ')',
            '~' => '˞',
        ]) : $text;
    }

    private function expand(string &$trans, string $visibleText): void
    {
        if (1.0 >= $this->expansionFactor) {
            return;
        }

        $visibleLength = $this->strlen($visibleText);
        $missingLength = (int) ceil($visibleLength * $this->expansionFactor) - $visibleLength;
        if ($this->brackets) {
            $missingLength -= 2;
        }

        if (0 >= $missingLength) {
            return;
        }

        $words = [];
        $wordsCount = 0;
        foreach (preg_split('/ +/', $visibleText, -1, \PREG_SPLIT_NO_EMPTY) as $word) {
            $wordLength = $this->strlen($word);

            if ($wordLength >= $missingLength) {
                continue;
            }

            if (!isset($words[$wordLength])) {
                $words[$wordLength] = 0;
            }

            ++$words[$wordLength];
            ++$wordsCount;
        }

        if (!$words) {
            $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1);

            return;
        }

        arsort($words, \SORT_NUMERIC);

        $longestWordLength = max(array_keys($words));

        while (true) {
            $r = mt_rand(1, $wordsCount);

            foreach ($words as $length => $count) {
                $r -= $count;
                if ($r <= 0) {
                    break;
                }
            }

            $trans .= ' '.str_repeat(self::EXPANSION_CHARACTER, $length);

            $missingLength -= $length + 1;

            if (0 === $missingLength) {
                return;
            }

            while ($longestWordLength >= $missingLength) {
                $wordsCount -= $words[$longestWordLength];
                unset($words[$longestWordLength]);

                if (!$words) {
                    $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1);

                    return;
                }

                $longestWordLength = max(array_keys($words));
            }
        }
    }

    private function addBrackets(string &$trans): void
    {
        if (!$this->brackets) {
            return;
        }

        $trans = '['.$trans.']';
    }

    private function strlen(string $s): int
    {
        return false === ($encoding = mb_detect_encoding($s, null, true)) ? \strlen($s) : mb_strlen($s, $encoding);
    }
}

// @php-cs-fixer-ignore random_api_migration As logic is coupled with mt_srand() in tests
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
 *
 * Options:
 * - path (mandatory): the directory where the files should be saved
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
abstract class FileDumper implements DumperInterface
{
    /**
     * A template for the relative paths to files.
     */
    protected string $relativePathTemplate = '%domain%.%locale%.%extension%';

    /**
     * Sets the template for the relative paths to files.
     */
    public function setRelativePathTemplate(string $relativePathTemplate): void
    {
        $this->relativePathTemplate = $relativePathTemplate;
    }

    public function dump(MessageCatalogue $messages, array $options = []): void
    {
        if (!\array_key_exists('path', $options)) {
            throw new InvalidArgumentException('The file dumper needs a path option.');
        }

        // save a file for each domain
        foreach ($messages->getDomains() as $domain) {
            $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
            if (!file_exists($fullpath)) {
                $directory = \dirname($fullpath);
                if (!file_exists($directory) && !@mkdir($directory, 0o777, true)) {
                    throw new RuntimeException(\sprintf('Unable to create directory "%s".', $directory));
                }
            }

            $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX;
            $intlMessages = $messages->all($intlDomain);

            if ($intlMessages) {
                $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale());
                file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options));

                $messages->replace([], $intlDomain);

                try {
                    if ($messages->all($domain)) {
                        file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
                    }
                    continue;
                } finally {
                    $messages->replace($intlMessages, $intlDomain);
                }
            }

            file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
        }
    }

    /**
     * Transforms a domain of a message catalogue to its string representation.
     */
    abstract public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string;

    /**
     * Gets the file extension of the dumper.
     */
    abstract protected function getExtension(): string;

    /**
     * Gets the relative file path using the template.
     */
    private function getRelativePath(string $domain, string $locale): string
    {
        return strtr($this->relativePathTemplate, [
            '%domain%' => $domain,
            '%locale%' => $locale,
            '%extension%' => $this->getExtension(),
        ]);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\Loader\MoFileLoader;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * MoFileDumper generates a gettext formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class MoFileDumper extends FileDumper
{
    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $sources = $targets = $sourceOffsets = $targetOffsets = '';
        $offsets = [];
        $size = 0;

        foreach ($messages->all($domain) as $source => $target) {
            $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]);
            $sources .= "\0".$source;
            $targets .= "\0".$target;
            ++$size;
        }

        $header = [
            'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
            'formatRevision' => 0,
            'count' => $size,
            'offsetId' => MoFileLoader::MO_HEADER_SIZE,
            'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
            'sizeHashes' => 0,
            'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
        ];

        $sourcesSize = \strlen($sources);
        $sourcesStart = $header['offsetHashes'] + 1;

        foreach ($offsets as $offset) {
            $sourceOffsets .= $this->writeLong($offset[1])
                          .$this->writeLong($offset[0] + $sourcesStart);
            $targetOffsets .= $this->writeLong($offset[3])
                          .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
        }

        return implode('', array_map($this->writeLong(...), $header))
               .$sourceOffsets
               .$targetOffsets
               .$sources
               .$targets;
    }

    protected function getExtension(): string
    {
        return 'mo';
    }

    private function writeLong(mixed $str): string
    {
        return pack('V*', $str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * XliffFileDumper generates xliff files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class XliffFileDumper extends FileDumper
{
    public function __construct(
        private string $extension = 'xlf',
    ) {
    }

    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $xliffVersion = '1.2';
        if (\array_key_exists('xliff_version', $options)) {
            $xliffVersion = $options['xliff_version'];
        }

        if (\array_key_exists('default_locale', $options)) {
            $defaultLocale = $options['default_locale'];
        } else {
            $defaultLocale = \Locale::getDefault();
        }

        if ('1.2' === $xliffVersion) {
            return $this->dumpXliff1($defaultLocale, $messages, $domain, $options);
        }
        if ('2.0' === $xliffVersion) {
            return $this->dumpXliff2($defaultLocale, $messages, $domain);
        }

        throw new InvalidArgumentException(\sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
    }

    protected function getExtension(): string
    {
        return $this->extension;
    }

    private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = []): string
    {
        $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony'];
        if (\array_key_exists('tool_info', $options)) {
            $toolInfo = array_merge($toolInfo, $options['tool_info']);
        }

        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;

        $xliff = $dom->appendChild($dom->createElement('xliff'));
        $xliff->setAttribute('version', '1.2');
        $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');

        $xliffFile = $xliff->appendChild($dom->createElement('file'));
        $xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale));
        $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale()));
        $xliffFile->setAttribute('datatype', 'plaintext');
        $xliffFile->setAttribute('original', 'file.ext');

        $xliffHead = $xliffFile->appendChild($dom->createElement('header'));
        $xliffTool = $xliffHead->appendChild($dom->createElement('tool'));
        foreach ($toolInfo as $id => $value) {
            $xliffTool->setAttribute($id, $value);
        }

        if ($catalogueMetadata = $messages->getCatalogueMetadata('', $domain) ?? []) {
            $xliffPropGroup = $xliffHead->appendChild($dom->createElement('prop-group'));
            foreach ($catalogueMetadata as $key => $value) {
                $xliffProp = $xliffPropGroup->appendChild($dom->createElement('prop'));
                $xliffProp->setAttribute('prop-type', $key);
                $xliffProp->appendChild($dom->createTextNode($value));
            }
        }

        $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
        foreach ($messages->all($domain) as $source => $target) {
            $translation = $dom->createElement('trans-unit');

            $translation->setAttribute('id', strtr(substr(base64_encode(hash('xxh128', $source, true)), 0, 7), '/+', '._'));
            $translation->setAttribute('resname', $source);

            $s = $translation->appendChild($dom->createElement('source'));
            $s->appendChild($dom->createTextNode($source));

            // Does the target contain characters requiring a CDATA section?
            $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);

            $targetElement = $dom->createElement('target');
            $metadata = $messages->getMetadata($source, $domain);
            if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
                foreach ($metadata['target-attributes'] as $name => $value) {
                    $targetElement->setAttribute($name, $value);
                }
            }
            $t = $translation->appendChild($targetElement);
            $t->appendChild($text);

            if ($this->hasMetadataArrayInfo('notes', $metadata)) {
                foreach ($metadata['notes'] as $note) {
                    if (!isset($note['content'])) {
                        continue;
                    }

                    $n = $translation->appendChild($dom->createElement('note'));
                    $n->appendChild($dom->createTextNode($note['content']));

                    if (isset($note['priority'])) {
                        $n->setAttribute('priority', $note['priority']);
                    }

                    if (isset($note['from'])) {
                        $n->setAttribute('from', $note['from']);
                    }
                }
            }

            $xliffBody->appendChild($translation);
        }

        return $dom->saveXML();
    }

    private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain): string
    {
        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;

        $xliff = $dom->appendChild($dom->createElement('xliff'));
        $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0');
        $xliff->setAttribute('version', '2.0');
        $xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale));
        $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));

        $xliffFile = $xliff->appendChild($dom->createElement('file'));
        if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
            $xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale());
        } else {
            $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
        }

        if ($catalogueMetadata = $messages->getCatalogueMetadata('', $domain) ?? []) {
            $xliff->setAttribute('xmlns:m', 'urn:oasis:names:tc:xliff:metadata:2.0');
            $xliffMetadata = $xliffFile->appendChild($dom->createElement('m:metadata'));
            foreach ($catalogueMetadata as $key => $value) {
                $xliffMeta = $xliffMetadata->appendChild($dom->createElement('prop'));
                $xliffMeta->setAttribute('type', $key);
                $xliffMeta->appendChild($dom->createTextNode($value));
            }
        }

        foreach ($messages->all($domain) as $source => $target) {
            $translation = $dom->createElement('unit');
            $translation->setAttribute('id', strtr(substr(base64_encode(hash('xxh128', $source, true)), 0, 7), '/+', '._'));

            if (\strlen($source) <= 80) {
                $translation->setAttribute('name', $source);
            }

            $metadata = $messages->getMetadata($source, $domain);

            // Add notes section
            if ($this->hasMetadataArrayInfo('notes', $metadata) && $metadata['notes']) {
                $notesElement = $dom->createElement('notes');
                foreach ($metadata['notes'] as $note) {
                    $n = $dom->createElement('note');
                    $n->appendChild($dom->createTextNode($note['content'] ?? ''));
                    unset($note['content']);

                    foreach ($note as $name => $value) {
                        $n->setAttribute($name, $value);
                    }
                    $notesElement->appendChild($n);
                }
                $translation->appendChild($notesElement);
            }

            $segment = $translation->appendChild($dom->createElement('segment'));

            if ($this->hasMetadataArrayInfo('segment-attributes', $metadata)) {
                foreach ($metadata['segment-attributes'] as $name => $value) {
                    $segment->setAttribute($name, $value);
                }
            }

            $s = $segment->appendChild($dom->createElement('source'));
            $s->appendChild($dom->createTextNode($source));

            // Does the target contain characters requiring a CDATA section?
            $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);

            $targetElement = $dom->createElement('target');
            if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
                foreach ($metadata['target-attributes'] as $name => $value) {
                    $targetElement->setAttribute($name, $value);
                }
            }
            $t = $segment->appendChild($targetElement);
            $t->appendChild($text);

            $xliffFile->appendChild($translation);
        }

        return $dom->saveXML();
    }

    private function hasMetadataArrayInfo(string $key, ?array $metadata = null): bool
    {
        return is_iterable($metadata[$key] ?? null);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * IniFileDumper generates an ini formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class IniFileDumper extends FileDumper
{
    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $output = '';

        foreach ($messages->all($domain) as $source => $target) {
            $escapeTarget = str_replace('"', '\"', $target);
            $output .= $source.'="'.$escapeTarget."\"\n";
        }

        return $output;
    }

    protected function getExtension(): string
    {
        return 'ini';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Util\ArrayConverter;
use Symfony\Component\Yaml\Yaml;

/**
 * YamlFileDumper generates yaml files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class YamlFileDumper extends FileDumper
{
    public function __construct(
        private string $extension = 'yml',
    ) {
    }

    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        if (!class_exists(Yaml::class)) {
            throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.');
        }

        $data = $messages->all($domain);

        if (isset($options['as_tree']) && $options['as_tree']) {
            $data = ArrayConverter::expandToTree($data);
        }

        if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) {
            return Yaml::dump($data, $inline);
        }

        return Yaml::dump($data);
    }

    protected function getExtension(): string
    {
        return $this->extension;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * JsonFileDumper generates an json formatted string representation of a message catalogue.
 *
 * @author singles
 */
class JsonFileDumper extends FileDumper
{
    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT;

        return json_encode($messages->all($domain), $flags);
    }

    protected function getExtension(): string
    {
        return 'json';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * CsvFileDumper generates a csv formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class CsvFileDumper extends FileDumper
{
    private string $delimiter = ';';
    private string $enclosure = '"';

    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $handle = fopen('php://memory', 'r+');

        foreach ($messages->all($domain) as $source => $target) {
            fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure, '\\');
        }

        rewind($handle);
        $output = stream_get_contents($handle);
        fclose($handle);

        return $output;
    }

    /**
     * Sets the delimiter and escape character for CSV.
     */
    public function setCsvControl(string $delimiter = ';', string $enclosure = '"'): void
    {
        $this->delimiter = $delimiter;
        $this->enclosure = $enclosure;
    }

    protected function getExtension(): string
    {
        return 'csv';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * PoFileDumper generates a gettext formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class PoFileDumper extends FileDumper
{
    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $output = 'msgid ""'."\n";
        $output .= 'msgstr ""'."\n";
        $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
        $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
        $output .= '"Language: '.$messages->getLocale().'\n"'."\n";
        $output .= "\n";

        $newLine = false;
        foreach ($messages->all($domain) as $source => $target) {
            if ($newLine) {
                $output .= "\n";
            } else {
                $newLine = true;
            }
            $metadata = $messages->getMetadata($source, $domain);

            if (isset($metadata['comments'])) {
                $output .= $this->formatComments($metadata['comments']);
            }
            if (isset($metadata['flags'])) {
                $output .= $this->formatComments(implode(',', (array) $metadata['flags']), ',');
            }
            if (isset($metadata['sources'])) {
                $output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':');
            }

            $sourceRules = $this->getStandardRules($source);
            $targetRules = $this->getStandardRules($target);
            if (2 == \count($sourceRules) && [] !== $targetRules) {
                $output .= \sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0]));
                $output .= \sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1]));
                foreach ($targetRules as $i => $targetRule) {
                    $output .= \sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule));
                }
            } else {
                $output .= \sprintf('msgid "%s"'."\n", $this->escape($source));
                $output .= \sprintf('msgstr "%s"'."\n", $this->escape($target));
            }
        }

        return $output;
    }

    private function getStandardRules(string $id): array
    {
        // Partly copied from TranslatorTrait::trans.
        $parts = [];
        if (preg_match('/^\|++$/', $id)) {
            $parts = explode('|', $id);
        } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
            $parts = $matches[0];
        }

        $intervalRegexp = <<<'EOF'
            /^(?P<interval>
                ({\s*
                    (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
                \s*})

                    |

                (?P<left_delimiter>[\[\]])
                    \s*
                    (?P<left>-Inf|\-?\d+(\.\d+)?)
                    \s*,\s*
                    (?P<right>\+?Inf|\-?\d+(\.\d+)?)
                    \s*
                (?P<right_delimiter>[\[\]])
            )\s*(?P<message>.*?)$/xs
            EOF;

        $standardRules = [];
        foreach ($parts as $part) {
            $part = trim(str_replace('||', '|', $part));

            if (preg_match($intervalRegexp, $part)) {
                // Explicit rule is not a standard rule.
                return [];
            }

            $standardRules[] = $part;
        }

        return $standardRules;
    }

    protected function getExtension(): string
    {
        return 'po';
    }

    private function escape(string $str): string
    {
        return addcslashes($str, "\0..\37\42\134");
    }

    private function formatComments(string|array $comments, string $prefix = ''): ?string
    {
        $output = null;

        foreach ((array) $comments as $comment) {
            $output .= \sprintf('#%s %s'."\n", $prefix, $comment);
        }

        return $output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * DumperInterface is the interface implemented by all translation dumpers.
 * There is no common option.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface DumperInterface
{
    /**
     * Dumps the message catalogue.
     *
     * @param array $options Options that are used by the dumper
     */
    public function dump(MessageCatalogue $messages, array $options = []): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class IcuResFileDumper extends FileDumper
{
    protected string $relativePathTemplate = '%domain%/%locale%.%extension%';

    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $data = $indexes = $resources = '';

        foreach ($messages->all($domain) as $source => $target) {
            $indexes .= pack('v', \strlen($data) + 28);
            $data .= $source."\0";
        }

        $data .= $this->writePadding($data);

        $keyTop = $this->getPosition($data);

        foreach ($messages->all($domain) as $source => $target) {
            $resources .= pack('V', $this->getPosition($data));

            $data .= pack('V', \strlen($target))
                .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
                .$this->writePadding($data)
            ;
        }

        $resOffset = $this->getPosition($data);

        $data .= pack('v', \count($messages->all($domain)))
            .$indexes
            .$this->writePadding($data)
            .$resources
        ;

        $bundleTop = $this->getPosition($data);

        $root = pack('V7',
            $resOffset + (2 << 28), // Resource Offset + Resource Type
            6,                      // Index length
            $keyTop,                        // Index keys top
            $bundleTop,                     // Index resources top
            $bundleTop,                     // Index bundle top
            \count($messages->all($domain)), // Index max table length
            0                               // Index attributes
        );

        $header = pack('vC2v4C12@32',
            32,                     // Header size
            0xDA, 0x27,             // Magic number 1 and 2
            20, 0, 0, 2,            // Rest of the header, ..., Size of a char
            0x52, 0x65, 0x73, 0x42, // Data format identifier
            1, 2, 0, 0,             // Data version
            1, 4, 0, 0              // Unicode version
        );

        return $header.$root.$data;
    }

    private function writePadding(string $data): ?string
    {
        $padding = \strlen($data) % 4;

        return $padding ? str_repeat("\xAA", 4 - $padding) : null;
    }

    private function getPosition(string $data): float|int
    {
        return (\strlen($data) + 28) / 4;
    }

    protected function getExtension(): string
    {
        return 'res';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * QtFileDumper generates ts files from a message catalogue.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class QtFileDumper extends FileDumper
{
    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;
        $ts = $dom->appendChild($dom->createElement('TS'));
        $context = $ts->appendChild($dom->createElement('context'));
        $context->appendChild($dom->createElement('name', $domain));

        foreach ($messages->all($domain) as $source => $target) {
            $message = $context->appendChild($dom->createElement('message'));
            $metadata = $messages->getMetadata($source, $domain);
            if (isset($metadata['sources'])) {
                foreach ((array) $metadata['sources'] as $location) {
                    $loc = explode(':', $location, 2);
                    $location = $message->appendChild($dom->createElement('location'));
                    $location->setAttribute('filename', $loc[0]);
                    if (isset($loc[1])) {
                        $location->setAttribute('line', $loc[1]);
                    }
                }
            }
            $message->appendChild($dom->createElement('source', $source));
            $message->appendChild($dom->createElement('translation', $target));
        }

        return $dom->saveXML();
    }

    protected function getExtension(): string
    {
        return 'ts';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * PhpFileDumper generates PHP files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class PhpFileDumper extends FileDumper
{
    public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
    {
        return "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";
    }

    protected function getExtension(): string
    {
        return 'php';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * LoaderInterface is the interface implemented by all translation loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderInterface
{
    /**
     * Loads a locale.
     *
     * @throws NotFoundResourceException when the resource cannot be found
     * @throws InvalidResourceException  when the resource cannot be loaded
     */
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;

/**
 * JsonFileLoader loads translations from an json file.
 *
 * @author singles
 */
class JsonFileLoader extends FileLoader
{
    protected function loadResource(string $resource): array
    {
        $messages = [];
        if ($data = file_get_contents($resource)) {
            $messages = json_decode($data, true);

            if (0 < $errorCode = json_last_error()) {
                throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode));
            }
        }

        return $messages;
    }

    /**
     * Translates JSON_ERROR_* constant into meaningful message.
     */
    private function getJSONErrorMessage(int $errorCode): string
    {
        return match ($errorCode) {
            \JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
            \JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
            \JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
            \JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
            \JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
            default => 'Unknown error',
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

/**
 * IniFileLoader loads translations from an ini file.
 *
 * @author stealth35
 */
class IniFileLoader extends FileLoader
{
    protected function loadResource(string $resource): array
    {
        return parse_ini_file($resource, true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Resource\DirectoryResource;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * IcuResFileLoader loads translations from a resource bundle.
 *
 * @author stealth35
 */
class IcuResFileLoader implements LoaderInterface
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
        }

        if (!is_dir($resource)) {
            throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
        }

        try {
            $rb = new \ResourceBundle($locale, $resource);
        } catch (\Exception) {
            $rb = null;
        }

        if (!$rb) {
            throw new InvalidResourceException(\sprintf('Cannot load resource "%s".', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);

        if (class_exists(DirectoryResource::class)) {
            $catalogue->addResource(new DirectoryResource($resource));
        }

        return $catalogue;
    }

    /**
     * Flattens an ResourceBundle.
     *
     * The scheme used is:
     *   key { key2 { key3 { "value" } } }
     * Becomes:
     *   'key.key2.key3' => 'value'
     *
     * This function takes an array by reference and will modify it
     *
     * @param \ResourceBundle $rb       The ResourceBundle that will be flattened
     * @param array           $messages Used internally for recursive calls
     * @param string|null     $path     Current path being parsed, used internally for recursive calls
     */
    protected function flatten(\ResourceBundle $rb, array &$messages = [], ?string $path = null): array
    {
        foreach ($rb as $key => $value) {
            $nodePath = $path ? $path.'.'.$key : $key;
            if ($value instanceof \ResourceBundle) {
                $this->flatten($value, $messages, $nodePath);
            } else {
                $messages[$nodePath] = $value;
            }
        }

        return $messages;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\NotFoundResourceException;

/**
 * CsvFileLoader loads translations from CSV files.
 *
 * @author Saša Stamenković <umpirsky@gmail.com>
 */
class CsvFileLoader extends FileLoader
{
    private string $delimiter = ';';
    private string $enclosure = '"';
    /**
     * @deprecated since Symfony 7.2, to be removed in 8.0
     */
    private string $escape = '';

    protected function loadResource(string $resource): array
    {
        $messages = [];

        try {
            $file = new \SplFileObject($resource, 'rb');
        } catch (\RuntimeException $e) {
            throw new NotFoundResourceException(\sprintf('Error opening file "%s".', $resource), 0, $e);
        }

        $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY | \SplFileObject::DROP_NEW_LINE);
        $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);

        foreach ($file as $data) {
            if (false === $data) {
                continue;
            }

            if (!str_starts_with($data[0], '#') && isset($data[1]) && 2 === \count($data)) {
                $messages[$data[0]] = $data[1];
            }
        }

        return $messages;
    }

    /**
     * Sets the delimiter, enclosure, and escape character for CSV.
     */
    public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = ''): void
    {
        $this->delimiter = $delimiter;
        $this->enclosure = $enclosure;
        if ('' !== $escape) {
            trigger_deprecation('symfony/translation', '7.2', 'The "escape" parameter of the "%s" method is deprecated. It will be removed in 8.0.', __METHOD__);
        }

        $this->escape = $escape;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

/**
 * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium
 * @copyright Copyright (c) 2012, Clemens Tolboom
 */
class PoFileLoader extends FileLoader
{
    /**
     * Parses portable object (PO) format.
     *
     * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
     * we should be able to parse files having:
     *
     * white-space
     * #  translator-comments
     * #. extracted-comments
     * #: reference...
     * #, flag...
     * #| msgid previous-untranslated-string
     * msgid untranslated-string
     * msgstr translated-string
     *
     * extra or different lines are:
     *
     * #| msgctxt previous-context
     * #| msgid previous-untranslated-string
     * msgctxt context
     *
     * #| msgid previous-untranslated-string-singular
     * #| msgid_plural previous-untranslated-string-plural
     * msgid untranslated-string-singular
     * msgid_plural untranslated-string-plural
     * msgstr[0] translated-string-case-0
     * ...
     * msgstr[N] translated-string-case-n
     *
     * The definition states:
     * - white-space and comments are optional.
     * - msgid "" that an empty singleline defines a header.
     *
     * This parser sacrifices some features of the reference implementation the
     * differences to that implementation are as follows.
     * - No support for comments spanning multiple lines.
     * - Translator and extracted comments are treated as being the same type.
     * - Message IDs are allowed to have other encodings as just US-ASCII.
     *
     * Items with an empty id are ignored.
     */
    protected function loadResource(string $resource): array
    {
        $stream = fopen($resource, 'r');

        $defaults = [
            'ids' => [],
            'translated' => null,
        ];

        $messages = [];
        $item = $defaults;
        $flags = [];

        while ($line = fgets($stream)) {
            $line = trim($line);

            if ('' === $line) {
                // Whitespace indicated current item is done
                if (!\in_array('fuzzy', $flags, true)) {
                    $this->addMessage($messages, $item);
                }
                $item = $defaults;
                $flags = [];
            } elseif (str_starts_with($line, '#,')) {
                $flags = array_map('trim', explode(',', substr($line, 2)));
            } elseif (str_starts_with($line, 'msgid "')) {
                // We start a new msg so save previous
                // TODO: this fails when comments or contexts are added
                $this->addMessage($messages, $item);
                $item = $defaults;
                $item['ids']['singular'] = substr($line, 7, -1);
            } elseif (str_starts_with($line, 'msgstr "')) {
                $item['translated'] = substr($line, 8, -1);
            } elseif ('"' === $line[0]) {
                $continues = isset($item['translated']) ? 'translated' : 'ids';

                if (\is_array($item[$continues])) {
                    end($item[$continues]);
                    $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
                } else {
                    $item[$continues] .= substr($line, 1, -1);
                }
            } elseif (str_starts_with($line, 'msgid_plural "')) {
                $item['ids']['plural'] = substr($line, 14, -1);
            } elseif (str_starts_with($line, 'msgstr[')) {
                $size = strpos($line, ']');
                $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
            }
        }
        // save last item
        if (!\in_array('fuzzy', $flags, true)) {
            $this->addMessage($messages, $item);
        }
        fclose($stream);

        return $messages;
    }

    /**
     * Save a translation item to the messages.
     *
     * A .po file could contain by error missing plural indexes. We need to
     * fix these before saving them.
     */
    private function addMessage(array &$messages, array $item): void
    {
        if (!empty($item['ids']['singular'])) {
            $id = stripcslashes($item['ids']['singular']);
            if (isset($item['ids']['plural'])) {
                $id .= '|'.stripcslashes($item['ids']['plural']);
            }

            $translated = (array) $item['translated'];
            // PO are by definition indexed so sort by index.
            ksort($translated);
            // Make sure every index is filled.
            end($translated);
            $count = key($translated);
            // Fill missing spots with '-'.
            $empties = array_fill(0, $count + 1, '-');
            $translated += $empties;
            ksort($translated);

            $messages[$id] = stripcslashes(implode('|', $translated));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
abstract class FileLoader extends ArrayLoader
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
        }

        $messages = $this->loadResource($resource);

        // empty resource
        $messages ??= [];

        // not an array
        if (!\is_array($messages)) {
            throw new InvalidResourceException(\sprintf('Unable to load file "%s".', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);

        if (class_exists(FileResource::class)) {
            $catalogue->addResource(new FileResource($resource));
        }

        return $catalogue;
    }

    /**
     * @throws InvalidResourceException if stream content has an invalid format
     */
    abstract protected function loadResource(string $resource): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * QtFileLoader loads translations from QT Translations XML files.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class QtFileLoader implements LoaderInterface
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!class_exists(XmlUtils::class)) {
            throw new RuntimeException('Loading translations from the QT format requires the Symfony Config component.');
        }

        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
        }

        try {
            $dom = XmlUtils::loadFile($resource);
        } catch (\InvalidArgumentException $e) {
            throw new InvalidResourceException(\sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
        }

        $internalErrors = libxml_use_internal_errors(true);
        libxml_clear_errors();

        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');

        $catalogue = new MessageCatalogue($locale);
        if (1 == $nodes->length) {
            $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
            foreach ($translations as $translation) {
                $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;

                if ($translationValue) {
                    $catalogue->set(
                        (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
                        $translationValue,
                        $domain
                    );
                }
            }

            if (class_exists(FileResource::class)) {
                $catalogue->addResource(new FileResource($resource));
            }
        }

        libxml_use_internal_errors($internalErrors);

        return $catalogue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

/**
 * PhpFileLoader loads translations from PHP files returning an array of translations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpFileLoader extends FileLoader
{
    private static ?array $cache = [];

    protected function loadResource(string $resource): array
    {
        if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOL))) {
            self::$cache = null;
        }

        if (null === self::$cache) {
            return require $resource;
        }

        return self::$cache[$resource] ??= require $resource;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Util\Exception\InvalidXmlException;
use Symfony\Component\Config\Util\Exception\XmlParsingException;
use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Util\XliffUtils;

/**
 * XliffFileLoader loads translations from XLIFF files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class XliffFileLoader implements LoaderInterface
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!class_exists(XmlUtils::class)) {
            throw new RuntimeException('Loading translations from the Xliff format requires the Symfony Config component.');
        }

        if (!$this->isXmlString($resource)) {
            if (!stream_is_local($resource)) {
                throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
            }

            if (!file_exists($resource)) {
                throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
            }

            if (!is_file($resource)) {
                throw new InvalidResourceException(\sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
            }
        }

        try {
            if ($this->isXmlString($resource)) {
                $dom = XmlUtils::parse($resource);
            } else {
                $dom = XmlUtils::loadFile($resource);
            }
        } catch (\InvalidArgumentException|XmlParsingException|InvalidXmlException $e) {
            throw new InvalidResourceException(\sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e);
        }

        if ($errors = XliffUtils::validateSchema($dom)) {
            throw new InvalidResourceException(\sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors));
        }

        $catalogue = new MessageCatalogue($locale);
        $this->extract($dom, $catalogue, $domain);

        if (is_file($resource) && class_exists(FileResource::class)) {
            $catalogue->addResource(new FileResource($resource));
        }

        return $catalogue;
    }

    private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain): void
    {
        $xliffVersion = XliffUtils::getVersionNumber($dom);

        if ('1.2' === $xliffVersion) {
            $this->extractXliff1($dom, $catalogue, $domain);
        }

        if ('2.0' === $xliffVersion) {
            $this->extractXliff2($dom, $catalogue, $domain);
        }
    }

    /**
     * Extract messages and metadata from DOMDocument into a MessageCatalogue.
     */
    private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain): void
    {
        $xml = simplexml_import_dom($dom);
        $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;

        $namespace = 'urn:oasis:names:tc:xliff:document:1.2';
        $xml->registerXPathNamespace('xliff', $namespace);

        foreach ($xml->xpath('//xliff:file') as $file) {
            $fileAttributes = $file->attributes();

            $file->registerXPathNamespace('xliff', $namespace);

            foreach ($file->xpath('.//xliff:prop') as $prop) {
                $catalogue->setCatalogueMetadata($prop->attributes()['prop-type'], (string) $prop, $domain);
            }

            foreach ($file->xpath('.//xliff:trans-unit') as $translation) {
                $attributes = $translation->attributes();

                if (!(isset($attributes['resname']) || isset($translation->source))) {
                    continue;
                }

                $source = (string) (isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source);

                if (isset($translation->target)
                    && 'needs-translation' === (string) $translation->target->attributes()['state']
                    && \in_array((string) $translation->target, [$source, (string) $translation->source], true)
                ) {
                    continue;
                }

                // If the xlf file has another encoding specified, try to convert it because
                // simple_xml will always return utf-8 encoded values
                $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding);

                $catalogue->set($source, $target, $domain);

                $metadata = [
                    'source' => (string) $translation->source,
                    'file' => [
                        'original' => (string) $fileAttributes['original'],
                    ],
                ];
                if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
                    $metadata['notes'] = $notes;
                }

                if (isset($translation->target) && $translation->target->attributes()) {
                    $metadata['target-attributes'] = [];
                    foreach ($translation->target->attributes() as $key => $value) {
                        $metadata['target-attributes'][$key] = (string) $value;
                    }
                }

                if (isset($attributes['id'])) {
                    $metadata['id'] = (string) $attributes['id'];
                }

                $catalogue->setMetadata($source, $metadata, $domain);
            }
        }
    }

    private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain): void
    {
        $xml = simplexml_import_dom($dom);
        $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;

        $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');

        foreach ($xml->xpath('//xliff:unit') as $unit) {
            foreach ($unit->segment as $segment) {
                $attributes = $unit->attributes();
                $source = $attributes['name'] ?? $segment->source;

                // If the xlf file has another encoding specified, try to convert it because
                // simple_xml will always return utf-8 encoded values
                $target = $this->utf8ToCharset((string) ($segment->target ?? $segment->source), $encoding);

                $catalogue->set((string) $source, $target, $domain);

                $metadata = [];
                if ($segment->attributes()) {
                    $metadata['segment-attributes'] = [];
                    foreach ($segment->attributes() as $key => $value) {
                        $metadata['segment-attributes'][$key] = (string) $value;
                    }
                }

                if (isset($segment->target) && $segment->target->attributes()) {
                    $metadata['target-attributes'] = [];
                    foreach ($segment->target->attributes() as $key => $value) {
                        $metadata['target-attributes'][$key] = (string) $value;
                    }
                }

                if (isset($unit->notes)) {
                    $metadata['notes'] = [];
                    foreach ($unit->notes->note as $noteNode) {
                        $note = [];
                        foreach ($noteNode->attributes() as $key => $value) {
                            $note[$key] = (string) $value;
                        }
                        $note['content'] = (string) $noteNode;
                        $metadata['notes'][] = $note;
                    }
                }

                $catalogue->setMetadata((string) $source, $metadata, $domain);
            }
        }
    }

    /**
     * Convert a UTF8 string to the specified encoding.
     */
    private function utf8ToCharset(string $content, ?string $encoding = null): string
    {
        if ('UTF-8' !== $encoding && $encoding) {
            return mb_convert_encoding($content, $encoding, 'UTF-8');
        }

        return $content;
    }

    private function parseNotesMetadata(?\SimpleXMLElement $noteElement = null, ?string $encoding = null): array
    {
        $notes = [];

        if (null === $noteElement) {
            return $notes;
        }

        /** @var \SimpleXMLElement $xmlNote */
        foreach ($noteElement as $xmlNote) {
            $noteAttributes = $xmlNote->attributes();
            $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)];
            if (isset($noteAttributes['priority'])) {
                $note['priority'] = (int) $noteAttributes['priority'];
            }

            if (isset($noteAttributes['from'])) {
                $note['from'] = (string) $noteAttributes['from'];
            }

            $notes[] = $note;
        }

        return $notes;
    }

    private function isXmlString(string $resource): bool
    {
        return str_starts_with($resource, '<?xml');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Yaml\Yaml;

/**
 * YamlFileLoader loads translations from Yaml files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class YamlFileLoader extends FileLoader
{
    private YamlParser $yamlParser;

    protected function loadResource(string $resource): array
    {
        if (!isset($this->yamlParser)) {
            if (!class_exists(YamlParser::class)) {
                throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.');
            }

            $this->yamlParser = new YamlParser();
        }

        try {
            $messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT);
        } catch (ParseException $e) {
            throw new InvalidResourceException(\sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e);
        }

        if (null !== $messages && !\is_array($messages)) {
            throw new InvalidResourceException(\sprintf('Unable to load file "%s".', $resource));
        }

        return $messages ?: [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * IcuResFileLoader loads translations from a resource bundle.
 *
 * @author stealth35
 */
class IcuDatFileLoader extends IcuResFileLoader
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!stream_is_local($resource.'.dat')) {
            throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource.'.dat')) {
            throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
        }

        try {
            $rb = new \ResourceBundle($locale, $resource);
        } catch (\Exception) {
            $rb = null;
        }

        if (!$rb) {
            throw new InvalidResourceException(\sprintf('Cannot load resource "%s".', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);

        if (class_exists(FileResource::class)) {
            $catalogue->addResource(new FileResource($resource.'.dat'));
        }

        return $catalogue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;

/**
 * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
 */
class MoFileLoader extends FileLoader
{
    /**
     * Magic used for validating the format of an MO file as well as
     * detecting if the machine used to create that file was little endian.
     */
    public const MO_LITTLE_ENDIAN_MAGIC = 0x950412DE;

    /**
     * Magic used for validating the format of an MO file as well as
     * detecting if the machine used to create that file was big endian.
     */
    public const MO_BIG_ENDIAN_MAGIC = 0xDE120495;

    /**
     * The size of the header of an MO file in bytes.
     */
    public const MO_HEADER_SIZE = 28;

    /**
     * Parses machine object (MO) format, independent of the machine's endian it
     * was created on. Both 32bit and 64bit systems are supported.
     */
    protected function loadResource(string $resource): array
    {
        $stream = fopen($resource, 'r');

        $stat = fstat($stream);

        if ($stat['size'] < self::MO_HEADER_SIZE) {
            throw new InvalidResourceException('MO stream content has an invalid format.');
        }
        $magic = unpack('V1', fread($stream, 4));
        $magic = hexdec(substr(dechex(current($magic)), -8));

        if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
            $isBigEndian = false;
        } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
            $isBigEndian = true;
        } else {
            throw new InvalidResourceException('MO stream content has an invalid format.');
        }

        // formatRevision
        $this->readLong($stream, $isBigEndian);
        $count = $this->readLong($stream, $isBigEndian);
        $offsetId = $this->readLong($stream, $isBigEndian);
        $offsetTranslated = $this->readLong($stream, $isBigEndian);
        // sizeHashes
        $this->readLong($stream, $isBigEndian);
        // offsetHashes
        $this->readLong($stream, $isBigEndian);

        $messages = [];

        for ($i = 0; $i < $count; ++$i) {
            $pluralId = null;
            $translated = null;

            fseek($stream, $offsetId + $i * 8);

            $length = $this->readLong($stream, $isBigEndian);
            $offset = $this->readLong($stream, $isBigEndian);

            if ($length < 1) {
                continue;
            }

            fseek($stream, $offset);
            $singularId = fread($stream, $length);

            if (str_contains($singularId, "\000")) {
                [$singularId, $pluralId] = explode("\000", $singularId);
            }

            fseek($stream, $offsetTranslated + $i * 8);
            $length = $this->readLong($stream, $isBigEndian);
            $offset = $this->readLong($stream, $isBigEndian);

            if ($length < 1) {
                continue;
            }

            fseek($stream, $offset);
            $translated = fread($stream, $length);

            if (str_contains($translated, "\000")) {
                $translated = explode("\000", $translated);
            }

            $ids = ['singular' => $singularId, 'plural' => $pluralId];
            $item = compact('ids', 'translated');

            if (!empty($item['ids']['singular'])) {
                $id = $item['ids']['singular'];
                if (isset($item['ids']['plural'])) {
                    $id .= '|'.$item['ids']['plural'];
                }
                $messages[$id] = stripcslashes(implode('|', (array) $item['translated']));
            }
        }

        fclose($stream);

        return array_filter($messages);
    }

    /**
     * Reads an unsigned long from stream respecting endianness.
     *
     * @param resource $stream
     */
    private function readLong($stream, bool $isBigEndian): int
    {
        $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
        $result = current($result);

        return (int) substr($result, -8);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * ArrayLoader loads translations from a PHP array.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ArrayLoader implements LoaderInterface
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        $resource = $this->flatten($resource);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($resource, $domain);

        return $catalogue;
    }

    /**
     * Flattens an nested array of translations.
     *
     * The scheme used is:
     *   'key' => ['key2' => ['key3' => 'value']]
     * Becomes:
     *   'key.key2.key3' => 'value'
     */
    private function flatten(array $messages): array
    {
        $result = [];
        foreach ($messages as $key => $value) {
            if (\is_array($value)) {
                foreach ($this->flatten($value) as $k => $v) {
                    if (null !== $v) {
                        $result[$key.'.'.$k] = $v;
                    }
                }
            } elseif (null !== $value) {
                $result[$key] = $value;
            }
        }

        return $result;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Writer;

use Symfony\Component\Translation\Dumper\DumperInterface;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * TranslationWriter writes translation messages.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class TranslationWriter implements TranslationWriterInterface
{
    /**
     * @var array<string, DumperInterface>
     */
    private array $dumpers = [];

    /**
     * Adds a dumper to the writer.
     */
    public function addDumper(string $format, DumperInterface $dumper): void
    {
        $this->dumpers[$format] = $dumper;
    }

    /**
     * Obtains the list of supported formats.
     */
    public function getFormats(): array
    {
        return array_keys($this->dumpers);
    }

    /**
     * Writes translation from the catalogue according to the selected format.
     *
     * @param string $format  The format to use to dump the messages
     * @param array  $options Options that are passed to the dumper
     *
     * @throws InvalidArgumentException
     */
    public function write(MessageCatalogue $catalogue, string $format, array $options = []): void
    {
        if (!isset($this->dumpers[$format])) {
            throw new InvalidArgumentException(\sprintf('There is no dumper associated with format "%s".', $format));
        }

        // get the right dumper
        $dumper = $this->dumpers[$format];

        if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0o777, true) && !is_dir($options['path'])) {
            throw new RuntimeException(\sprintf('Translation Writer was not able to create directory "%s".', $options['path']));
        }

        // save
        $dumper->dump($catalogue, $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Writer;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * TranslationWriter writes translation messages.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface TranslationWriterInterface
{
    /**
     * Writes translation from the catalogue according to the selected format.
     *
     * @param string $format  The format to use to dump the messages
     * @param array  $options Options that are passed to the dumper
     *
     * @throws InvalidArgumentException
     */
    public function write(MessageCatalogue $catalogue, string $format, array $options = []): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\Resource\ResourceInterface;

/**
 * MessageCatalogueInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface MessageCatalogueInterface
{
    public const INTL_DOMAIN_SUFFIX = '+intl-icu';

    /**
     * Gets the catalogue locale.
     */
    public function getLocale(): string;

    /**
     * Gets the domains.
     */
    public function getDomains(): array;

    /**
     * Gets the messages within a given domain.
     *
     * If $domain is null, it returns all messages.
     */
    public function all(?string $domain = null): array;

    /**
     * Sets a message translation.
     *
     * @param string $id          The message id
     * @param string $translation The messages translation
     * @param string $domain      The domain name
     */
    public function set(string $id, string $translation, string $domain = 'messages'): void;

    /**
     * Checks if a message has a translation.
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     */
    public function has(string $id, string $domain = 'messages'): bool;

    /**
     * Checks if a message has a translation (it does not take into account the fallback mechanism).
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     */
    public function defines(string $id, string $domain = 'messages'): bool;

    /**
     * Gets a message translation.
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     */
    public function get(string $id, string $domain = 'messages'): string;

    /**
     * Sets translations for a given domain.
     *
     * @param array  $messages An array of translations
     * @param string $domain   The domain name
     */
    public function replace(array $messages, string $domain = 'messages'): void;

    /**
     * Adds translations for a given domain.
     *
     * @param array  $messages An array of translations
     * @param string $domain   The domain name
     */
    public function add(array $messages, string $domain = 'messages'): void;

    /**
     * Merges translations from the given Catalogue into the current one.
     *
     * The two catalogues must have the same locale.
     */
    public function addCatalogue(self $catalogue): void;

    /**
     * Merges translations from the given Catalogue into the current one
     * only when the translation does not exist.
     *
     * This is used to provide default translations when they do not exist for the current locale.
     */
    public function addFallbackCatalogue(self $catalogue): void;

    /**
     * Gets the fallback catalogue.
     */
    public function getFallbackCatalogue(): ?self;

    /**
     * Returns an array of resources loaded to build this collection.
     *
     * @return ResourceInterface[]
     */
    public function getResources(): array;

    /**
     * Adds a resource for this collection.
     */
    public function addResource(ResourceInterface $resource): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Formatter;

use Symfony\Component\Translation\IdentityTranslator;
use Symfony\Contracts\Translation\TranslatorInterface;

// Help opcache.preload discover always-needed symbols
class_exists(IntlFormatter::class);

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterface
{
    private TranslatorInterface $translator;
    private IntlFormatterInterface $intlFormatter;

    /**
     * @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization
     */
    public function __construct(?TranslatorInterface $translator = null, ?IntlFormatterInterface $intlFormatter = null)
    {
        $this->translator = $translator ?? new IdentityTranslator();
        $this->intlFormatter = $intlFormatter ?? new IntlFormatter();
    }

    public function format(string $message, string $locale, array $parameters = []): string
    {
        return $this->translator->trans($message, $parameters, null, $locale);
    }

    public function formatIntl(string $message, string $locale, array $parameters = []): string
    {
        return $this->intlFormatter->formatIntl($message, $locale, $parameters);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Formatter;

/**
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
interface MessageFormatterInterface
{
    /**
     * Formats a localized message pattern with given arguments.
     *
     * @param string $message    The message (may also be an object that can be cast to string)
     * @param string $locale     The message locale
     * @param array  $parameters An array of parameters for the message
     */
    public function format(string $message, string $locale, array $parameters = []): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Formatter;

/**
 * Formats ICU message patterns.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface IntlFormatterInterface
{
    /**
     * Formats a localized message using rules defined by ICU MessageFormat.
     *
     * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details
     */
    public function formatIntl(string $message, string $locale, array $parameters = []): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Formatter;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\LogicException;

/**
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class IntlFormatter implements IntlFormatterInterface
{
    private bool $hasMessageFormatter;
    private array $cache = [];

    public function formatIntl(string $message, string $locale, array $parameters = []): string
    {
        // MessageFormatter constructor throws an exception if the message is empty
        if ('' === $message) {
            return '';
        }

        if (!$formatter = $this->cache[$locale][$message] ?? null) {
            if (!$this->hasMessageFormatter ??= class_exists(\MessageFormatter::class)) {
                throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.');
            }
            try {
                $this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message);
            } catch (\IntlException $e) {
                throw new InvalidArgumentException(\sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e);
            }
        }

        foreach ($parameters as $key => $value) {
            if (\in_array($key[0] ?? null, ['%', '{'], true)) {
                unset($parameters[$key]);
                $parameters[trim($key, '%{ }')] = $value;
            }
        }

        if (false === $message = $formatter->format($parameters)) {
            throw new InvalidArgumentException(\sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage());
        }

        return $message;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Routing\RequestContext;
use Symfony\Contracts\Translation\LocaleAwareInterface;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class LocaleSwitcher implements LocaleAwareInterface
{
    private string $defaultLocale;

    /**
     * @param LocaleAwareInterface[] $localeAwareServices
     */
    public function __construct(
        private string $locale,
        private iterable $localeAwareServices,
        private ?RequestContext $requestContext = null,
    ) {
        $this->defaultLocale = $locale;
    }

    public function setLocale(string $locale): void
    {
        // Silently ignore if the intl extension is not loaded
        try {
            if (class_exists(\Locale::class, false)) {
                \Locale::setDefault($locale);
            }
        } catch (\Exception) {
        }

        $this->locale = $locale;
        $this->requestContext?->setParameter('_locale', $locale);

        foreach ($this->localeAwareServices as $service) {
            $service->setLocale($locale);
        }
    }

    public function getLocale(): string
    {
        return $this->locale;
    }

    /**
     * Switch to a new locale, execute a callback, then switch back to the original.
     *
     * @template T
     *
     * @param callable(string $locale):T $callback
     *
     * @return T
     */
    public function runWithLocale(string $locale, callable $callback): mixed
    {
        $original = $this->getLocale();
        $this->setLocale($locale);

        try {
            return $callback($locale);
        } finally {
            $this->setLocale($original);
        }
    }

    public function reset(): void
    {
        $this->setLocale($this->defaultLocale);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

if (!\function_exists(t::class)) {
    /**
     * @author Nate Wiebe <nate@northern.co>
     */
    function t(string $message, array $parameters = [], ?string $domain = null): TranslatableMessage
    {
        return new TranslatableMessage($message, $parameters, $domain);
    }
}
<?xml version='1.0'?>
<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns ="http://www.w3.org/1999/xhtml"
  xml:lang="en">

 <xs:annotation>
  <xs:documentation>
   <div>
    <h1>About the XML namespace</h1>

    <div class="bodytext">
     <p>

      This schema document describes the XML namespace, in a form
      suitable for import by other schema documents.
     </p>
     <p>
      See <a href="http://www.w3.org/XML/1998/namespace.html">
      http://www.w3.org/XML/1998/namespace.html</a> and
      <a href="http://www.w3.org/TR/REC-xml">
      http://www.w3.org/TR/REC-xml</a> for information 
      about this namespace.
     </p>

     <p>
      Note that local names in this namespace are intended to be
      defined only by the World Wide Web Consortium or its subgroups.
      The names currently defined in this namespace are listed below.
      They should not be used with conflicting semantics by any Working
      Group, specification, or document instance.
     </p>
     <p>   
      See further below in this document for more information about <a
      href="#usage">how to refer to this schema document from your own
      XSD schema documents</a> and about <a href="#nsversioning">the
      namespace-versioning policy governing this schema document</a>.
     </p>
    </div>
   </div>

  </xs:documentation>
 </xs:annotation>

 <xs:attribute name="lang">
  <xs:annotation>
   <xs:documentation>
    <div>
     
      <h3>lang (as an attribute name)</h3>
      <p>

       denotes an attribute whose value
       is a language code for the natural language of the content of
       any element; its value is inherited.  This name is reserved
       by virtue of its definition in the XML specification.</p>
     
    </div>
    <div>
     <h4>Notes</h4>
     <p>
      Attempting to install the relevant ISO 2- and 3-letter
      codes as the enumerated possible values is probably never
      going to be a realistic possibility.  
     </p>
     <p>

      See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
       http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
      and the IANA language subtag registry at
      <a href="http://www.iana.org/assignments/language-subtag-registry">
       http://www.iana.org/assignments/language-subtag-registry</a>
      for further information.
     </p>
     <p>

      The union allows for the 'un-declaration' of xml:lang with
      the empty string.
     </p>
    </div>
   </xs:documentation>
  </xs:annotation>
  <xs:simpleType>
   <xs:union memberTypes="xs:language">
    <xs:simpleType>    
     <xs:restriction base="xs:string">
      <xs:enumeration value=""/>

     </xs:restriction>
    </xs:simpleType>
   </xs:union>
  </xs:simpleType>
 </xs:attribute>

 <xs:attribute name="space">
  <xs:annotation>
   <xs:documentation>

    <div>
     
      <h3>space (as an attribute name)</h3>
      <p>
       denotes an attribute whose
       value is a keyword indicating what whitespace processing
       discipline is intended for the content of the element; its
       value is inherited.  This name is reserved by virtue of its
       definition in the XML specification.</p>
     
    </div>
   </xs:documentation>
  </xs:annotation>
  <xs:simpleType>

   <xs:restriction base="xs:NCName">
    <xs:enumeration value="default"/>
    <xs:enumeration value="preserve"/>
   </xs:restriction>
  </xs:simpleType>
 </xs:attribute>
 
 <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
   <xs:documentation>

    <div>
     
      <h3>base (as an attribute name)</h3>
      <p>
       denotes an attribute whose value
       provides a URI to be used as the base for interpreting any
       relative URIs in the scope of the element on which it
       appears; its value is inherited.  This name is reserved
       by virtue of its definition in the XML Base specification.</p>
     
     <p>
      See <a
      href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
      for information about this attribute.
     </p>

    </div>
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 
 <xs:attribute name="id" type="xs:ID">
  <xs:annotation>
   <xs:documentation>
    <div>
     
      <h3>id (as an attribute name)</h3> 
      <p>

       denotes an attribute whose value
       should be interpreted as if declared to be of type ID.
       This name is reserved by virtue of its definition in the
       xml:id specification.</p>
     
     <p>
      See <a
      href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
      for information about this attribute.
     </p>
    </div>
   </xs:documentation>
  </xs:annotation>

 </xs:attribute>

 <xs:attributeGroup name="specialAttrs">
  <xs:attribute ref="xml:base"/>
  <xs:attribute ref="xml:lang"/>
  <xs:attribute ref="xml:space"/>
  <xs:attribute ref="xml:id"/>
 </xs:attributeGroup>

 <xs:annotation>

  <xs:documentation>
   <div>
   
    <h3>Father (in any context at all)</h3> 

    <div class="bodytext">
     <p>
      denotes Jon Bosak, the chair of 
      the original XML Working Group.  This name is reserved by 
      the following decision of the W3C XML Plenary and 
      XML Coordination groups:
     </p>
     <blockquote>
       <p>

	In appreciation for his vision, leadership and
	dedication the W3C XML Plenary on this 10th day of
	February, 2000, reserves for Jon Bosak in perpetuity
	the XML name "xml:Father".
       </p>
     </blockquote>
    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

 <xs:annotation>
  <xs:documentation>

   <div xml:id="usage" id="usage">
    <h2><a name="usage">About this schema document</a></h2>

    <div class="bodytext">
     <p>
      This schema defines attributes and an attribute group suitable
      for use by schemas wishing to allow <code>xml:base</code>,
      <code>xml:lang</code>, <code>xml:space</code> or
      <code>xml:id</code> attributes on elements they define.
     </p>

     <p>
      To enable this, such a schema must import this schema for
      the XML namespace, e.g. as follows:
     </p>
     <pre>
          &lt;schema.. .>
          .. .
           &lt;import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
     </pre>
     <p>
      or
     </p>
     <pre>

           &lt;import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
     </pre>
     <p>
      Subsequently, qualified reference to any of the attributes or the
      group defined below will have the desired effect, e.g.
     </p>
     <pre>
          &lt;type.. .>
          .. .
           &lt;attributeGroup ref="xml:specialAttrs"/>
     </pre>
     <p>
      will define a type which will schema-validate an instance element
      with any of those attributes.
     </p>

    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

 <xs:annotation>
  <xs:documentation>
   <div id="nsversioning" xml:id="nsversioning">
    <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>

    <div class="bodytext">
     <p>
      In keeping with the XML Schema WG's standard versioning
      policy, this schema document will persist at
      <a href="http://www.w3.org/2009/01/xml.xsd">
       http://www.w3.org/2009/01/xml.xsd</a>.
     </p>
     <p>
      At the date of issue it can also be found at
      <a href="http://www.w3.org/2001/xml.xsd">
       http://www.w3.org/2001/xml.xsd</a>.
     </p>

     <p>
      The schema document at that URI may however change in the future,
      in order to remain compatible with the latest version of XML
      Schema itself, or with the XML namespace itself.  In other words,
      if the XML Schema or XML namespaces change, the version of this
      document at <a href="http://www.w3.org/2001/xml.xsd">
       http://www.w3.org/2001/xml.xsd 
      </a> 
      will change accordingly; the version at 
      <a href="http://www.w3.org/2009/01/xml.xsd">
       http://www.w3.org/2009/01/xml.xsd 
      </a> 
      will not change.
     </p>
     <p>

      Previous dated (and unchanging) versions of this schema 
      document are at:
     </p>
     <ul>
      <li><a href="http://www.w3.org/2009/01/xml.xsd">
	http://www.w3.org/2009/01/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2007/08/xml.xsd">
	http://www.w3.org/2007/08/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2004/10/xml.xsd">

	http://www.w3.org/2004/10/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2001/03/xml.xsd">
	http://www.w3.org/2001/03/xml.xsd</a></li>
     </ul>
    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!--

    XLIFF Version 2.0
    OASIS Standard
    05 August 2014
    Copyright (c) OASIS Open 2014. All rights reserved.
    Source: http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/schemas/
     -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified"
    xmlns:xlf="urn:oasis:names:tc:xliff:document:2.0"
    targetNamespace="urn:oasis:names:tc:xliff:document:2.0">

  <!-- Import -->

  <xs:import namespace="http://www.w3.org/XML/1998/namespace"
      schemaLocation="informativeCopiesOf3rdPartySchemas/w3c/xml.xsd"/>

  <!-- Element Group -->

  <xs:group name="inline">
    <xs:choice>
      <xs:element ref="xlf:cp"/>
      <xs:element ref="xlf:ph"/>
      <xs:element ref="xlf:pc"/>
      <xs:element ref="xlf:sc"/>
      <xs:element ref="xlf:ec"/>
      <xs:element ref="xlf:mrk"/>
      <xs:element ref="xlf:sm"/>
      <xs:element ref="xlf:em"/>
    </xs:choice>
  </xs:group>

  <!-- Attribute Types -->

  <xs:simpleType name="yesNo">
    <xs:restriction base="xs:string">
      <xs:enumeration value="yes"/>
      <xs:enumeration value="no"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="yesNoFirstNo">
    <xs:restriction base="xs:string">
      <xs:enumeration value="yes"/>
      <xs:enumeration value="firstNo"/>
      <xs:enumeration value="no"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="dirValue">
    <xs:restriction base="xs:string">
      <xs:enumeration value="ltr"/>
      <xs:enumeration value="rtl"/>
      <xs:enumeration value="auto"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="appliesTo">
    <xs:restriction base="xs:string">
      <xs:enumeration value="source"/>
      <xs:enumeration value="target"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="userDefinedValue">
    <xs:restriction base="xs:string">
      <xs:pattern value="[^\s:]+:[^\s:]+"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="attrType_type">
    <xs:restriction base="xs:string">
      <xs:enumeration value="fmt"/>
      <xs:enumeration value="ui"/>
      <xs:enumeration value="quote"/>
      <xs:enumeration value="link"/>
      <xs:enumeration value="image"/>
      <xs:enumeration value="other"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="typeForMrkValues">
    <xs:restriction base="xs:NMTOKEN">
      <xs:enumeration value="generic"/>
      <xs:enumeration value="comment"/>
      <xs:enumeration value="term"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="attrType_typeForMrk">
    <xs:union memberTypes="xlf:typeForMrkValues xlf:userDefinedValue"/>
  </xs:simpleType>

  <xs:simpleType name="priorityValue">
    <xs:restriction base="xs:positiveInteger">
      <xs:minInclusive value="1"/>
      <xs:maxInclusive value="10"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="stateType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="initial"/>
      <xs:enumeration value="translated"/>
      <xs:enumeration value="reviewed"/>
      <xs:enumeration value="final"/>
    </xs:restriction>
  </xs:simpleType>

  <!-- Structural Elements -->

  <xs:element name="xliff">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:file"/>
      </xs:sequence>
      <xs:attribute name="version" use="required"/>
      <xs:attribute name="srcLang" use="required"/>
      <xs:attribute name="trgLang" use="optional"/>
      <xs:attribute ref="xml:space" use="optional" default="default"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="file">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:skeleton"/>
        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
            processContents="lax"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
        <xs:choice minOccurs="1" maxOccurs="unbounded">
          <xs:element ref="xlf:unit"/>
          <xs:element ref="xlf:group"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="canResegment" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="original" use="optional"/>
      <xs:attribute name="translate" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="srcDir" use="optional" type="xlf:dirValue" default="auto"/>
      <xs:attribute name="trgDir" use="optional" type="xlf:dirValue" default="auto"/>
      <xs:attribute ref="xml:space" use="optional"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="skeleton">
    <xs:complexType mixed="true">
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
            processContents="lax"/>
      </xs:sequence>
      <xs:attribute name="href" use="optional"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="group">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
            processContents="lax"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element ref="xlf:unit"/>
          <xs:element ref="xlf:group"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="name" use="optional"/>
      <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
      <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
      <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
      <xs:attribute ref="xml:space" use="optional"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="unit">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
            processContents="lax"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:originalData"/>
        <xs:choice minOccurs="1" maxOccurs="unbounded">
          <xs:element ref="xlf:segment"/>
          <xs:element ref="xlf:ignorable"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="name" use="optional"/>
      <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
      <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
      <xs:attribute ref="xml:space" use="optional"/>
      <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="segment">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
      </xs:sequence>
      <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="state" use="optional" type="xlf:stateType" default="initial"/>
      <xs:attribute name="subState" use="optional"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="ignorable">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
      </xs:sequence>
      <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="notes">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:note"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="note">
    <xs:complexType mixed="true">
      <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="appliesTo" use="optional" type="xlf:appliesTo"/>
      <xs:attribute name="category" use="optional"/>
      <xs:attribute name="priority" use="optional" type="xlf:priorityValue" default="1"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="originalData">
    <xs:complexType mixed="false">
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:data"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="data">
    <xs:complexType mixed="true">
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="xlf:cp"/>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="dir" use="optional" type="xlf:dirValue" default="auto"/>
      <xs:attribute ref="xml:space" use="optional" fixed="preserve"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="source">
    <xs:complexType mixed="true">
      <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
      <xs:attribute ref="xml:lang" use="optional"/>
      <xs:attribute ref="xml:space" use="optional"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="target">
    <xs:complexType mixed="true">
      <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
      <xs:attribute ref="xml:lang" use="optional"/>
      <xs:attribute ref="xml:space" use="optional"/>
      <xs:attribute name="order" use="optional" type="xs:positiveInteger"/>
    </xs:complexType>
  </xs:element>

  <!-- Inline Elements -->

  <xs:element name="cp">
    <!-- Code Point -->
    <xs:complexType mixed="false">
      <xs:attribute name="hex" use="required" type="xs:hexBinary"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="ph">
    <!-- Placeholder -->
    <xs:complexType mixed="false">
      <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
      <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="disp" use="optional"/>
      <xs:attribute name="equiv" use="optional"/>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
      <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
      <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="pc">
    <!-- Paired Code -->
    <xs:complexType mixed="true">
      <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
      <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
      <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="dispEnd" use="optional"/>
      <xs:attribute name="dispStart" use="optional"/>
      <xs:attribute name="equivEnd" use="optional"/>
      <xs:attribute name="equivStart" use="optional"/>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="dataRefEnd" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="dataRefStart" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="subFlowsEnd" use="optional" type="xs:NMTOKENS"/>
      <xs:attribute name="subFlowsStart" use="optional" type="xs:NMTOKENS"/>
      <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
      <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
      <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="sc">
    <!-- Start Code -->
    <xs:complexType mixed="false">
      <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
      <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
      <xs:attribute name="disp" use="optional"/>
      <xs:attribute name="equiv" use="optional"/>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
      <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
      <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
      <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="ec">
    <!-- End Code -->
    <xs:complexType mixed="false">
      <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
      <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
      <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
      <xs:attribute name="disp" use="optional"/>
      <xs:attribute name="equiv" use="optional"/>
      <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
      <xs:attribute name="startRef" use="optional" type="xs:NMTOKEN"/>
      <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
      <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
      <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="mrk">
    <!-- Annotation Marker -->
    <xs:complexType mixed="true">
      <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
      <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
      <xs:attribute name="value" use="optional"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="sm">
    <!-- Start Annotation Marker -->
    <xs:complexType mixed="false">
      <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
      <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
      <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
      <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
      <xs:attribute name="value" use="optional"/>
      <xs:anyAttribute namespace="##other" processContents="lax"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="em">
    <!-- End Annotation Marker -->
    <xs:complexType mixed="false">
      <xs:attribute name="startRef" use="required" type="xs:NMTOKEN"/>
    </xs:complexType>
  </xs:element>

</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!--

May-19-2004:
- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements
to <choice> itself.
- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
<alt-trans>.

Oct-2005
- updated version info to 1.2
- equiv-trans attribute to <trans-unit> element
- merged-trans attribute for <group> element
- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source>
- Create a new value "seg" for the mtype attribute of the <mrk> element
- Add mid as an optional attribute for the <alt-trans> element

Nov-14-2005
- Changed name attribute for <context-group> from required to optional
- Added extension point at <xliff>

Jan-9-2006
- Added alttranstype type attribute to <alt-trans>, and values

Jan-10-2006
- Corrected error with overwritten purposeValueList
- Corrected name="AttrType_Version",  attribute should have been "name"

-->
<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
  <!-- Import for xml:lang and xml:space -->
  <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
  <!-- Attributes Lists -->
  <xsd:simpleType name="XTend">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="x-[^\s]+"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="context-typeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="database">
        <xsd:annotation>
          <xsd:documentation>Indicates a database content.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="element">
        <xsd:annotation>
          <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="elementtitle">
        <xsd:annotation>
          <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="linenumber">
        <xsd:annotation>
          <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the &lt;source&gt; is found.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="numparams">
        <xsd:annotation>
          <xsd:documentation>Indicates a the number of parameters contained within the &lt;source&gt;.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="paramnotes">
        <xsd:annotation>
          <xsd:documentation>Indicates notes pertaining to the parameters in the &lt;source&gt;.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="record">
        <xsd:annotation>
          <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="recordtitle">
        <xsd:annotation>
          <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sourcefile">
        <xsd:annotation>
          <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original &lt;file&gt; attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="count-typeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="num-usages">
        <xsd:annotation>
          <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="repetition">
        <xsd:annotation>
          <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="total">
        <xsd:annotation>
          <xsd:documentation>Indicates a total count.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="InlineDelimitersValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'ctype' when used other elements than &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="bold">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="italic">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="underlined">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="link">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="InlinePlaceholdersValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'ctype' when used with &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="image">
        <xsd:annotation>
          <xsd:documentation>Indicates a inline image.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pb">
        <xsd:annotation>
          <xsd:documentation>Indicates a page break.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="lb">
        <xsd:annotation>
          <xsd:documentation>Indicates a line break.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="mime-typeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="datatypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="asp">
        <xsd:annotation>
          <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="c">
        <xsd:annotation>
          <xsd:documentation>Indicates C source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cdf">
        <xsd:annotation>
          <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cfm">
        <xsd:annotation>
          <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cpp">
        <xsd:annotation>
          <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="csharp">
        <xsd:annotation>
          <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cstring">
        <xsd:annotation>
          <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="csv">
        <xsd:annotation>
          <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="database">
        <xsd:annotation>
          <xsd:documentation>Indicates database data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="documentfooter">
        <xsd:annotation>
          <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="documentheader">
        <xsd:annotation>
          <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="filedialog">
        <xsd:annotation>
          <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="form">
        <xsd:annotation>
          <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="html">
        <xsd:annotation>
          <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="htmlbody">
        <xsd:annotation>
          <xsd:documentation>Indicates content within an HTML document’s &lt;body&gt; element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ini">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="interleaf">
        <xsd:annotation>
          <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javaclass">
        <xsd:annotation>
          <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javapropertyresourcebundle">
        <xsd:annotation>
          <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javalistresourcebundle">
        <xsd:annotation>
          <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javascript">
        <xsd:annotation>
          <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="jscript">
        <xsd:annotation>
          <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="layout">
        <xsd:annotation>
          <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="lisp">
        <xsd:annotation>
          <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="margin">
        <xsd:annotation>
          <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menufile">
        <xsd:annotation>
          <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="messagefile">
        <xsd:annotation>
          <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mif">
        <xsd:annotation>
          <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mimetype">
        <xsd:annotation>
          <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mo">
        <xsd:annotation>
          <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="msglib">
        <xsd:annotation>
          <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pagefooter">
        <xsd:annotation>
          <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pageheader">
        <xsd:annotation>
          <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="parameters">
        <xsd:annotation>
          <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pascal">
        <xsd:annotation>
          <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="php">
        <xsd:annotation>
          <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="plaintext">
        <xsd:annotation>
          <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="po">
        <xsd:annotation>
          <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="report">
        <xsd:annotation>
          <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="resources">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="resx">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rtf">
        <xsd:annotation>
          <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sgml">
        <xsd:annotation>
          <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sgmldtd">
        <xsd:annotation>
          <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="svg">
        <xsd:annotation>
          <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="vbscript">
        <xsd:annotation>
          <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="warning">
        <xsd:annotation>
          <xsd:documentation>Indicates warning message.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="winres">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xhtml">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xml">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xmldtd">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xsl">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xul">
        <xsd:annotation>
          <xsd:documentation>Indicates XUL elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="mtypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="abbrev">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="abbreviated-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="abbreviation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="acronym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="appellation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="collocation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="common-name">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="datetime">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="equation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="expanded-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="formula">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="head-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="initialism">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="international-scientific-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="internationalism">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="logical-expression">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="materials-management-unit">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="name">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="near-synonym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="part-number">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="phrase">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="phraseological-unit">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="protected">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="romanized-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="seg">
        <xsd:annotation>
          <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="set-phrase">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="short-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sku">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="standard-text">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="symbol">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="synonym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="synonymous-phrase">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="term">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="transcribed-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="transliterated-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="truncated-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="variant">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="restypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="auto3state">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="autocheckbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="autoradiobutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bitmap">
        <xsd:annotation>
          <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="button">
        <xsd:annotation>
          <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="caption">
        <xsd:annotation>
          <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cell">
        <xsd:annotation>
          <xsd:documentation>Indicates the cell in a table, for example the content of the &lt;td&gt; element in HTML.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkbox">
        <xsd:annotation>
          <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkboxmenuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkedlistbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="colorchooser">
        <xsd:annotation>
          <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="combobox">
        <xsd:annotation>
          <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="comboboxexitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="comboboxitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="component">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="contextmenu">
        <xsd:annotation>
          <xsd:documentation>Indicates a context menu.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ctext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cursor">
        <xsd:annotation>
          <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="datetimepicker">
        <xsd:annotation>
          <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="defpushbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dialog">
        <xsd:annotation>
          <xsd:documentation>Indicates a dialog box.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dlginit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="edit">
        <xsd:annotation>
          <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="file">
        <xsd:annotation>
          <xsd:documentation>Indicates a filename.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="filechooser">
        <xsd:annotation>
          <xsd:documentation>Indicates a file dialog.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="fn">
        <xsd:annotation>
          <xsd:documentation>Indicates a footnote.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="font">
        <xsd:annotation>
          <xsd:documentation>Indicates a font name.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="footer">
        <xsd:annotation>
          <xsd:documentation>Indicates a footer.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="frame">
        <xsd:annotation>
          <xsd:documentation>Indicates a frame object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="grid">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="groupbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="header">
        <xsd:annotation>
          <xsd:documentation>Indicates a header item.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="heading">
        <xsd:annotation>
          <xsd:documentation>Indicates a heading, such has the content of &lt;h1&gt;, &lt;h2&gt;, etc. in HTML.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="hedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="hscrollbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="icon">
        <xsd:annotation>
          <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="iedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="keywords">
        <xsd:annotation>
          <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="label">
        <xsd:annotation>
          <xsd:documentation>Indicates a label object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="linklabel">
        <xsd:annotation>
          <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="list">
        <xsd:annotation>
          <xsd:documentation>Indicates a list (a group of list-items, for example an &lt;ol&gt; or &lt;ul&gt; element in HTML).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="listbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="listitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ltext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menu">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menubar">
        <xsd:annotation>
          <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menuseparator">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="message">
        <xsd:annotation>
          <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="monthcalendar">
        <xsd:annotation>
          <xsd:documentation>Indicates a calendar control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="numericupdown">
        <xsd:annotation>
          <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="panel">
        <xsd:annotation>
          <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="popupmenu">
        <xsd:annotation>
          <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pushbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pushbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="radio">
        <xsd:annotation>
          <xsd:documentation>Indicates a radio button object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="radiobuttonmenuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rcdata">
        <xsd:annotation>
          <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="row">
        <xsd:annotation>
          <xsd:documentation>Indicates a row in a table.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rtext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="scrollpane">
        <xsd:annotation>
          <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="separator">
        <xsd:annotation>
          <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="shortcut">
        <xsd:annotation>
          <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="spinner">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="splitter">
        <xsd:annotation>
          <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="state3">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="statusbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="string">
        <xsd:annotation>
          <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tabcontrol">
        <xsd:annotation>
          <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="table">
        <xsd:annotation>
          <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="textbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="togglebutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="toolbar">
        <xsd:annotation>
          <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tooltip">
        <xsd:annotation>
          <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="trackbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tree">
        <xsd:annotation>
          <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="uri">
        <xsd:annotation>
          <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="userbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="usercontrol">
        <xsd:annotation>
          <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="var">
        <xsd:annotation>
          <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="versioninfo">
        <xsd:annotation>
          <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="vscrollbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="window">
        <xsd:annotation>
          <xsd:documentation>Indicates a graphical window.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="size-unitValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="byte">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="char">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="col">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cm">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dlgunit">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="em">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ex">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="glyph">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="in">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in inches.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mm">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="percent">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pixel">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="point">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in point.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="row">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="stateValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="final">
        <xsd:annotation>
          <xsd:documentation>Indicates the terminating state.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-adaptation">
        <xsd:annotation>
          <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-l10n">
        <xsd:annotation>
          <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-adaptation">
        <xsd:annotation>
          <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-l10n">
        <xsd:annotation>
          <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-translation">
        <xsd:annotation>
          <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-translation">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="new">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="signed-off">
        <xsd:annotation>
          <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="translated">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="state-qualifierValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="exact-match">
        <xsd:annotation>
          <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="fuzzy-match">
        <xsd:annotation>
          <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="id-match">
        <xsd:annotation>
          <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-glossary">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-inherited">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-mt">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-repository">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-tm">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mt-suggestion">
        <xsd:annotation>
          <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-grammar">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-inaccurate">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-length">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-spelling">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tm-suggestion">
        <xsd:annotation>
          <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="unitValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="word">
        <xsd:annotation>
          <xsd:documentation>Refers to words.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="page">
        <xsd:annotation>
          <xsd:documentation>Refers to pages.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="trans-unit">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;trans-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bin-unit">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;bin-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="glyph">
        <xsd:annotation>
          <xsd:documentation>Refers to glyphs.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="item">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;trans-unit&gt; and/or &lt;bin-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="instance">
        <xsd:annotation>
          <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="character">
        <xsd:annotation>
          <xsd:documentation>Refers to characters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="line">
        <xsd:annotation>
          <xsd:documentation>Refers to lines.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sentence">
        <xsd:annotation>
          <xsd:documentation>Refers to sentences.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="paragraph">
        <xsd:annotation>
          <xsd:documentation>Refers to paragraphs.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="segment">
        <xsd:annotation>
          <xsd:documentation>Refers to segments.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="placeable">
        <xsd:annotation>
          <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="priorityValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:positiveInteger">
      <xsd:enumeration value="1">
        <xsd:annotation>
          <xsd:documentation>Highest priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="2">
        <xsd:annotation>
          <xsd:documentation>High priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="3">
        <xsd:annotation>
          <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="4">
        <xsd:annotation>
          <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="5">
        <xsd:annotation>
          <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="6">
        <xsd:annotation>
          <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="7">
        <xsd:annotation>
          <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="8">
        <xsd:annotation>
          <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="9">
        <xsd:annotation>
          <xsd:documentation>Low priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="10">
        <xsd:annotation>
          <xsd:documentation>Lowest priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="reformatValueYesNo">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="yes">
        <xsd:annotation>
          <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="no">
        <xsd:annotation>
          <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="reformatValueList">
    <xsd:list>
      <xsd:simpleType>
        <xsd:union memberTypes="xlf:XTend">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="coord">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-x">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-y">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-cx">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-cy">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-name">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-size">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-weight">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="css-style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="ex-style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:union>
      </xsd:simpleType>
    </xsd:list>
  </xsd:simpleType>
  <xsd:simpleType name="purposeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="information">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="location">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="match">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="alttranstypeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="proposal">
        <xsd:annotation>
          <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="previous-version">
        <xsd:annotation>
          <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected">
        <xsd:annotation>
          <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="reference">
        <xsd:annotation>
          <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="accepted">
        <xsd:annotation>
          <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <!-- Other Types -->
  <xsd:complexType name="ElemType_ExternalReference">
    <xsd:choice>
      <xsd:element ref="xlf:internal-file"/>
      <xsd:element ref="xlf:external-file"/>
    </xsd:choice>
  </xsd:complexType>
  <xsd:simpleType name="AttrType_purpose">
    <xsd:list>
      <xsd:simpleType>
        <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
      </xsd:simpleType>
    </xsd:list>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_datatype">
    <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_restype">
    <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_alttranstype">
    <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_context-type">
    <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_state">
    <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_state-qualifier">
    <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_count-type">
    <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_InlineDelimiters">
    <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_InlinePlaceholders">
    <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_size-unit">
    <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_mtype">
    <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_unit">
    <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_priority">
    <xsd:union memberTypes="xlf:priorityValueList"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_reformat">
    <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_YesNo">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="yes"/>
      <xsd:enumeration value="no"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Position">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="open"/>
      <xsd:enumeration value="close"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_assoc">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="preceding"/>
      <xsd:enumeration value="following"/>
      <xsd:enumeration value="both"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_annotates">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="source"/>
      <xsd:enumeration value="target"/>
      <xsd:enumeration value="general"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Coordinates">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Version">
    <xsd:annotation>
      <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="1.2"/>
      <xsd:enumeration value="1.1"/>
      <xsd:enumeration value="1.0"/>
    </xsd:restriction>
  </xsd:simpleType>
  <!-- Groups -->
  <xsd:group name="ElemGroup_TextContent">
    <xsd:choice>
      <xsd:element ref="xlf:g"/>
      <xsd:element ref="xlf:bpt"/>
      <xsd:element ref="xlf:ept"/>
      <xsd:element ref="xlf:ph"/>
      <xsd:element ref="xlf:it"/>
      <xsd:element ref="xlf:mrk"/>
      <xsd:element ref="xlf:x"/>
      <xsd:element ref="xlf:bx"/>
      <xsd:element ref="xlf:ex"/>
    </xsd:choice>
  </xsd:group>
  <xsd:attributeGroup name="AttrGroup_TextContent">
    <xsd:attribute name="id" type="xsd:string" use="required"/>
    <xsd:attribute name="ts" type="xsd:string" use="optional"/>
    <xsd:attribute name="xid" type="xsd:string" use="optional"/>
    <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
    <xsd:anyAttribute namespace="##any" processContents="skip"/>
  </xsd:attributeGroup>
  <!-- XLIFF Structure -->
  <xsd:element name="xliff">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="skip"/>
        <xsd:element ref="xlf:file"/>
      </xsd:sequence>
      <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="file">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" ref="xlf:header"/>
        <xsd:element ref="xlf:body"/>
      </xsd:sequence>
      <xsd:attribute name="original" type="xsd:string" use="required"/>
      <xsd:attribute name="source-language" type="xsd:language" use="required"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute default="manual" name="tool" type="xsd:string" use="optional"/>
      <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
      <xsd:attribute ref="xml:space" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="category" type="xsd:string" use="optional"/>
      <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
      <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
      <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
    <xsd:unique name="U_group_id">
      <xsd:selector xpath=".//xlf:group"/>
      <xsd:field xpath="@id"/>
    </xsd:unique>
    <xsd:key name="K_unit_id">
      <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
      <xsd:field xpath="@id"/>
    </xsd:key>
    <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
      <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
      <xsd:field xpath="@xid"/>
    </xsd:keyref>
    <xsd:key name="K_tool-id">
      <xsd:selector xpath="xlf:header/xlf:tool"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:key>
    <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath="."/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:key name="K_count-group_name">
      <xsd:selector xpath=".//xlf:count-group"/>
      <xsd:field xpath="@name"/>
    </xsd:key>
    <xsd:unique name="U_context-group_name">
      <xsd:selector xpath=".//xlf:context-group"/>
      <xsd:field xpath="@name"/>
    </xsd:unique>
    <xsd:key name="K_phase-name">
      <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
      <xsd:field xpath="@phase-name"/>
    </xsd:key>
    <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
      <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
      <xsd:field xpath="@phase-name"/>
    </xsd:keyref>
    <xsd:unique name="U_uid">
      <xsd:selector xpath=".//xlf:external-file"/>
      <xsd:field xpath="@uid"/>
    </xsd:unique>
  </xsd:element>
  <xsd:element name="header">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
        <xsd:element minOccurs="0" ref="xlf:phase-group"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
          <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:prop-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:tool"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="skip"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="internal-file">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="form" type="xsd:string"/>
          <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="external-file">
    <xsd:complexType>
      <xsd:attribute name="href" type="xsd:string" use="required"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
      <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="note">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute ref="xml:lang" use="optional"/>
          <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
          <xsd:attribute name="from" type="xsd:string" use="optional"/>
          <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="phase-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:phase"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="phase">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:note"/>
      </xsd:sequence>
      <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
      <xsd:attribute name="process-name" type="xsd:string" use="required"/>
      <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool" type="xsd:string" use="optional"/>
      <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
      <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="count-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:count"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="count">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
          <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
          <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="context-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:context"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="optional"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="context">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
          <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
          <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="prop-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:prop"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="prop">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="prop-type" type="xsd:string" use="required"/>
          <xsd:attribute ref="xml:lang" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="tool">
    <xsd:complexType mixed="true">
      <xsd:sequence>
        <xsd:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
      <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
      <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
      <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="body">
    <xsd:complexType>
      <xsd:choice maxOccurs="unbounded" minOccurs="0">
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
      </xsd:choice>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="group">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:sequence>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:prop-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
          <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="skip"/>
        </xsd:sequence>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
        </xsd:choice>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
      <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
      <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="trans-unit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="xlf:source"/>
        <xsd:element minOccurs="0" ref="xlf:seg-source"/>
        <xsd:element minOccurs="0" ref="xlf:target"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element ref="xlf:context-group"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:prop-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:alt-trans"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="skip"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="required"/>
      <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
      <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
      <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
    <xsd:unique name="U_tu_segsrc_mid">
      <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:unique>
    <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
      <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
      <xsd:field xpath="@mid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="source">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
    <xsd:unique name="U_source_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_source_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="seg-source">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
    <xsd:unique name="U_segsrc_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_segsrc_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="target">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
      <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
    <xsd:unique name="U_target_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_target_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="alt-trans">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" ref="xlf:source"/>
        <xsd:element minOccurs="0" ref="xlf:seg-source"/>
        <xsd:element maxOccurs="unbounded" ref="xlf:target"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:prop-group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="skip"/>
      </xsd:sequence>
      <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool" type="xsd:string" use="optional"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="origin" type="xsd:string" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
    <xsd:unique name="U_at_segsrc_mid">
      <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:unique>
    <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
      <xsd:selector xpath="./xlf:target/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="bin-unit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="xlf:bin-source"/>
        <xsd:element minOccurs="0" ref="xlf:bin-target"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element ref="xlf:context-group"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:prop-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:trans-unit"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="skip"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="required"/>
      <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
      <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bin-source">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element ref="xlf:internal-file"/>
        <xsd:element ref="xlf:external-file"/>
      </xsd:choice>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bin-target">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element ref="xlf:internal-file"/>
        <xsd:element ref="xlf:external-file"/>
      </xsd:choice>
      <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
      <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
  <!-- Element for inline codes -->
  <xsd:element name="g">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="x">
    <xsd:complexType>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bx">
    <xsd:complexType>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ex">
    <xsd:complexType>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ph">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bpt">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ept">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="it">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="sub">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="xid" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="mrk">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
      <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="comment" type="xsd:string" use="optional"/>
      <xsd:attribute name="ts" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##any" processContents="skip"/>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if ('cli' !== \PHP_SAPI) {
    throw new Exception('This script must be run from the command line.');
}

$usageInstructions = <<<END

      Usage instructions
      -------------------------------------------------------------------------------

      $ cd symfony-code-root-directory/

      # show the translation status of all locales
      $ php translation-status.php

      # only show the translation status of incomplete or erroneous locales
      $ php translation-status.php --incomplete

      # show the translation status of all locales, all their missing translations and mismatches between trans-unit id and source
      $ php translation-status.php -v

      # show the status of a single locale
      $ php translation-status.php fr

      # show the status of a single locale, missing translations and mismatches between trans-unit id and source
      $ php translation-status.php fr -v

    END;

$config = [
    // if TRUE, the full list of missing translations is displayed
    'verbose_output' => false,
    // NULL = analyze all locales
    'locale_to_analyze' => null,
    // append --incomplete to only show incomplete languages
    'include_completed_languages' => true,
    // the reference files all the other translations are compared to
    'original_files' => [
        'src/Symfony/Component/Form/Resources/translations/validators.en.xlf',
        'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf',
        'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf',
    ],
];

$argc = $_SERVER['argc'];
$argv = $_SERVER['argv'];

if ($argc > 4) {
    echo str_replace('translation-status.php', $argv[0], $usageInstructions);
    exit(1);
}

foreach (array_slice($argv, 1) as $argumentOrOption) {
    if ('--incomplete' === $argumentOrOption) {
        $config['include_completed_languages'] = false;
        continue;
    }

    if (str_starts_with($argumentOrOption, '-')) {
        $config['verbose_output'] = true;
    } else {
        $config['locale_to_analyze'] = $argumentOrOption;
    }
}

foreach ($config['original_files'] as $originalFilePath) {
    if (!file_exists($originalFilePath)) {
        echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s  %s', \PHP_EOL, $originalFilePath);
        exit(1);
    }
}

$totalMissingTranslations = 0;
$totalTranslationMismatches = 0;

foreach ($config['original_files'] as $originalFilePath) {
    $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']);
    $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths);

    $totalMissingTranslations += array_sum(array_map(static fn ($translation) => count($translation['missingKeys']), array_values($translationStatus)));
    $totalTranslationMismatches += array_sum(array_map(static fn ($translation) => count($translation['mismatches']), array_values($translationStatus)));

    printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output'], $config['include_completed_languages']);
}

exit($totalTranslationMismatches > 0 ? 1 : 0);

function findTranslationFiles($originalFilePath, $localeToAnalyze): array
{
    $translations = [];

    $translationsDir = dirname($originalFilePath);
    $originalFileName = basename($originalFilePath);
    $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName);

    $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern, \GLOB_NOSORT);
    sort($translationFiles);
    foreach ($translationFiles as $filePath) {
        $locale = extractLocaleFromFilePath($filePath);

        if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) {
            continue;
        }

        $translations[$locale] = $filePath;
    }

    return $translations;
}

function calculateTranslationStatus($originalFilePath, $translationFilePaths): array
{
    $translationStatus = [];
    $allTranslationKeys = extractTranslationKeys($originalFilePath);

    foreach ($translationFilePaths as $locale => $translationPath) {
        $translatedKeys = extractTranslationKeys($translationPath);
        $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys);
        $mismatches = findTransUnitMismatches($allTranslationKeys, $translatedKeys);

        $translationStatus[$locale] = [
            'total' => count($allTranslationKeys),
            'translated' => count($translatedKeys),
            'missingKeys' => $missingKeys,
            'mismatches' => $mismatches,
        ];
        $translationStatus[$locale]['is_completed'] = isTranslationCompleted($translationStatus[$locale]);
    }

    return $translationStatus;
}

function isTranslationCompleted(array $translationStatus): bool
{
    return $translationStatus['total'] === $translationStatus['translated'] && 0 === count($translationStatus['mismatches']);
}

function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput, $includeCompletedLanguages)
{
    printTitle($originalFilePath);
    printTable($translationStatus, $verboseOutput, $includeCompletedLanguages);
    echo \PHP_EOL.\PHP_EOL;
}

function extractLocaleFromFilePath($filePath)
{
    $parts = explode('.', $filePath);

    return $parts[count($parts) - 2];
}

function extractTranslationKeys($filePath): array
{
    $translationKeys = [];
    $contents = new SimpleXMLElement(file_get_contents($filePath));

    foreach ($contents->file->body->{'trans-unit'} as $translationKey) {
        $translationId = (string) $translationKey['id'];
        $translationKey = (string) ($translationKey['resname'] ?? $translationKey->source);

        $translationKeys[$translationId] = $translationKey;
    }

    return $translationKeys;
}

/**
 * Check whether the trans-unit id and source match with the base translation.
 */
function findTransUnitMismatches(array $baseTranslationKeys, array $translatedKeys): array
{
    $mismatches = [];

    foreach ($baseTranslationKeys as $translationId => $translationKey) {
        if (!isset($translatedKeys[$translationId])) {
            continue;
        }
        if ($translatedKeys[$translationId] !== $translationKey) {
            $mismatches[$translationId] = [
                'found' => $translatedKeys[$translationId],
                'expected' => $translationKey,
            ];
        }
    }

    return $mismatches;
}

function printTitle($title)
{
    echo $title.\PHP_EOL;
    echo str_repeat('=', strlen($title)).\PHP_EOL.\PHP_EOL;
}

function printTable($translations, $verboseOutput, bool $includeCompletedLanguages)
{
    if (0 === count($translations)) {
        echo 'No translations found';

        return;
    }
    $longestLocaleNameLength = max(array_map('strlen', array_keys($translations)));

    foreach ($translations as $locale => $translation) {
        if (!$includeCompletedLanguages && $translation['is_completed']) {
            continue;
        }

        if ($translation['translated'] > $translation['total']) {
            textColorRed();
        } elseif (count($translation['mismatches']) > 0) {
            textColorRed();
        } elseif ($translation['is_completed']) {
            textColorGreen();
        }

        echo sprintf(
            '|  Locale: %-'.$longestLocaleNameLength.'s  |  Translated: %2d/%2d  |  Mismatches: %d  |',
            $locale,
            $translation['translated'],
            $translation['total'],
            count($translation['mismatches'])
        ).\PHP_EOL;

        textColorNormal();

        $shouldBeClosed = false;
        if (true === $verboseOutput && count($translation['missingKeys']) > 0) {
            echo '|    Missing Translations:'.\PHP_EOL;

            foreach ($translation['missingKeys'] as $id => $content) {
                echo sprintf('|      (id=%s) %s', $id, $content).\PHP_EOL;
            }
            $shouldBeClosed = true;
        }
        if (true === $verboseOutput && count($translation['mismatches']) > 0) {
            echo '|    Mismatches between trans-unit id and source:'.\PHP_EOL;

            foreach ($translation['mismatches'] as $id => $content) {
                echo sprintf('|      (id=%s) Expected: %s', $id, $content['expected']).\PHP_EOL;
                echo sprintf('|              Found:    %s', $content['found']).\PHP_EOL;
            }
            $shouldBeClosed = true;
        }
        if ($shouldBeClosed) {
            echo str_repeat('-', 80).\PHP_EOL;
        }
    }
}

function textColorGreen()
{
    echo "\033[32m";
}

function textColorRed()
{
    echo "\033[31m";
}

function textColorNormal()
{
    echo "\033[0m";
}
{
    "az_Cyrl": "root",
    "bs_Cyrl": "root",
    "en_150": "en_001",
    "en_AG": "en_001",
    "en_AI": "en_001",
    "en_AT": "en_150",
    "en_AU": "en_001",
    "en_BB": "en_001",
    "en_BE": "en_150",
    "en_BM": "en_001",
    "en_BS": "en_001",
    "en_BW": "en_001",
    "en_BZ": "en_001",
    "en_CC": "en_001",
    "en_CH": "en_150",
    "en_CK": "en_001",
    "en_CM": "en_001",
    "en_CX": "en_001",
    "en_CY": "en_001",
    "en_CZ": "en_150",
    "en_DE": "en_150",
    "en_DG": "en_001",
    "en_DK": "en_150",
    "en_DM": "en_001",
    "en_EE": "en_150",
    "en_ER": "en_001",
    "en_ES": "en_150",
    "en_FI": "en_150",
    "en_FJ": "en_001",
    "en_FK": "en_001",
    "en_FM": "en_001",
    "en_FR": "en_150",
    "en_GB": "en_001",
    "en_GD": "en_001",
    "en_GE": "en_150",
    "en_GG": "en_001",
    "en_GH": "en_001",
    "en_GI": "en_001",
    "en_GM": "en_001",
    "en_GS": "en_001",
    "en_GY": "en_001",
    "en_HK": "en_001",
    "en_HU": "en_150",
    "en_ID": "en_001",
    "en_IE": "en_001",
    "en_IL": "en_001",
    "en_IM": "en_001",
    "en_IN": "en_001",
    "en_IO": "en_001",
    "en_IT": "en_150",
    "en_JE": "en_001",
    "en_JM": "en_001",
    "en_KE": "en_001",
    "en_KI": "en_001",
    "en_KN": "en_001",
    "en_KY": "en_001",
    "en_LC": "en_001",
    "en_LR": "en_001",
    "en_LS": "en_001",
    "en_LT": "en_150",
    "en_LV": "en_150",
    "en_MG": "en_001",
    "en_MO": "en_001",
    "en_MS": "en_001",
    "en_MT": "en_001",
    "en_MU": "en_001",
    "en_MV": "en_001",
    "en_MW": "en_001",
    "en_MY": "en_001",
    "en_NA": "en_001",
    "en_NF": "en_001",
    "en_NG": "en_001",
    "en_NL": "en_150",
    "en_NO": "en_150",
    "en_NR": "en_001",
    "en_NU": "en_001",
    "en_NZ": "en_001",
    "en_PG": "en_001",
    "en_PK": "en_001",
    "en_PL": "en_150",
    "en_PN": "en_001",
    "en_PT": "en_150",
    "en_PW": "en_001",
    "en_RO": "en_150",
    "en_RW": "en_001",
    "en_SB": "en_001",
    "en_SC": "en_001",
    "en_SD": "en_001",
    "en_SE": "en_150",
    "en_SG": "en_001",
    "en_SH": "en_001",
    "en_SI": "en_150",
    "en_SK": "en_150",
    "en_SL": "en_001",
    "en_SS": "en_001",
    "en_SX": "en_001",
    "en_SZ": "en_001",
    "en_TC": "en_001",
    "en_TK": "en_001",
    "en_TO": "en_001",
    "en_TT": "en_001",
    "en_TV": "en_001",
    "en_TZ": "en_001",
    "en_UA": "en_150",
    "en_UG": "en_001",
    "en_VC": "en_001",
    "en_VG": "en_001",
    "en_VU": "en_001",
    "en_WS": "en_001",
    "en_ZA": "en_001",
    "en_ZM": "en_001",
    "en_ZW": "en_001",
    "es_AR": "es_419",
    "es_BO": "es_419",
    "es_BR": "es_419",
    "es_BZ": "es_419",
    "es_CL": "es_419",
    "es_CO": "es_419",
    "es_CR": "es_419",
    "es_CU": "es_419",
    "es_DO": "es_419",
    "es_EC": "es_419",
    "es_GT": "es_419",
    "es_HN": "es_419",
    "es_MX": "es_419",
    "es_NI": "es_419",
    "es_PA": "es_419",
    "es_PE": "es_419",
    "es_PR": "es_419",
    "es_PY": "es_419",
    "es_SV": "es_419",
    "es_US": "es_419",
    "es_UY": "es_419",
    "es_VE": "es_419",
    "ff_Adlm": "root",
    "hi_Latn": "en_IN",
    "kk_Arab": "root",
    "ks_Deva": "root",
    "nb": "no",
    "nn": "no",
    "pa_Arab": "root",
    "pt_AO": "pt_PT",
    "pt_CH": "pt_PT",
    "pt_CV": "pt_PT",
    "pt_GQ": "pt_PT",
    "pt_GW": "pt_PT",
    "pt_LU": "pt_PT",
    "pt_MO": "pt_PT",
    "pt_MZ": "pt_PT",
    "pt_ST": "pt_PT",
    "pt_TL": "pt_PT",
    "sd_Deva": "root",
    "sr_Latn": "root",
    "uz_Arab": "root",
    "uz_Cyrl": "root",
    "zh_Hant": "root",
    "zh_Hant_MO": "zh_Hant_HK"
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ProviderExceptionInterface extends ExceptionInterface
{
    /*
     * Returns debug info coming from the Symfony\Contracts\HttpClient\ResponseInterface
     */
    public function getDebug(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

use Symfony\Component\Translation\Bridge;
use Symfony\Component\Translation\Provider\Dsn;

class UnsupportedSchemeException extends LogicException
{
    private const SCHEME_TO_PACKAGE_MAP = [
        'crowdin' => [
            'class' => Bridge\Crowdin\CrowdinProviderFactory::class,
            'package' => 'symfony/crowdin-translation-provider',
        ],
        'loco' => [
            'class' => Bridge\Loco\LocoProviderFactory::class,
            'package' => 'symfony/loco-translation-provider',
        ],
        'lokalise' => [
            'class' => Bridge\Lokalise\LokaliseProviderFactory::class,
            'package' => 'symfony/lokalise-translation-provider',
        ],
        'phrase' => [
            'class' => Bridge\Phrase\PhraseProviderFactory::class,
            'package' => 'symfony/phrase-translation-provider',
        ],
    ];

    public function __construct(Dsn $dsn, ?string $name = null, array $supported = [])
    {
        $provider = $dsn->getScheme();
        if (false !== $pos = strpos($provider, '+')) {
            $provider = substr($provider, 0, $pos);
        }
        $package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null;
        if ($package && !class_exists($package['class'])) {
            parent::__construct(\sprintf('Unable to synchronize translations via "%s" as the provider is not installed. Try running "composer require %s".', $provider, $package['package']));

            return;
        }

        $message = \sprintf('The "%s" scheme is not supported', $dsn->getScheme());
        if ($name && $supported) {
            $message .= \sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported));
        }

        parent::__construct($message.'.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Thrown when a resource cannot be loaded.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * @author Oskar Stark <oskarstark@googlemail.com>
 */
class MissingRequiredOptionException extends IncompleteDsnException
{
    public function __construct(string $option, ?string $dsn = null, ?\Throwable $previous = null)
    {
        $message = \sprintf('The option "%s" is required but missing.', $option);

        parent::__construct($message, $dsn, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

use Symfony\Contracts\HttpClient\ResponseInterface;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ProviderException extends RuntimeException implements ProviderExceptionInterface
{
    private string $debug;

    public function __construct(
        string $message,
        private ResponseInterface $response,
        int $code = 0,
        ?\Exception $previous = null,
    ) {
        $this->debug = $response->getInfo('debug') ?? '';

        parent::__construct($message, $code, $previous);
    }

    public function getResponse(): ResponseInterface
    {
        return $this->response;
    }

    public function getDebug(): string
    {
        return $this->debug;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Thrown when a resource does not exist.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Base InvalidArgumentException for the Translation component.
 *
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

class IncompleteDsnException extends InvalidArgumentException
{
    public function __construct(string $message, ?string $dsn = null, ?\Throwable $previous = null)
    {
        if ($dsn) {
            $message = \sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
        }

        parent::__construct($message, 0, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Base LogicException for Translation component.
 *
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Base RuntimeException for the Translation component.
 *
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\ConfigCacheFactory;
use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Config\ConfigCacheInterface;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
use Symfony\Component\Translation\Formatter\MessageFormatter;
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

// Help opcache.preload discover always-needed symbols
class_exists(MessageCatalogue::class);

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
{
    /**
     * @var MessageCatalogueInterface[]
     */
    protected array $catalogues = [];

    private string $locale;

    /**
     * @var string[]
     */
    private array $fallbackLocales = [];

    /**
     * @var LoaderInterface[]
     */
    private array $loaders = [];

    private array $resources = [];

    private MessageFormatterInterface $formatter;

    private ?ConfigCacheFactoryInterface $configCacheFactory;

    private array $parentLocales;

    private bool $hasIntlFormatter;

    /**
     * @var array<string, string|int|float|TranslatableInterface>
     */
    private array $globalParameters = [];

    /**
     * @var array<string, string|int|float>
     */
    private array $globalTranslatedParameters = [];

    /**
     * @throws InvalidArgumentException If a locale contains invalid characters
     */
    public function __construct(
        string $locale,
        ?MessageFormatterInterface $formatter = null,
        private ?string $cacheDir = null,
        private bool $debug = false,
        private array $cacheVary = [],
    ) {
        $this->setLocale($locale);

        $this->formatter = $formatter ??= new MessageFormatter();
        $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
    }

    public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory): void
    {
        $this->configCacheFactory = $configCacheFactory;
    }

    /**
     * Adds a Loader.
     *
     * @param string $format The name of the loader (@see addResource())
     */
    public function addLoader(string $format, LoaderInterface $loader): void
    {
        $this->loaders[$format] = $loader;
    }

    /**
     * Adds a Resource.
     *
     * @param string $format   The name of the loader (@see addLoader())
     * @param mixed  $resource The resource name
     *
     * @throws InvalidArgumentException If the locale contains invalid characters
     */
    public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void
    {
        $domain ??= 'messages';

        $this->assertValidLocale($locale);
        $locale ?: $locale = class_exists(\Locale::class) ? \Locale::getDefault() : 'en';

        $this->resources[$locale][] = [$format, $resource, $domain];

        if (\in_array($locale, $this->fallbackLocales, true)) {
            $this->catalogues = [];
        } else {
            unset($this->catalogues[$locale]);
        }
    }

    public function setLocale(string $locale): void
    {
        $this->assertValidLocale($locale);
        $this->locale = $locale;
    }

    public function getLocale(): string
    {
        return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
    }

    /**
     * Sets the fallback locales.
     *
     * @param string[] $locales
     *
     * @throws InvalidArgumentException If a locale contains invalid characters
     */
    public function setFallbackLocales(array $locales): void
    {
        // needed as the fallback locales are linked to the already loaded catalogues
        $this->catalogues = [];

        foreach ($locales as $locale) {
            $this->assertValidLocale($locale);
        }

        $this->fallbackLocales = $this->cacheVary['fallback_locales'] = $locales;
    }

    /**
     * Gets the fallback locales.
     *
     * @internal
     */
    public function getFallbackLocales(): array
    {
        return $this->fallbackLocales;
    }

    public function addGlobalParameter(string $id, string|int|float|TranslatableInterface $value): void
    {
        $this->globalParameters[$id] = $value;
        $this->globalTranslatedParameters = [];
    }

    public function getGlobalParameters(): array
    {
        return $this->globalParameters;
    }

    public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        if (null === $id || '' === $id) {
            return '';
        }

        $domain ??= 'messages';

        $catalogue = $this->getCatalogue($locale);
        $locale = $catalogue->getLocale();
        while (!$catalogue->defines($id, $domain)) {
            if ($cat = $catalogue->getFallbackCatalogue()) {
                $catalogue = $cat;
                $locale = $catalogue->getLocale();
            } else {
                break;
            }
        }

        foreach ($parameters as $key => $value) {
            if ($value instanceof TranslatableInterface) {
                $parameters[$key] = $value->trans($this, $locale);
            }
        }

        if (null === $globalParameters = &$this->globalTranslatedParameters[$locale]) {
            $globalParameters = $this->globalParameters;
            foreach ($globalParameters as $key => $value) {
                if ($value instanceof TranslatableInterface) {
                    $globalParameters[$key] = $value->trans($this, $locale);
                }
            }
        }

        if ($globalParameters) {
            $parameters += $globalParameters;
        }

        $len = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX);
        if ($this->hasIntlFormatter
            && ($catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)
            || (\strlen($domain) > $len && 0 === substr_compare($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX, -$len, $len)))
        ) {
            return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
        }

        return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
    }

    public function getCatalogue(?string $locale = null): MessageCatalogueInterface
    {
        if (!$locale) {
            $locale = $this->getLocale();
        } else {
            $this->assertValidLocale($locale);
        }

        if (!isset($this->catalogues[$locale])) {
            $this->loadCatalogue($locale);
        }

        return $this->catalogues[$locale];
    }

    public function getCatalogues(): array
    {
        return array_values($this->catalogues);
    }

    /**
     * Gets the loaders.
     *
     * @return LoaderInterface[]
     */
    protected function getLoaders(): array
    {
        return $this->loaders;
    }

    protected function loadCatalogue(string $locale): void
    {
        if (null === $this->cacheDir) {
            $this->initializeCatalogue($locale);
        } else {
            $this->initializeCacheCatalogue($locale);
        }
    }

    protected function initializeCatalogue(string $locale): void
    {
        $this->assertValidLocale($locale);

        try {
            $this->doLoadCatalogue($locale);
        } catch (NotFoundResourceException $e) {
            if (!$this->computeFallbackLocales($locale)) {
                throw $e;
            }
        }
        $this->loadFallbackCatalogues($locale);
    }

    private function initializeCacheCatalogue(string $locale): void
    {
        if (isset($this->catalogues[$locale])) {
            /* Catalogue already initialized. */
            return;
        }

        $this->assertValidLocale($locale);
        $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
            function (ConfigCacheInterface $cache) use ($locale) {
                $this->dumpCatalogue($locale, $cache);
            }
        );

        if (isset($this->catalogues[$locale])) {
            /* Catalogue has been initialized as it was written out to cache. */
            return;
        }

        /* Read catalogue from cache. */
        $this->catalogues[$locale] = include $cache->getPath();
    }

    private function dumpCatalogue(string $locale, ConfigCacheInterface $cache): void
    {
        $this->initializeCatalogue($locale);
        $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);

        $content = \sprintf(<<<EOF
            <?php

            use Symfony\Component\Translation\MessageCatalogue;

            \$catalogue = new MessageCatalogue('%s', %s);

            %s
            return \$catalogue;

            EOF,
            $locale,
            var_export($this->getAllMessages($this->catalogues[$locale]), true),
            $fallbackContent
        );

        $cache->write($content, $this->catalogues[$locale]->getResources());
    }

    private function getFallbackContent(MessageCatalogue $catalogue): string
    {
        $fallbackContent = '';
        $current = '';
        $replacementPattern = '/[^a-z0-9_]/i';
        $fallbackCatalogue = $catalogue->getFallbackCatalogue();
        while ($fallbackCatalogue) {
            $fallback = $fallbackCatalogue->getLocale();
            $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
            $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));

            $fallbackContent .= \sprintf(<<<'EOF'
                $catalogue%s = new MessageCatalogue('%s', %s);
                $catalogue%s->addFallbackCatalogue($catalogue%s);

                EOF,
                $fallbackSuffix,
                $fallback,
                var_export($this->getAllMessages($fallbackCatalogue), true),
                $currentSuffix,
                $fallbackSuffix
            );
            $current = $fallbackCatalogue->getLocale();
            $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
        }

        return $fallbackContent;
    }

    private function getCatalogueCachePath(string $locale): string
    {
        return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('xxh128', serialize($this->cacheVary), true)), 0, 7), '/', '_').'.php';
    }

    /**
     * @internal
     */
    protected function doLoadCatalogue(string $locale): void
    {
        $this->catalogues[$locale] = new MessageCatalogue($locale);

        if (isset($this->resources[$locale])) {
            foreach ($this->resources[$locale] as $resource) {
                if (!isset($this->loaders[$resource[0]])) {
                    if (\is_string($resource[1])) {
                        throw new RuntimeException(\sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
                    }

                    throw new RuntimeException(\sprintf('No loader is registered for the "%s" format.', $resource[0]));
                }
                $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
            }
        }
    }

    private function loadFallbackCatalogues(string $locale): void
    {
        $current = $this->catalogues[$locale];

        foreach ($this->computeFallbackLocales($locale) as $fallback) {
            if (!isset($this->catalogues[$fallback])) {
                $this->initializeCatalogue($fallback);
            }

            $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
            foreach ($this->catalogues[$fallback]->getResources() as $resource) {
                $fallbackCatalogue->addResource($resource);
            }
            $current->addFallbackCatalogue($fallbackCatalogue);
            $current = $fallbackCatalogue;
        }
    }

    protected function computeFallbackLocales(string $locale): array
    {
        $this->parentLocales ??= json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true);

        $originLocale = $locale;
        $locales = [];

        while ($locale) {
            $parent = $this->parentLocales[$locale] ?? null;

            if ($parent) {
                $locale = 'root' !== $parent ? $parent : null;
            } elseif (\function_exists('locale_parse')) {
                $localeSubTags = locale_parse($locale);
                $locale = null;
                if (1 < \count($localeSubTags)) {
                    array_pop($localeSubTags);
                    $locale = locale_compose($localeSubTags) ?: null;
                }
            } elseif ($i = strrpos($locale, '_') ?: strrpos($locale, '-')) {
                $locale = substr($locale, 0, $i);
            } else {
                $locale = null;
            }

            if (null !== $locale) {
                $locales[] = $locale;
            }
        }

        foreach ($this->fallbackLocales as $fallback) {
            if ($fallback === $originLocale) {
                continue;
            }

            $locales[] = $fallback;
        }

        return array_unique($locales);
    }

    /**
     * Asserts that the locale is valid, throws an Exception if not.
     *
     * @throws InvalidArgumentException If the locale contains invalid characters
     */
    protected function assertValidLocale(string $locale): void
    {
        if (!preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
            throw new InvalidArgumentException(\sprintf('Invalid "%s" locale.', $locale));
        }
    }

    /**
     * Provides the ConfigCache factory implementation, falling back to a
     * default implementation if necessary.
     */
    private function getConfigCacheFactory(): ConfigCacheFactoryInterface
    {
        $this->configCacheFactory ??= new ConfigCacheFactory($this->debug);

        return $this->configCacheFactory;
    }

    private function getAllMessages(MessageCatalogueInterface $catalogue): array
    {
        $allMessages = [];

        foreach ($catalogue->all() as $domain => $messages) {
            if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
                $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
                $messages = array_diff_key($messages, $intlMessages);
            }
            if ($messages) {
                $allMessages[$domain] = $messages;
            }
        }

        return $allMessages;
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Translation\Exception\InvalidArgumentException;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
interface TranslatorBagInterface
{
    /**
     * Gets the catalogue by locale.
     *
     * @param string|null $locale The locale or null to use the default
     *
     * @throws InvalidArgumentException If the locale contains invalid characters
     */
    public function getCatalogue(?string $locale = null): MessageCatalogueInterface;

    /**
     * Returns all catalogues of the instance.
     *
     * @return MessageCatalogueInterface[]
     */
    public function getCatalogues(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Contracts\Translation\TranslatableInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * @author Nate Wiebe <nate@northern.co>
 */
class TranslatableMessage implements TranslatableInterface
{
    public function __construct(
        private string $message,
        private array $parameters = [],
        private ?string $domain = null,
    ) {
    }

    /**
     * @deprecated since Symfony 7.4
     */
    public function __toString(): string
    {
        trigger_deprecation('symfony/translation', '7.4', 'Method "%s()" is deprecated.', __METHOD__);

        return $this->getMessage();
    }

    public function getMessage(): string
    {
        return $this->message;
    }

    public function getParameters(): array
    {
        return $this->parameters;
    }

    public function getDomain(): ?string
    {
        return $this->domain;
    }

    public function trans(TranslatorInterface $translator, ?string $locale = null): string
    {
        $parameters = $this->getParameters();
        foreach ($parameters as $k => $v) {
            if ($v instanceof TranslatableInterface) {
                $parameters[$k] = $v->trans($translator, $locale);
            }
        }

        return $translator->trans($this->getMessage(), $parameters, $this->getDomain(), $locale);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * This interface is used to get, set, and delete metadata about the Catalogue.
 *
 * @author Hugo Alliaume <hugo@alliau.me>
 */
interface CatalogueMetadataAwareInterface
{
    /**
     * Gets catalogue metadata for the given domain and key.
     *
     * Passing an empty domain will return an array with all catalogue metadata indexed by
     * domain and then by key. Passing an empty key will return an array with all
     * catalogue metadata for the given domain.
     *
     * @return mixed The value that was set or an array with the domains/keys or null
     */
    public function getCatalogueMetadata(string $key = '', string $domain = 'messages'): mixed;

    /**
     * Adds catalogue metadata to a message domain.
     */
    public function setCatalogueMetadata(string $key, mixed $value, string $domain = 'messages'): void;

    /**
     * Deletes catalogue metadata for the given key and domain.
     *
     * Passing an empty domain will delete all catalogue metadata. Passing an empty key will
     * delete all metadata for the given domain.
     */
    public function deleteCatalogueMetadata(string $key = '', string $domain = 'messages'): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Base catalogues binary operation class.
 *
 * A catalogue binary operation performs operation on
 * source (the left argument) and target (the right argument) catalogues.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractOperation implements OperationInterface
{
    public const OBSOLETE_BATCH = 'obsolete';
    public const NEW_BATCH = 'new';
    public const ALL_BATCH = 'all';

    protected MessageCatalogue $result;

    /**
     * This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
     *
     * The data structure of this array is as follows:
     *
     *     [
     *         'domain 1' => [
     *             'all' => [...],
     *             'new' => [...],
     *             'obsolete' => [...]
     *         ],
     *         'domain 2' => [
     *             'all' => [...],
     *             'new' => [...],
     *             'obsolete' => [...]
     *         ],
     *         ...
     *     ]
     *
     * @var array The array that stores 'all', 'new' and 'obsolete' messages
     */
    protected array $messages;

    private array $domains;

    /**
     * @throws LogicException
     */
    public function __construct(
        protected MessageCatalogueInterface $source,
        protected MessageCatalogueInterface $target,
    ) {
        if ($source->getLocale() !== $target->getLocale()) {
            throw new LogicException('Operated catalogues must belong to the same locale.');
        }

        $this->result = new MessageCatalogue($source->getLocale());
        $this->messages = [];
    }

    public function getDomains(): array
    {
        if (!isset($this->domains)) {
            $domains = [];
            foreach ([$this->source, $this->target] as $catalogue) {
                foreach ($catalogue->getDomains() as $domain) {
                    $domains[$domain] = $domain;

                    if ($catalogue->all($domainIcu = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX)) {
                        $domains[$domainIcu] = $domainIcu;
                    }
                }
            }

            $this->domains = array_values($domains);
        }

        return $this->domains;
    }

    public function getMessages(string $domain): array
    {
        if (!\in_array($domain, $this->getDomains(), true)) {
            throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
        }

        if (!isset($this->messages[$domain][self::ALL_BATCH])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain][self::ALL_BATCH];
    }

    public function getNewMessages(string $domain): array
    {
        if (!\in_array($domain, $this->getDomains(), true)) {
            throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
        }

        if (!isset($this->messages[$domain][self::NEW_BATCH])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain][self::NEW_BATCH];
    }

    public function getObsoleteMessages(string $domain): array
    {
        if (!\in_array($domain, $this->getDomains(), true)) {
            throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
        }

        if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain][self::OBSOLETE_BATCH];
    }

    public function getResult(): MessageCatalogueInterface
    {
        foreach ($this->getDomains() as $domain) {
            if (!isset($this->messages[$domain])) {
                $this->processDomain($domain);
            }
        }

        return $this->result;
    }

    /**
     * @param self::*_BATCH $batch
     */
    public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void
    {
        // If MessageFormatter class does not exists, intl domains are not supported.
        if (!class_exists(\MessageFormatter::class)) {
            return;
        }

        foreach ($this->getDomains() as $domain) {
            $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
            $messages = match ($batch) {
                self::OBSOLETE_BATCH => $this->getObsoleteMessages($domain),
                self::NEW_BATCH => $this->getNewMessages($domain),
                self::ALL_BATCH => $this->getMessages($domain),
                default => throw new \InvalidArgumentException(\sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH)),
            };

            if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
                continue;
            }

            $result = $this->getResult();
            $allIntlMessages = $result->all($intlDomain);
            $currentMessages = array_diff_key($messages, $result->all($domain));
            $result->replace($currentMessages, $domain);
            $result->replace($allIntlMessages + $messages, $intlDomain);
        }
    }

    /**
     * Performs operation on source and target catalogues for the given domain and
     * stores the results.
     *
     * @param string $domain The domain which the operation will be performed for
     */
    abstract protected function processDomain(string $domain): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Target operation between two catalogues:
 * intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
 * all = intersection ∪ (target ∖ intersection) = target
 * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
 * obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target}
 * Basically, the result contains messages from the target catalogue.
 *
 * @author Michael Lee <michael.lee@zerustech.com>
 */
class TargetOperation extends AbstractOperation
{
    protected function processDomain(string $domain): void
    {
        $this->messages[$domain] = [
            'all' => [],
            'new' => [],
            'obsolete' => [],
        ];
        $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;

        foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) {
            if (null === $this->result->getCatalogueMetadata($key, $domain)) {
                $this->result->setCatalogueMetadata($key, $value, $domain);
            }
        }

        foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) {
            if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) {
                $this->result->setCatalogueMetadata($key, $value, $intlDomain);
            }
        }

        // For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
        // because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
        //
        // For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));``
        // because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback}
        //
        // For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))``
        // because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}

        foreach ($this->source->all($domain) as $id => $message) {
            if ($this->target->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
                $this->result->add([$id => $message], $d);
                if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
                    $this->result->setMetadata($id, $keyMetadata, $d);
                }
            } else {
                $this->messages[$domain]['obsolete'][$id] = $message;
            }
        }

        foreach ($this->target->all($domain) as $id => $message) {
            if (!$this->source->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->messages[$domain]['new'][$id] = $message;
                $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
                $this->result->add([$id => $message], $d);
                if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
                    $this->result->setMetadata($id, $keyMetadata, $d);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Merge operation between two catalogues as follows:
 * all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
 * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
 * obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅
 * Basically, the result contains messages from both catalogues.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class MergeOperation extends AbstractOperation
{
    protected function processDomain(string $domain): void
    {
        $this->messages[$domain] = [
            'all' => [],
            'new' => [],
            'obsolete' => [],
        ];
        $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;

        foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) {
            if (null === $this->result->getCatalogueMetadata($key, $domain)) {
                $this->result->setCatalogueMetadata($key, $value, $domain);
            }
        }

        foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) {
            if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) {
                $this->result->setCatalogueMetadata($key, $value, $intlDomain);
            }
        }

        foreach ($this->source->all($domain) as $id => $message) {
            $this->messages[$domain]['all'][$id] = $message;
            $d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
            $this->result->add([$id => $message], $d);
            if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
                $this->result->setMetadata($id, $keyMetadata, $d);
            }
        }

        foreach ($this->target->all($domain) as $id => $message) {
            if (!$this->source->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->messages[$domain]['new'][$id] = $message;
                $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
                $this->result->add([$id => $message], $d);
                if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
                    $this->result->setMetadata($id, $keyMetadata, $d);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Represents an operation on catalogue(s).
 *
 * An instance of this interface performs an operation on one or more catalogues and
 * stores intermediate and final results of the operation.
 *
 * The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and
 * the following results are stored:
 *
 * Messages: also called 'all', are valid messages for the given domain after the operation is performed.
 *
 * New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}).
 *
 * Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}).
 *
 * Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'.
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface OperationInterface
{
    /**
     * Returns domains affected by operation.
     */
    public function getDomains(): array;

    /**
     * Returns all valid messages ('all') after operation.
     */
    public function getMessages(string $domain): array;

    /**
     * Returns new messages ('new') after operation.
     */
    public function getNewMessages(string $domain): array;

    /**
     * Returns obsolete messages ('obsolete') after operation.
     */
    public function getObsoleteMessages(string $domain): array;

    /**
     * Returns resulting catalogue ('result').
     */
    public function getResult(): MessageCatalogueInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Reader;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * TranslationReader reads translation messages from translation files.
 *
 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
 */
interface TranslationReaderInterface
{
    /**
     * Reads translation messages from a directory to the catalogue.
     */
    public function read(string $directory, MessageCatalogue $catalogue): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Reader;

use Symfony\Component\Finder\Finder;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * TranslationReader reads translation messages from translation files.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class TranslationReader implements TranslationReaderInterface
{
    /**
     * Loaders used for import.
     *
     * @var array<string, LoaderInterface>
     */
    private array $loaders = [];

    /**
     * Adds a loader to the translation extractor.
     *
     * @param string $format The format of the loader
     */
    public function addLoader(string $format, LoaderInterface $loader): void
    {
        $this->loaders[$format] = $loader;
    }

    public function read(string $directory, MessageCatalogue $catalogue): void
    {
        if (!is_dir($directory)) {
            return;
        }

        foreach ($this->loaders as $format => $loader) {
            // load any existing translation files
            $finder = new Finder();
            $extension = $catalogue->getLocale().'.'.$format;
            $files = $finder->files()->name('*.'.$extension)->in($directory);
            foreach ($files as $file) {
                $domain = substr($file->getFilename(), 0, -1 * \strlen($extension) - 1);
                $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\Translation\Exception\LogicException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface, CatalogueMetadataAwareInterface
{
    private array $metadata = [];
    private array $catalogueMetadata = [];
    private array $resources = [];
    private ?MessageCatalogueInterface $fallbackCatalogue = null;
    private ?self $parent = null;

    /**
     * @param array $messages An array of messages classified by domain
     */
    public function __construct(
        private string $locale,
        private array $messages = [],
    ) {
    }

    public function getLocale(): string
    {
        return $this->locale;
    }

    public function getDomains(): array
    {
        $domains = [];

        foreach ($this->messages as $domain => $messages) {
            if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
                $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
            }
            $domains[$domain] = $domain;
        }

        return array_values($domains);
    }

    public function all(?string $domain = null): array
    {
        if (null !== $domain) {
            // skip messages merge if intl-icu requested explicitly
            if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
                return $this->messages[$domain] ?? [];
            }

            return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []);
        }

        $allMessages = [];

        foreach ($this->messages as $domain => $messages) {
            if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
                $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
                $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []);
            } else {
                $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages;
            }
        }

        return $allMessages;
    }

    public function set(string $id, string $translation, string $domain = 'messages'): void
    {
        $this->add([$id => $translation], $domain);
    }

    public function has(string $id, string $domain = 'messages'): bool
    {
        if (isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
            return true;
        }

        if (null !== $this->fallbackCatalogue) {
            return $this->fallbackCatalogue->has($id, $domain);
        }

        return false;
    }

    public function defines(string $id, string $domain = 'messages'): bool
    {
        return isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]);
    }

    public function get(string $id, string $domain = 'messages'): string
    {
        if (isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
            return $this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id];
        }

        if (isset($this->messages[$domain][$id])) {
            return $this->messages[$domain][$id];
        }

        if (null !== $this->fallbackCatalogue) {
            return $this->fallbackCatalogue->get($id, $domain);
        }

        return $id;
    }

    public function replace(array $messages, string $domain = 'messages'): void
    {
        unset($this->messages[$domain], $this->messages[$domain.self::INTL_DOMAIN_SUFFIX]);

        $this->add($messages, $domain);
    }

    public function add(array $messages, string $domain = 'messages'): void
    {
        $altDomain = str_ends_with($domain, self::INTL_DOMAIN_SUFFIX) ? substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX)) : $domain.self::INTL_DOMAIN_SUFFIX;
        foreach ($messages as $id => $message) {
            unset($this->messages[$altDomain][$id]);
            $this->messages[$domain][$id] = $message;
        }

        if ([] === ($this->messages[$altDomain] ?? null)) {
            unset($this->messages[$altDomain]);
        }
    }

    public function addCatalogue(MessageCatalogueInterface $catalogue): void
    {
        if ($catalogue->getLocale() !== $this->locale) {
            throw new LogicException(\sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale));
        }

        foreach ($catalogue->all() as $domain => $messages) {
            if ($intlMessages = $catalogue->all($domain.self::INTL_DOMAIN_SUFFIX)) {
                $this->add($intlMessages, $domain.self::INTL_DOMAIN_SUFFIX);
                $messages = array_diff_key($messages, $intlMessages);
            }
            $this->add($messages, $domain);
        }

        foreach ($catalogue->getResources() as $resource) {
            $this->addResource($resource);
        }

        if ($catalogue instanceof MetadataAwareInterface) {
            $metadata = $catalogue->getMetadata('', '');
            $this->addMetadata($metadata);
        }

        if ($catalogue instanceof CatalogueMetadataAwareInterface) {
            $catalogueMetadata = $catalogue->getCatalogueMetadata('', '');
            $this->addCatalogueMetadata($catalogueMetadata);
        }
    }

    public function addFallbackCatalogue(MessageCatalogueInterface $catalogue): void
    {
        // detect circular references
        $c = $catalogue;
        while ($c = $c->getFallbackCatalogue()) {
            if ($c->getLocale() === $this->getLocale()) {
                throw new LogicException(\sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
            }
        }

        $c = $this;
        do {
            if ($c->getLocale() === $catalogue->getLocale()) {
                throw new LogicException(\sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
            }

            foreach ($catalogue->getResources() as $resource) {
                $c->addResource($resource);
            }
        } while ($c = $c->parent);

        $catalogue->parent = $this;
        $this->fallbackCatalogue = $catalogue;

        foreach ($catalogue->getResources() as $resource) {
            $this->addResource($resource);
        }
    }

    public function getFallbackCatalogue(): ?MessageCatalogueInterface
    {
        return $this->fallbackCatalogue;
    }

    public function getResources(): array
    {
        return array_values($this->resources);
    }

    public function addResource(ResourceInterface $resource): void
    {
        $this->resources[$resource->__toString()] = $resource;
    }

    public function getMetadata(string $key = '', string $domain = 'messages'): mixed
    {
        if ('' == $domain) {
            return $this->metadata;
        }

        if (isset($this->metadata[$domain.self::INTL_DOMAIN_SUFFIX])) {
            if ('' === $key) {
                return $this->metadata[$domain.self::INTL_DOMAIN_SUFFIX];
            }

            if (isset($this->metadata[$domain.self::INTL_DOMAIN_SUFFIX][$key])) {
                return $this->metadata[$domain.self::INTL_DOMAIN_SUFFIX][$key];
            }
        }

        if (isset($this->metadata[$domain])) {
            if ('' == $key) {
                return $this->metadata[$domain];
            }

            if (isset($this->metadata[$domain][$key])) {
                return $this->metadata[$domain][$key];
            }
        }

        return null;
    }

    public function setMetadata(string $key, mixed $value, string $domain = 'messages'): void
    {
        $this->metadata[$domain][$key] = $value;
    }

    public function deleteMetadata(string $key = '', string $domain = 'messages'): void
    {
        if ('' == $domain) {
            $this->metadata = [];
        } elseif ('' == $key) {
            unset($this->metadata[$domain]);
        } else {
            unset($this->metadata[$domain][$key]);
        }
    }

    public function getCatalogueMetadata(string $key = '', string $domain = 'messages'): mixed
    {
        if (!$domain) {
            return $this->catalogueMetadata;
        }

        if (isset($this->catalogueMetadata[$domain])) {
            if (!$key) {
                return $this->catalogueMetadata[$domain];
            }

            if (isset($this->catalogueMetadata[$domain][$key])) {
                return $this->catalogueMetadata[$domain][$key];
            }
        }

        return null;
    }

    public function setCatalogueMetadata(string $key, mixed $value, string $domain = 'messages'): void
    {
        $this->catalogueMetadata[$domain][$key] = $value;
    }

    public function deleteCatalogueMetadata(string $key = '', string $domain = 'messages'): void
    {
        if (!$domain) {
            $this->catalogueMetadata = [];
        } elseif (!$key) {
            unset($this->catalogueMetadata[$domain]);
        } else {
            unset($this->catalogueMetadata[$domain][$key]);
        }
    }

    /**
     * Adds current values with the new values.
     *
     * @param array $values Values to add
     */
    private function addMetadata(array $values): void
    {
        foreach ($values as $domain => $keys) {
            foreach ($keys as $key => $value) {
                $this->setMetadata($key, $value, $domain);
            }
        }
    }

    private function addCatalogueMetadata(array $values): void
    {
        foreach ($values as $domain => $keys) {
            foreach ($keys as $key => $value) {
                $this->setCatalogueMetadata($key, $value, $domain);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;

/**
 * @author Yonel Ceruto <yonelceruto@gmail.com>
 */
class TranslatorPathsPass extends AbstractRecursivePass
{
    protected bool $skipScalars = true;

    private int $level = 0;

    /**
     * @var array<string, bool>
     */
    private array $paths = [];

    /**
     * @var array<int, Definition>
     */
    private array $definitions = [];

    /**
     * @var array<string, array<string, bool>>
     */
    private array $controllers = [];

    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('translator')) {
            return;
        }

        foreach ($this->findControllerArguments($container) as $controller => $argument) {
            $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller));
            if ($container->hasDefinition($id)) {
                [$locatorRef] = $argument->getValues();
                $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true;
            }
        }

        try {
            parent::process($container);

            $paths = [];
            foreach ($this->paths as $class => $_) {
                if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
                    $paths[] = $r->getFileName();
                    foreach ($r->getTraits() as $trait) {
                        $paths[] = $trait->getFileName();
                    }
                }
            }
            if ($paths) {
                if ($container->hasDefinition('console.command.translation_debug')) {
                    $definition = $container->getDefinition('console.command.translation_debug');
                    $definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths));
                }
                if ($container->hasDefinition('console.command.translation_extract')) {
                    $definition = $container->getDefinition('console.command.translation_extract');
                    $definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths));
                }
            }
        } finally {
            $this->level = 0;
            $this->paths = [];
            $this->definitions = [];
        }
    }

    protected function processValue(mixed $value, bool $isRoot = false): mixed
    {
        if ($value instanceof Reference) {
            if ('translator' === (string) $value) {
                for ($i = $this->level - 1; $i >= 0; --$i) {
                    $class = $this->definitions[$i]->getClass();

                    if (ServiceLocator::class === $class) {
                        if (!isset($this->controllers[$this->currentId ?? ''])) {
                            continue;
                        }
                        foreach ($this->controllers[$this->currentId ?? ''] as $class => $_) {
                            $this->paths[$class] = true;
                        }
                    } else {
                        $this->paths[$class] = true;
                    }

                    break;
                }
            }

            return $value;
        }

        if ($value instanceof Definition) {
            $this->definitions[$this->level++] = $value;
            $value = parent::processValue($value, $isRoot);
            unset($this->definitions[--$this->level]);

            return $value;
        }

        return parent::processValue($value, $isRoot);
    }

    private function findControllerArguments(ContainerBuilder $container): array
    {
        if (!$container->has('argument_resolver.service')) {
            return [];
        }
        $resolverDef = $container->findDefinition('argument_resolver.service');

        if (TraceableValueResolver::class === $resolverDef->getClass()) {
            $resolverDef = $container->getDefinition($resolverDef->getArgument(0));
        }

        $argument = $resolverDef->getArgument(0);
        if ($argument instanceof Reference) {
            $argument = $container->getDefinition($argument);
        }

        return $argument->getArgument(0);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Adds tagged translation.formatter services to translation writer.
 */
class TranslationDumperPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('translation.writer')) {
            return;
        }

        $definition = $container->getDefinition('translation.writer');

        foreach ($container->findTaggedServiceIds('translation.dumper', true) as $id => $attributes) {
            $definition->addMethodCall('addDumper', [$attributes[0]['alias'], new Reference($id)]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class TranslatorPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('translator.default')) {
            return;
        }

        $loaders = [];
        $loaderRefs = [];
        foreach ($container->findTaggedServiceIds('translation.loader', true) as $id => $attributes) {
            $loaderRefs[$id] = new Reference($id);
            $loaders[$id][] = $attributes[0]['alias'];
            if (isset($attributes[0]['legacy-alias'])) {
                $loaders[$id][] = $attributes[0]['legacy-alias'];
            }
        }

        if ($container->hasDefinition('translation.reader')) {
            $definition = $container->getDefinition('translation.reader');
            foreach ($loaders as $id => $formats) {
                foreach ($formats as $format) {
                    $definition->addMethodCall('addLoader', [$format, $loaderRefs[$id]]);
                }
            }
        }

        $container
            ->findDefinition('translator.default')
            ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
            ->replaceArgument(3, $loaders)
        ;

        if ($container->hasDefinition('validator') && $container->hasDefinition('translation.extractor.visitor.constraint')) {
            $constraintVisitorDefinition = $container->getDefinition('translation.extractor.visitor.constraint');
            $constraintClassNames = [];

            foreach ($container->getDefinitions() as $definition) {
                if (!$definition->hasTag('validator.constraint_validator')) {
                    continue;
                }
                // Resolve constraint validator FQCN even if defined as %foo.validator.class% parameter
                $className = $container->getParameterBag()->resolveValue($definition->getClass());
                // Extraction of the constraint class name from the Constraint Validator FQCN
                $constraintClassNames[] = str_replace('Validator', '', substr(strrchr($className, '\\'), 1));
            }

            $constraintVisitorDefinition->setArgument(0, $constraintClassNames);
        }

        if (!$container->hasParameter('twig.default_path')) {
            return;
        }

        $paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(1));
        if ($container->hasDefinition('console.command.translation_debug')) {
            $definition = $container->getDefinition('console.command.translation_debug');
            $definition->replaceArgument(4, $container->getParameter('twig.default_path'));

            if (\count($definition->getArguments()) > 6) {
                $definition->replaceArgument(6, $paths);
            }
        }
        if ($container->hasDefinition('console.command.translation_extract')) {
            $definition = $container->getDefinition('console.command.translation_extract');
            $definition->replaceArgument(5, $container->getParameter('twig.default_path'));

            if (\count($definition->getArguments()) > 7) {
                $definition->replaceArgument(7, $paths);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Adds tagged translation.extractor services to translation extractor.
 */
class TranslationExtractorPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasDefinition('translation.extractor')) {
            return;
        }

        $definition = $container->getDefinition('translation.extractor');

        foreach ($container->findTaggedServiceIds('translation.extractor', true) as $id => $attributes) {
            $definition->addMethodCall('addExtractor', [$attributes[0]['alias'] ?? $id, new Reference($id)]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class LoggingTranslatorPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) {
            return;
        }

        if (!$container->hasParameter('translator.logging') || !$container->getParameter('translator.logging')) {
            return;
        }

        $translatorAlias = $container->getAlias('translator');
        $definition = $container->getDefinition((string) $translatorAlias);
        $class = $container->getParameterBag()->resolveValue($definition->getClass());

        if (!$r = $container->getReflectionClass($class)) {
            throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
        }

        if (!$r->isSubclassOf(TranslatorInterface::class) || !$r->isSubclassOf(TranslatorBagInterface::class)) {
            return;
        }

        $container->getDefinition('translator.logging')->setDecoratedService('translator');
        $warmer = $container->getDefinition('translation.warmer');
        $subscriberAttributes = $warmer->getTag('container.service_subscriber');
        $warmer->clearTag('container.service_subscriber');

        foreach ($subscriberAttributes as $k => $v) {
            if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) {
                $warmer->addTag('container.service_subscriber', $v);
            }
        }
        $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Translation\TranslatorBagInterface;

/**
 * @author Christian Flothmann <christian.flothmann@sensiolabs.de>
 */
class DataCollectorTranslatorPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        if (!$container->has('translator')) {
            return;
        }

        $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass());

        if (!is_subclass_of($translatorClass, TranslatorBagInterface::class)) {
            $container->removeDefinition('translator.data_collector');
            $container->removeDefinition('data_collector.translation');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Contracts\Service\ResetInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 *
 * @final since Symfony 7.1
 */
class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, WarmableInterface, ResetInterface
{
    public const MESSAGE_DEFINED = 0;
    public const MESSAGE_MISSING = 1;
    public const MESSAGE_EQUALS_FALLBACK = 2;

    private array $messages = [];

    public function __construct(
        private TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator,
    ) {
    }

    public function reset(): void
    {
        $this->messages = [];
    }

    public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
        $this->collectMessage($locale, $domain, $id, $trans, $parameters);

        return $trans;
    }

    public function setLocale(string $locale): void
    {
        $this->translator->setLocale($locale);
    }

    public function getLocale(): string
    {
        return $this->translator->getLocale();
    }

    public function getCatalogue(?string $locale = null): MessageCatalogueInterface
    {
        return $this->translator->getCatalogue($locale);
    }

    public function getCatalogues(): array
    {
        return $this->translator->getCatalogues();
    }

    public function warmUp(string $cacheDir, ?string $buildDir = null): array
    {
        if ($this->translator instanceof WarmableInterface) {
            return $this->translator->warmUp($cacheDir, $buildDir);
        }

        return [];
    }

    /**
     * Gets the fallback locales.
     */
    public function getFallbackLocales(): array
    {
        if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
            return $this->translator->getFallbackLocales();
        }

        return [];
    }

    public function getGlobalParameters(): array
    {
        if ($this->translator instanceof Translator || method_exists($this->translator, 'getGlobalParameters')) {
            return $this->translator->getGlobalParameters();
        }

        return [];
    }

    public function __call(string $method, array $args): mixed
    {
        return $this->translator->{$method}(...$args);
    }

    public function getCollectedMessages(): array
    {
        return $this->messages;
    }

    private function collectMessage(?string $locale, ?string $domain, string $id, string $translation, ?array $parameters = []): void
    {
        $domain ??= 'messages';

        $catalogue = $this->translator->getCatalogue($locale);
        $locale = $catalogue->getLocale();
        $fallbackLocale = null;
        if ($catalogue->defines($id, $domain)) {
            $state = self::MESSAGE_DEFINED;
        } elseif ($catalogue->has($id, $domain)) {
            $state = self::MESSAGE_EQUALS_FALLBACK;

            $fallbackCatalogue = $catalogue->getFallbackCatalogue();
            while ($fallbackCatalogue) {
                if ($fallbackCatalogue->defines($id, $domain)) {
                    $fallbackLocale = $fallbackCatalogue->getLocale();
                    break;
                }
                $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
            }
        } else {
            $state = self::MESSAGE_MISSING;
        }

        $this->messages[] = [
            'locale' => $locale,
            'fallbackLocale' => $fallbackLocale,
            'domain' => $domain,
            'id' => $id,
            'translation' => $translation,
            'parameters' => $parameters,
            'state' => $state,
            'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null,
        ];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\DataCollector;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
use Symfony\Component\Translation\DataCollectorTranslator;
use Symfony\Component\VarDumper\Cloner\Data;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 *
 * @final
 */
class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
{
    public function __construct(
        private DataCollectorTranslator $translator,
    ) {
    }

    public function lateCollect(): void
    {
        $messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages());

        $this->data += $this->computeCount($messages);
        $this->data['messages'] = $messages;

        $this->data = $this->cloneVar($this->data);
    }

    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        $this->data['locale'] = $this->translator->getLocale();
        $this->data['fallback_locales'] = $this->translator->getFallbackLocales();
        $this->data['global_parameters'] = $this->translator->getGlobalParameters();
    }

    public function reset(): void
    {
        $this->data = [];
    }

    public function getMessages(): array|Data
    {
        return $this->data['messages'] ?? [];
    }

    public function getCountMissings(): int
    {
        return $this->data[DataCollectorTranslator::MESSAGE_MISSING] ?? 0;
    }

    public function getCountFallbacks(): int
    {
        return $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] ?? 0;
    }

    public function getCountDefines(): int
    {
        return $this->data[DataCollectorTranslator::MESSAGE_DEFINED] ?? 0;
    }

    public function getLocale(): ?string
    {
        return !empty($this->data['locale']) ? $this->data['locale'] : null;
    }

    /**
     * @internal
     */
    public function getFallbackLocales(): Data|array
    {
        return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : [];
    }

    /**
     * @internal
     */
    public function getGlobalParameters(): Data|array
    {
        return $this->data['global_parameters'] ?? [];
    }

    public function getName(): string
    {
        return 'translation';
    }

    private function sanitizeCollectedMessages(array $messages): array
    {
        $result = [];
        foreach ($messages as $key => $message) {
            $messageId = $message['locale'].$message['domain'].$message['id'];

            if (!isset($result[$messageId])) {
                $message['count'] = 1;
                $message['parameters'] = !empty($message['parameters']) ? [$message['parameters']] : [];
                $messages[$key]['translation'] = $this->sanitizeString($message['translation']);
                $result[$messageId] = $message;
            } else {
                if (!empty($message['parameters'])) {
                    $result[$messageId]['parameters'][] = $message['parameters'];
                }

                ++$result[$messageId]['count'];
            }

            unset($messages[$key]);
        }

        return $result;
    }

    private function computeCount(array $messages): array
    {
        $count = [
            DataCollectorTranslator::MESSAGE_DEFINED => 0,
            DataCollectorTranslator::MESSAGE_MISSING => 0,
            DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0,
        ];

        foreach ($messages as $message) {
            ++$count[$message['state']];
        }

        return $count;
    }

    private function sanitizeString(string $string, int $length = 80): string
    {
        $string = trim(preg_replace('/\s+/', ' ', $string));

        if (false !== $encoding = mb_detect_encoding($string, null, true)) {
            if (mb_strlen($string, $encoding) > $length) {
                return mb_substr($string, 0, $length - 3, $encoding).'...';
            }
        } elseif (\strlen($string) > $length) {
            return substr($string, 0, $length - 3).'...';
        }

        return $string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\Translation\Dumper\XliffFileDumper;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\Provider\ProviderInterface;
use Symfony\Component\Translation\TranslatorBag;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * A test case to ease testing a translation provider.
 *
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
abstract class ProviderTestCase extends TestCase
{
    protected HttpClientInterface $client;
    protected LoggerInterface|MockObject $logger;
    protected string $defaultLocale;
    protected LoaderInterface|MockObject $loader;
    protected XliffFileDumper|MockObject $xliffFileDumper;
    protected TranslatorBagInterface|MockObject $translatorBag;

    abstract public static function createProvider(HttpClientInterface $client, LoaderInterface $loader, LoggerInterface $logger, string $defaultLocale, string $endpoint): ProviderInterface;

    /**
     * @return iterable<array{0: ProviderInterface, 1: string}>
     */
    abstract public static function toStringProvider(): iterable;

    /**
     * @dataProvider toStringProvider
     */
    #[DataProvider('toStringProvider')]
    public function testToString(ProviderInterface $provider, string $expected)
    {
        $this->assertSame($expected, (string) $provider);
    }

    protected function getClient(): MockHttpClient
    {
        return $this->client ??= new MockHttpClient();
    }

    protected function getLoader(): LoaderInterface
    {
        return $this->loader ??= new ArrayLoader();
    }

    protected function getLogger(): LoggerInterface
    {
        return $this->logger ??= new NullLogger();
    }

    protected function getDefaultLocale(): string
    {
        return $this->defaultLocale ??= 'en';
    }

    protected function getXliffFileDumper(): XliffFileDumper
    {
        return $this->xliffFileDumper ??= new XliffFileDumper();
    }

    protected function getTranslatorBag(): TranslatorBagInterface
    {
        return $this->translatorBag ??= new TranslatorBag();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use Symfony\Component\Translation\Exception\IncompleteDsnException;
use Symfony\Component\Translation\Provider\Dsn;

trait IncompleteDsnTestTrait
{
    /**
     * @return iterable<array{0: string, 1?: string|null}>
     */
    abstract public static function incompleteDsnProvider(): iterable;

    /**
     * @dataProvider incompleteDsnProvider
     */
    #[DataProvider('incompleteDsnProvider')]
    public function testIncompleteDsnException(string $dsn, ?string $message = null)
    {
        $factory = $this->createFactory();

        $dsn = new Dsn($dsn);

        $this->expectException(IncompleteDsnException::class);
        if (null !== $message) {
            $this->expectExceptionMessage($message);
        }

        $factory->create($dsn);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test;

use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\Translation\Dumper\XliffFileDumper;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * A test case to ease testing a translation provider factory.
 *
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 *
 * @deprecated since Symfony 7.2, use AbstractProviderFactoryTestCase instead
 */
abstract class ProviderFactoryTestCase extends AbstractProviderFactoryTestCase
{
    use IncompleteDsnTestTrait;

    protected HttpClientInterface $client;
    protected LoggerInterface|MockObject $logger;
    protected string $defaultLocale;
    protected LoaderInterface|MockObject $loader;
    protected XliffFileDumper|MockObject $xliffFileDumper;
    protected TranslatorBagInterface|MockObject $translatorBag;

    /**
     * @return iterable<array{0: string, 1?: string|null}>
     */
    public static function unsupportedSchemeProvider(): iterable
    {
        return [];
    }

    /**
     * @return iterable<array{0: string, 1?: string|null}>
     */
    public static function incompleteDsnProvider(): iterable
    {
        return [];
    }

    protected function getClient(): HttpClientInterface
    {
        return $this->client ??= new MockHttpClient();
    }

    protected function getLogger(): LoggerInterface
    {
        return $this->logger ??= $this->createMock(LoggerInterface::class);
    }

    protected function getDefaultLocale(): string
    {
        return $this->defaultLocale ??= 'en';
    }

    protected function getLoader(): LoaderInterface
    {
        return $this->loader ??= $this->createMock(LoaderInterface::class);
    }

    protected function getXliffFileDumper(): XliffFileDumper
    {
        return $this->xliffFileDumper ??= $this->createMock(XliffFileDumper::class);
    }

    protected function getTranslatorBag(): TranslatorBagInterface
    {
        return $this->translatorBag ??= $this->createMock(TranslatorBagInterface::class);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
use Symfony\Component\Translation\Provider\Dsn;
use Symfony\Component\Translation\Provider\ProviderFactoryInterface;

abstract class AbstractProviderFactoryTestCase extends TestCase
{
    abstract public function createFactory(): ProviderFactoryInterface;

    /**
     * @return iterable<array{0: bool, 1: string}>
     */
    abstract public static function supportsProvider(): iterable;

    /**
     * @return iterable<array{0: string, 1: string}>
     */
    abstract public static function createProvider(): iterable;

    /**
     * @return iterable<array{0: string, 1?: string|null}>
     */
    abstract public static function unsupportedSchemeProvider(): iterable;

    /**
     * @dataProvider supportsProvider
     */
    #[DataProvider('supportsProvider')]
    public function testSupports(bool $expected, string $dsn)
    {
        $factory = $this->createFactory();

        $this->assertSame($expected, $factory->supports(new Dsn($dsn)));
    }

    /**
     * @dataProvider createProvider
     */
    #[DataProvider('createProvider')]
    public function testCreate(string $expected, string $dsn)
    {
        $factory = $this->createFactory();
        $provider = $factory->create(new Dsn($dsn));

        $this->assertSame($expected, (string) $provider);
    }

    /**
     * @dataProvider unsupportedSchemeProvider
     */
    #[DataProvider('unsupportedSchemeProvider')]
    public function testUnsupportedSchemeException(string $dsn, ?string $message = null)
    {
        $factory = $this->createFactory();

        $dsn = new Dsn($dsn);

        $this->expectException(UnsupportedSchemeException::class);
        if (null !== $message) {
            $this->expectExceptionMessage($message);
        }

        $factory->create($dsn);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\CI\GithubActionReporter;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Util\XliffUtils;

/**
 * Validates XLIFF files syntax and outputs encountered errors.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Javier Eguiluz <javier.eguiluz@gmail.com>
 */
#[AsCommand(name: 'lint:xliff', description: 'Lint an XLIFF file and outputs encountered errors')]
class XliffLintCommand extends Command
{
    private string $format;
    private bool $displayCorrectFiles;
    private ?\Closure $directoryIteratorProvider;
    private ?\Closure $isReadableProvider;

    public function __construct(
        ?string $name = null,
        ?callable $directoryIteratorProvider = null,
        ?callable $isReadableProvider = null,
        private bool $requireStrictFileNames = true,
    ) {
        parent::__construct($name);

        $this->directoryIteratorProvider = null === $directoryIteratorProvider ? null : $directoryIteratorProvider(...);
        $this->isReadableProvider = null === $isReadableProvider ? null : $isReadableProvider(...);
    }

    protected function configure(): void
    {
        $this
            ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
            ->addOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())))
            ->setHelp(<<<EOF
                The <info>%command.name%</info> command lints an XLIFF file and outputs to STDOUT
                the first encountered syntax error.

                You can validates XLIFF contents passed from STDIN:

                  <info>cat filename | php %command.full_name% -</info>

                You can also validate the syntax of a file:

                  <info>php %command.full_name% filename</info>

                Or of a whole directory:

                  <info>php %command.full_name% dirname</info>

                The <info>--format</info> option specifies the format of the command output:

                  <info>php %command.full_name% dirname --format=json</info>

                EOF
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $filenames = (array) $input->getArgument('filename');
        $this->format = $input->getOption('format') ?? (GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt');
        $this->displayCorrectFiles = $output->isVerbose();

        if (['-'] === $filenames) {
            return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]);
        }

        if (!$filenames) {
            throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
        }

        $filesInfo = [];
        foreach ($filenames as $filename) {
            if (!$this->isReadable($filename)) {
                throw new RuntimeException(\sprintf('File or directory "%s" is not readable.', $filename));
            }

            foreach ($this->getFiles($filename) as $file) {
                $filesInfo[] = $this->validate(file_get_contents($file), $file);
            }
        }

        return $this->display($io, $filesInfo);
    }

    private function validate(string $content, ?string $file = null): array
    {
        $errors = [];

        // Avoid: Warning DOMDocument::loadXML(): Empty string supplied as input
        if ('' === trim($content)) {
            return ['file' => $file, 'valid' => true];
        }

        $internal = libxml_use_internal_errors(true);

        $document = new \DOMDocument();
        $document->loadXML($content);

        if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
            $normalizedLocalePattern = \sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/'));
            // strict file names require translation files to be named '____.locale.xlf'
            // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
            // also, the regexp matching must be case-insensitive, as defined for 'target-language' values
            // http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language
            $expectedFilenamePattern = $this->requireStrictFileNames ? \sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : \sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern);

            if (0 === preg_match($expectedFilenamePattern, basename($file))) {
                $errors[] = [
                    'line' => -1,
                    'column' => -1,
                    'message' => \sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
                ];
            }
        }

        foreach (XliffUtils::validateSchema($document) as $xmlError) {
            $errors[] = [
                'line' => $xmlError['line'],
                'column' => $xmlError['column'],
                'message' => $xmlError['message'],
            ];
        }

        libxml_clear_errors();
        libxml_use_internal_errors($internal);

        return ['file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors];
    }

    private function display(SymfonyStyle $io, array $files): int
    {
        return match ($this->format) {
            'txt' => $this->displayTxt($io, $files),
            'json' => $this->displayJson($io, $files),
            'github' => $this->displayTxt($io, $files, true),
            default => throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
        };
    }

    private function displayTxt(SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false): int
    {
        $countFiles = \count($filesInfo);
        $erroredFiles = 0;
        $githubReporter = $errorAsGithubAnnotations ? new GithubActionReporter($io) : null;

        foreach ($filesInfo as $info) {
            if ($info['valid'] && $this->displayCorrectFiles) {
                $io->comment('<info>OK</info>'.($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
            } elseif (!$info['valid']) {
                ++$erroredFiles;
                $io->text('<error> ERROR </error>'.($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
                $io->listing(array_map(static function ($error) use ($info, $githubReporter) {
                    // general document errors have a '-1' line number
                    $line = -1 === $error['line'] ? null : $error['line'];

                    $githubReporter?->error($error['message'], $info['file'], $line, null !== $line ? $error['column'] : null);

                    return null === $line ? $error['message'] : \sprintf('Line %d, Column %d: %s', $line, $error['column'], $error['message']);
                }, $info['messages']));
            }
        }

        if (0 === $erroredFiles) {
            $io->success(\sprintf('All %d XLIFF files contain valid syntax.', $countFiles));
        } else {
            $io->warning(\sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
        }

        return min($erroredFiles, 1);
    }

    private function displayJson(SymfonyStyle $io, array $filesInfo): int
    {
        $errors = 0;

        array_walk($filesInfo, static function (&$v) use (&$errors) {
            $v['file'] = (string) $v['file'];
            if (!$v['valid']) {
                ++$errors;
            }
        });

        $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));

        return min($errors, 1);
    }

    /**
     * @return iterable<\SplFileInfo>
     */
    private function getFiles(string $fileOrDirectory): iterable
    {
        if (is_file($fileOrDirectory)) {
            yield new \SplFileInfo($fileOrDirectory);

            return;
        }

        foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
            if (!\in_array($file->getExtension(), ['xlf', 'xliff'], true)) {
                continue;
            }

            yield $file;
        }
    }

    /**
     * @return iterable<\SplFileInfo>
     */
    private function getDirectoryIterator(string $directory): iterable
    {
        $default = static fn ($directory) => new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
            \RecursiveIteratorIterator::LEAVES_ONLY
        );

        if (null !== $this->directoryIteratorProvider) {
            return ($this->directoryIteratorProvider)($directory, $default);
        }

        return $default($directory);
    }

    private function isReadable(string $fileOrDirectory): bool
    {
        $default = static fn ($fileOrDirectory) => is_readable($fileOrDirectory);

        if (null !== $this->isReadableProvider) {
            return ($this->isReadableProvider)($fileOrDirectory, $default);
        }

        return $default($fileOrDirectory);
    }

    private function getTargetLanguageFromFile(\DOMDocument $xliffContents): ?string
    {
        foreach ($xliffContents->getElementsByTagName('file')[0]->attributes ?? [] as $attribute) {
            if ('target-language' === $attribute->nodeName) {
                return $attribute->nodeValue;
            }
        }

        return null;
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues($this->getAvailableFormatOptions());
        }
    }

    /** @return string[] */
    private function getAvailableFormatOptions(): array
    {
        return ['txt', 'json', 'github'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Command;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;
use Symfony\Component\Translation\TranslatorBag;

/**
 * @internal
 */
trait TranslationTrait
{
    private function readLocalTranslations(array $locales, array $domains, array $transPaths): TranslatorBag
    {
        $bag = new TranslatorBag();

        foreach ($locales as $locale) {
            $catalogue = new MessageCatalogue($locale);
            foreach ($transPaths as $path) {
                $this->reader->read($path, $catalogue);
            }

            if ($domains) {
                foreach ($domains as $domain) {
                    $bag->addCatalogue($this->filterCatalogue($catalogue, $domain));
                }
            } else {
                $bag->addCatalogue($catalogue);
            }
        }

        return $bag;
    }

    private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue
    {
        $filteredCatalogue = new MessageCatalogue($catalogue->getLocale());

        // extract intl-icu messages only
        $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
        if ($intlMessages = $catalogue->all($intlDomain)) {
            $filteredCatalogue->add($intlMessages, $intlDomain);
        }

        // extract all messages and subtract intl-icu messages
        if ($messages = array_diff($catalogue->all($domain), $intlMessages)) {
            $filteredCatalogue->add($messages, $domain);
        }
        foreach ($catalogue->getResources() as $resource) {
            $filteredCatalogue->addResource($resource);
        }

        if ($metadata = $catalogue->getMetadata('', $intlDomain)) {
            foreach ($metadata as $k => $v) {
                $filteredCatalogue->setMetadata($k, $v, $intlDomain);
            }
        }

        if ($metadata = $catalogue->getMetadata('', $domain)) {
            foreach ($metadata as $k => $v) {
                $filteredCatalogue->setMetadata($k, $v, $domain);
            }
        }

        return $filteredCatalogue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Translation\Exception\ExceptionInterface;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Lint translations files syntax and outputs encountered errors.
 *
 * @author Hugo Alliaume <hugo@alliau.me>
 */
#[AsCommand(name: 'lint:translations', description: 'Lint translations files syntax and outputs encountered errors')]
class TranslationLintCommand extends Command
{
    private SymfonyStyle $io;

    public function __construct(
        private TranslatorInterface&TranslatorBagInterface $translator,
        private array $enabledLocales = [],
    ) {
        parent::__construct();
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestOptionValuesFor('locale')) {
            $suggestions->suggestValues($this->enabledLocales);
        }
    }

    protected function configure(): void
    {
        $this
            ->setDefinition([
                new InputOption('locale', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to lint.', $this->enabledLocales),
            ])
            ->setHelp(<<<'EOF'
                The <info>%command.name%</> command lint translations.

                  <info>php %command.full_name%</>
                EOF
            );
    }

    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        $this->io = new SymfonyStyle($input, $output);
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $locales = $input->getOption('locale');

        /** @var array<string, array<string, array<string, \Throwable>>> $errors */
        $errors = [];
        $domainsByLocales = [];

        foreach ($locales as $locale) {
            $messageCatalogue = $this->translator->getCatalogue($locale);

            foreach ($domainsByLocales[$locale] = $messageCatalogue->getDomains() as $domain) {
                foreach ($messageCatalogue->all($domain) as $id => $translation) {
                    try {
                        $this->translator->trans($id, [], $domain, $messageCatalogue->getLocale());
                    } catch (ExceptionInterface $e) {
                        $errors[$locale][$domain][$id] = $e;
                    }
                }
            }
        }

        if (!$domainsByLocales) {
            $this->io->error('No translation files were found.');

            return Command::SUCCESS;
        }

        $this->io->table(
            ['Locale', 'Domains', 'Valid?'],
            array_map(
                static fn (string $locale, array $domains) => [
                    $locale,
                    implode(', ', $domains),
                    !\array_key_exists($locale, $errors) ? '<info>Yes</>' : '<error>No</>',
                ],
                array_keys($domainsByLocales),
                $domainsByLocales
            ),
        );

        if ($errors) {
            foreach ($errors as $locale => $domains) {
                foreach ($domains as $domain => $domainsErrors) {
                    $this->io->section(\sprintf('Errors for locale "%s" and domain "%s"', $locale, $domain));

                    foreach ($domainsErrors as $id => $error) {
                        $this->io->text(\sprintf('Translation key "%s" is invalid:', $id));
                        $this->io->error($error->getMessage());
                    }
                }
            }

            return Command::FAILURE;
        }

        $this->io->success('All translations are valid.');

        return Command::SUCCESS;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Translation\Provider\FilteringProvider;
use Symfony\Component\Translation\Provider\TranslationProviderCollection;
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
use Symfony\Component\Translation\TranslatorBag;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
#[AsCommand(name: 'translation:push', description: 'Push translations to a given provider.')]
final class TranslationPushCommand extends Command
{
    use TranslationTrait;

    public function __construct(
        private TranslationProviderCollection $providers,
        private TranslationReaderInterface $reader,
        private array $transPaths = [],
        private array $enabledLocales = [],
    ) {
        parent::__construct();
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('provider')) {
            $suggestions->suggestValues($this->providers->keys());

            return;
        }

        if ($input->mustSuggestOptionValuesFor('domains')) {
            $provider = $this->providers->get($input->getArgument('provider'));

            if (method_exists($provider, 'getDomains')) {
                $domains = $provider->getDomains();
                $suggestions->suggestValues($domains);
            }

            return;
        }

        if ($input->mustSuggestOptionValuesFor('locales')) {
            $suggestions->suggestValues($this->enabledLocales);
        }
    }

    protected function configure(): void
    {
        $keys = $this->providers->keys();
        $defaultProvider = 1 === \count($keys) ? $keys[0] : null;

        $this
            ->setDefinition([
                new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
                new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
                new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
                new InputOption('domains', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
                new InputOption('locales', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
            ])
            ->setHelp(<<<'EOF'
                The <info>%command.name%</> command pushes translations to the given provider. Only new
                translations are pushed, existing ones are not overwritten.

                You can overwrite existing translations by using the <info>--force</> flag:

                  <info>php %command.full_name% --force provider</>

                You can delete provider translations which are not present locally by using the <info>--delete-missing</> flag:

                  <info>php %command.full_name% --delete-missing provider</>

                Full example:

                  <info>php %command.full_name% provider --force --delete-missing --domains=messages --domains=validators --locales=en</>

                This command pushes all translations associated with the <info>messages</> and <info>validators</> domains for the <info>en</> locale.
                Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case.
                Provider translations for others domains and locales are ignored.

                EOF
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $provider = $this->providers->get($input->getArgument('provider'));

        if (!$this->enabledLocales) {
            throw new InvalidArgumentException(\sprintf('You must define "framework.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
        }

        $io = new SymfonyStyle($input, $output);
        $domains = $input->getOption('domains');
        $locales = $input->getOption('locales');
        $force = $input->getOption('force');
        $deleteMissing = $input->getOption('delete-missing');

        if (!$domains && $provider instanceof FilteringProvider) {
            $domains = $provider->getDomains();
        }

        // Reading local translations must be done after retrieving the domains from the provider
        // in order to manage only translations from configured domains
        $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);

        if (!$domains) {
            $domains = $this->getDomainsFromTranslatorBag($localTranslations);
        }

        if (!$deleteMissing && $force) {
            $provider->write($localTranslations);

            $io->success(\sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));

            return 0;
        }

        $providerTranslations = $provider->read($domains, $locales);

        if ($deleteMissing) {
            $provider->delete($providerTranslations->diff($localTranslations));

            $io->success(\sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));

            // Read provider translations again, after missing translations deletion,
            // to avoid push freshly deleted translations.
            $providerTranslations = $provider->read($domains, $locales);
        }

        $translationsToWrite = $localTranslations->diff($providerTranslations);

        if ($force) {
            $translationsToWrite->addBag($localTranslations->intersect($providerTranslations));
        }

        $provider->write($translationsToWrite);

        $io->success(\sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));

        return 0;
    }

    private function getDomainsFromTranslatorBag(TranslatorBag $translatorBag): array
    {
        $domains = [];

        foreach ($translatorBag->getCatalogues() as $catalogue) {
            $domains = array_merge($domains, $catalogue->getDomains());
        }

        return array_unique($domains);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Translation\Catalogue\TargetOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Provider\TranslationProviderCollection;
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
use Symfony\Component\Translation\Writer\TranslationWriterInterface;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
#[AsCommand(name: 'translation:pull', description: 'Pull translations from a given provider.')]
final class TranslationPullCommand extends Command
{
    use TranslationTrait;

    public function __construct(
        private TranslationProviderCollection $providerCollection,
        private TranslationWriterInterface $writer,
        private TranslationReaderInterface $reader,
        private string $defaultLocale,
        private array $transPaths = [],
        private array $enabledLocales = [],
    ) {
        parent::__construct();
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if ($input->mustSuggestArgumentValuesFor('provider')) {
            $suggestions->suggestValues($this->providerCollection->keys());

            return;
        }

        if ($input->mustSuggestOptionValuesFor('domains')) {
            $provider = $this->providerCollection->get($input->getArgument('provider'));

            if (method_exists($provider, 'getDomains')) {
                $suggestions->suggestValues($provider->getDomains());
            }

            return;
        }

        if ($input->mustSuggestOptionValuesFor('locales')) {
            $suggestions->suggestValues($this->enabledLocales);

            return;
        }

        if ($input->mustSuggestOptionValuesFor('format')) {
            $suggestions->suggestValues(['php', 'xlf', 'xlf12', 'xlf20', 'po', 'mo', 'yml', 'yaml', 'ts', 'csv', 'json', 'ini', 'res']);
        }
    }

    protected function configure(): void
    {
        $keys = $this->providerCollection->keys();
        $defaultProvider = 1 === \count($keys) ? $keys[0] : null;

        $this
            ->setDefinition([
                new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
                new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
                new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
                new InputOption('domains', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
                new InputOption('locales', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
                new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Override the default output format.', 'xlf12'),
                new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Write messages as a tree-like structure. Needs --format=yaml. The given value defines the level where to switch to inline YAML'),
            ])
            ->setHelp(<<<'EOF'
                The <info>%command.name%</> command pulls translations from the given provider. Only
                new translations are pulled, existing ones are not overwritten.

                You can overwrite existing translations (and remove the missing ones on local side) by using the <info>--force</> flag:

                  <info>php %command.full_name% --force provider</>

                Full example:

                  <info>php %command.full_name% provider --force --domains=messages --domains=validators --locales=en</>

                This command pulls all translations associated with the <info>messages</> and <info>validators</> domains for the <info>en</> locale.
                Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case.
                Local translations for others domains and locales are ignored.

                EOF
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);

        $provider = $this->providerCollection->get($input->getArgument('provider'));
        $force = $input->getOption('force');
        $intlIcu = $input->getOption('intl-icu');
        $locales = $input->getOption('locales') ?: $this->enabledLocales;
        $domains = $input->getOption('domains');
        $format = $input->getOption('format');
        $asTree = (int) $input->getOption('as-tree');
        $xliffVersion = '1.2';

        if ($intlIcu && !$force) {
            $io->note('--intl-icu option only has an effect when used with --force. Here, it will be ignored.');
        }

        switch ($format) {
            case 'xlf20': $xliffVersion = '2.0';
                // no break
            case 'xlf12': $format = 'xlf';
        }

        $writeOptions = [
            'path' => end($this->transPaths),
            'xliff_version' => $xliffVersion,
            'default_locale' => $this->defaultLocale,
            'as_tree' => (bool) $asTree,
            'inline' => $asTree,
        ];

        if (!$domains) {
            $domains = $provider->getDomains();
        }

        $providerTranslations = $provider->read($domains, $locales);

        if ($force) {
            foreach ($providerTranslations->getCatalogues() as $catalogue) {
                $operation = new TargetOperation(new MessageCatalogue($catalogue->getLocale()), $catalogue);
                if ($intlIcu) {
                    $operation->moveMessagesToIntlDomainsIfPossible();
                }
                $this->writer->write($operation->getResult(), $format, $writeOptions);
            }

            $io->success(\sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));

            return 0;
        }

        $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);

        // Append pulled translations to local ones.
        $localTranslations->addBag($providerTranslations->diff($localTranslations));

        foreach ($localTranslations->getCatalogues() as $catalogue) {
            $this->writer->write($catalogue, $format, $writeOptions);
        }

        $io->success(\sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));

        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Translation\Extractor\Visitor\AbstractVisitor;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * PhpAstExtractor extracts translation messages from a PHP AST.
 *
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
final class PhpAstExtractor extends AbstractFileExtractor implements ExtractorInterface
{
    private Parser $parser;

    public function __construct(
        /**
         * @param iterable<AbstractVisitor&NodeVisitor> $visitors
         */
        private readonly iterable $visitors,
        private string $prefix = '',
    ) {
        if (!class_exists(ParserFactory::class)) {
            throw new \LogicException(\sprintf('You cannot use "%s" as the "nikic/php-parser" package is not installed. Try running "composer require nikic/php-parser".', static::class));
        }

        $this->parser = (new ParserFactory())->createForHostVersion();
    }

    public function extract(iterable|string $resource, MessageCatalogue $catalogue): void
    {
        foreach ($this->extractFiles($resource) as $file) {
            $traverser = new NodeTraverser();

            // This is needed to resolve namespaces in class methods/constants.
            $nameResolver = new NodeVisitor\NameResolver();
            $traverser->addVisitor($nameResolver);

            foreach ($this->visitors as $visitor) {
                $visitor->initialize($catalogue, $file, $this->prefix);
                $traverser->addVisitor($visitor);
            }

            $nodes = $this->parser->parse(file_get_contents($file));
            $traverser->traverse($nodes);
        }
    }

    public function setPrefix(string $prefix): void
    {
        $this->prefix = $prefix;
    }

    protected function canBeExtracted(string $file): bool
    {
        return 'php' === pathinfo($file, \PATHINFO_EXTENSION)
            && $this->isFile($file)
            && preg_match('/\bt\(|->trans\(|TranslatableMessage|Symfony\\\\Component\\\\Validator\\\\Constraints/i', file_get_contents($file));
    }

    protected function extractFromDirectory(array|string $resource): iterable|Finder
    {
        if (!class_exists(Finder::class)) {
            throw new \LogicException(\sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class));
        }

        return (new Finder())->files()->name('*.php')->in($resource);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * Extracts translation messages from a directory or files to the catalogue.
 * New found messages are injected to the catalogue using the prefix.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface ExtractorInterface
{
    /**
     * Extracts translation messages from files, a file or a directory to the catalogue.
     *
     * @param string|iterable<string> $resource Files, a file or a directory
     *
     * @return void
     */
    public function extract(string|iterable $resource, MessageCatalogue $catalogue);

    /**
     * Sets the prefix that should be used for new found messages.
     *
     * @return void
     */
    public function setPrefix(string $prefix);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\Exception\InvalidArgumentException;

/**
 * Base class used by classes that extract translation messages from files.
 *
 * @author Marcos D. Sánchez <marcosdsanchez@gmail.com>
 */
abstract class AbstractFileExtractor
{
    protected function extractFiles(string|iterable $resource): iterable
    {
        if (is_iterable($resource)) {
            $files = [];
            foreach ($resource as $file) {
                if ($this->canBeExtracted($file)) {
                    $files[] = $this->toSplFileInfo($file);
                }
            }
        } elseif (is_file($resource)) {
            $files = $this->canBeExtracted($resource) ? [$this->toSplFileInfo($resource)] : [];
        } else {
            $files = $this->extractFromDirectory($resource);
        }

        return $files;
    }

    private function toSplFileInfo(string $file): \SplFileInfo
    {
        return new \SplFileInfo($file);
    }

    /**
     * @throws InvalidArgumentException
     */
    protected function isFile(string $file): bool
    {
        if (!is_file($file)) {
            throw new InvalidArgumentException(\sprintf('The "%s" file does not exist.', $file));
        }

        return true;
    }

    abstract protected function canBeExtracted(string $file): bool;

    abstract protected function extractFromDirectory(string|array $resource): iterable;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * ChainExtractor extracts translation messages from template files.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class ChainExtractor implements ExtractorInterface
{
    /**
     * The extractors.
     *
     * @var ExtractorInterface[]
     */
    private array $extractors = [];

    /**
     * Adds a loader to the translation extractor.
     */
    public function addExtractor(string $format, ExtractorInterface $extractor): void
    {
        $this->extractors[$format] = $extractor;
    }

    public function setPrefix(string $prefix): void
    {
        foreach ($this->extractors as $extractor) {
            $extractor->setPrefix($prefix);
        }
    }

    public function extract(string|iterable $directory, MessageCatalogue $catalogue): void
    {
        foreach ($this->extractors as $extractor) {
            $extractor->extract($directory, $catalogue);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor\Visitor;

use PhpParser\Node;
use PhpParser\NodeVisitor;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
final class TranslatableMessageVisitor extends AbstractVisitor implements NodeVisitor
{
    public function beforeTraverse(array $nodes): ?Node
    {
        return null;
    }

    public function enterNode(Node $node): ?Node
    {
        return null;
    }

    public function leaveNode(Node $node): ?Node
    {
        if (!$node instanceof Node\Expr\New_) {
            return null;
        }

        if (!($className = $node->class) instanceof Node\Name) {
            return null;
        }

        if (!\in_array('TranslatableMessage', $className->getParts(), true)) {
            return null;
        }

        $firstNamedArgumentIndex = $this->nodeFirstNamedArgumentIndex($node);

        if (!$messages = $this->getStringArguments($node, 0 < $firstNamedArgumentIndex ? 0 : 'message')) {
            return null;
        }

        $domain = $this->getStringArguments($node, 2 < $firstNamedArgumentIndex ? 2 : 'domain')[0] ?? null;

        foreach ($messages as $message) {
            $this->addMessageToCatalogue($message, $domain, $node->getStartLine());
        }

        return null;
    }

    public function afterTraverse(array $nodes): ?Node
    {
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor\Visitor;

use PhpParser\Node;
use Symfony\Component\Translation\MessageCatalogue;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
abstract class AbstractVisitor
{
    private MessageCatalogue $catalogue;
    private \SplFileInfo $file;
    private string $messagePrefix;

    public function initialize(MessageCatalogue $catalogue, \SplFileInfo $file, string $messagePrefix): void
    {
        $this->catalogue = $catalogue;
        $this->file = $file;
        $this->messagePrefix = $messagePrefix;
    }

    protected function addMessageToCatalogue(string $message, ?string $domain, int $line): void
    {
        $domain ??= 'messages';
        $this->catalogue->set($message, $this->messagePrefix.$message, $domain);
        $metadata = $this->catalogue->getMetadata($message, $domain) ?? [];
        $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $this->file);
        $metadata['sources'][] = $normalizedFilename.':'.$line;
        $this->catalogue->setMetadata($message, $metadata, $domain);
    }

    protected function getStringArguments(Node\Expr\CallLike|Node\Attribute|Node\Expr\New_ $node, int|string $index, bool $indexIsRegex = false): array
    {
        if (\is_string($index)) {
            return $this->getStringNamedArguments($node, $index, $indexIsRegex);
        }

        $args = $node instanceof Node\Expr\CallLike ? $node->getRawArgs() : $node->args;

        if (!($arg = $args[$index] ?? null) instanceof Node\Arg) {
            return [];
        }

        return (array) $this->getStringValue($arg->value);
    }

    protected function hasNodeNamedArguments(Node\Expr\CallLike|Node\Attribute|Node\Expr\New_ $node): bool
    {
        $args = $node instanceof Node\Expr\CallLike ? $node->getRawArgs() : $node->args;

        foreach ($args as $arg) {
            if ($arg instanceof Node\Arg && null !== $arg->name) {
                return true;
            }
        }

        return false;
    }

    protected function nodeFirstNamedArgumentIndex(Node\Expr\CallLike|Node\Attribute|Node\Expr\New_ $node): int
    {
        $args = $node instanceof Node\Expr\CallLike ? $node->getRawArgs() : $node->args;

        foreach ($args as $i => $arg) {
            if ($arg instanceof Node\Arg && null !== $arg->name) {
                return $i;
            }
        }

        return \PHP_INT_MAX;
    }

    private function getStringNamedArguments(Node\Expr\CallLike|Node\Attribute $node, ?string $argumentName = null, bool $isArgumentNamePattern = false): array
    {
        $args = $node instanceof Node\Expr\CallLike ? $node->getArgs() : $node->args;
        $argumentValues = [];

        foreach ($args as $arg) {
            if (!$isArgumentNamePattern && $arg->name?->toString() === $argumentName) {
                $argumentValues[] = $this->getStringValue($arg->value);
            } elseif ($isArgumentNamePattern && preg_match($argumentName, $arg->name?->toString() ?? '') > 0) {
                $argumentValues[] = $this->getStringValue($arg->value);
            }
        }

        return array_filter($argumentValues);
    }

    private function getStringValue(Node $node): ?string
    {
        if ($node instanceof Node\Scalar\String_) {
            return $node->value;
        }

        if ($node instanceof Node\Expr\BinaryOp\Concat) {
            if (null === $left = $this->getStringValue($node->left)) {
                return null;
            }

            if (null === $right = $this->getStringValue($node->right)) {
                return null;
            }

            return $left.$right;
        }

        if ($node instanceof Node\Expr\Assign && $node->expr instanceof Node\Scalar\String_) {
            return $node->expr->value;
        }

        if ($node instanceof Node\Expr\ClassConstFetch) {
            try {
                $reflection = new \ReflectionClass($node->class->toString());
                $constant = $reflection->getReflectionConstant($node->name->toString());
                if (false !== $constant && \is_string($constant->getValue())) {
                    return $constant->getValue();
                }
            } catch (\ReflectionException) {
            }
        }

        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor\Visitor;

use PhpParser\Node;
use PhpParser\NodeVisitor;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
final class TransMethodVisitor extends AbstractVisitor implements NodeVisitor
{
    public function beforeTraverse(array $nodes): ?Node
    {
        return null;
    }

    public function enterNode(Node $node): ?Node
    {
        return null;
    }

    public function leaveNode(Node $node): ?Node
    {
        if (!$node instanceof Node\Expr\MethodCall && !$node instanceof Node\Expr\FuncCall) {
            return null;
        }

        if (!\is_string($node->name) && !$node->name instanceof Node\Identifier && !$node->name instanceof Node\Name) {
            return null;
        }

        $name = $node->name instanceof Node\Name ? $node->name->getLast() : (string) $node->name;

        if ('trans' === $name || 't' === $name) {
            $firstNamedArgumentIndex = $this->nodeFirstNamedArgumentIndex($node);

            if (!$messages = $this->getStringArguments($node, 0 < $firstNamedArgumentIndex ? 0 : 'id')) {
                return null;
            }

            $domain = $this->getStringArguments($node, 2 < $firstNamedArgumentIndex ? 2 : 'domain')[0] ?? null;

            foreach ($messages as $message) {
                $this->addMessageToCatalogue($message, $domain, $node->getStartLine());
            }
        }

        return null;
    }

    public function afterTraverse(array $nodes): ?Node
    {
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor\Visitor;

use PhpParser\Node;
use PhpParser\NodeVisitor;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 *
 * Code mostly comes from https://github.com/php-translation/extractor/blob/master/src/Visitor/Php/Symfony/Constraint.php
 */
final class ConstraintVisitor extends AbstractVisitor implements NodeVisitor
{
    public function __construct(
        private readonly array $constraintClassNames = [],
    ) {
    }

    public function beforeTraverse(array $nodes): ?Node
    {
        return null;
    }

    public function enterNode(Node $node): ?Node
    {
        return null;
    }

    public function leaveNode(Node $node): ?Node
    {
        if (!$node instanceof Node\Expr\New_ && !$node instanceof Node\Attribute) {
            return null;
        }

        $className = $node instanceof Node\Attribute ? $node->name : $node->class;
        if (!$className instanceof Node\Name) {
            return null;
        }

        $parts = $className->getParts();
        $isConstraintClass = false;

        foreach ($parts as $part) {
            if (\in_array($part, $this->constraintClassNames, true)) {
                $isConstraintClass = true;

                break;
            }
        }

        if (!$isConstraintClass) {
            return null;
        }

        $arg = $node->args[0] ?? null;
        if (!$arg instanceof Node\Arg) {
            return null;
        }

        if ($this->hasNodeNamedArguments($node)) {
            $messages = $this->getStringArguments($node, '/message/i', true);
        } else {
            if (!$arg->value instanceof Node\Expr\Array_) {
                // There is no way to guess which argument is a message to be translated.
                return null;
            }

            $messages = [];
            $options = $arg->value;

            foreach ($options->items as $item) {
                if (!$item->key instanceof Node\Scalar\String_) {
                    continue;
                }

                if (false === stripos($item->key->value ?? '', 'message')) {
                    continue;
                }

                if (!$item->value instanceof Node\Scalar\String_) {
                    continue;
                }

                $messages[] = $item->value->value;

                break;
            }
        }

        foreach ($messages as $message) {
            $this->addMessageToCatalogue($message, 'validators', $node->getStartLine());
        }

        return null;
    }

    public function afterTraverse(array $nodes): ?Node
    {
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Psr\Log\LoggerInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
{
    public function __construct(
        private TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator,
        private LoggerInterface $logger,
    ) {
    }

    public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
        $this->log($id, $domain, $locale);

        return $trans;
    }

    public function setLocale(string $locale): void
    {
        $prev = $this->translator->getLocale();
        $this->translator->setLocale($locale);
        if ($prev === $locale) {
            return;
        }

        $this->logger->debug(\sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale));
    }

    public function getLocale(): string
    {
        return $this->translator->getLocale();
    }

    public function getCatalogue(?string $locale = null): MessageCatalogueInterface
    {
        return $this->translator->getCatalogue($locale);
    }

    public function getCatalogues(): array
    {
        return $this->translator->getCatalogues();
    }

    /**
     * Gets the fallback locales.
     */
    public function getFallbackLocales(): array
    {
        if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
            return $this->translator->getFallbackLocales();
        }

        return [];
    }

    public function __call(string $method, array $args): mixed
    {
        return $this->translator->{$method}(...$args);
    }

    /**
     * Logs for missing translations.
     */
    private function log(string $id, ?string $domain, ?string $locale): void
    {
        $domain ??= 'messages';

        $catalogue = $this->translator->getCatalogue($locale);
        if ($catalogue->defines($id, $domain)) {
            return;
        }

        if ($catalogue->has($id, $domain)) {
            $this->logger->debug('Translation use fallback catalogue.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
        } else {
            $this->logger->warning('Translation not found.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\TranslatorTrait;

/**
 * IdentityTranslator does not translate anything.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IdentityTranslator implements TranslatorInterface, LocaleAwareInterface
{
    use TranslatorTrait;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Util;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\InvalidResourceException;

/**
 * Provides some utility methods for XLIFF translation files, such as validating
 * their contents according to the XSD schema.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class XliffUtils
{
    /**
     * Gets xliff file version based on the root "version" attribute.
     *
     * Defaults to 1.2 for backwards compatibility.
     *
     * @throws InvalidArgumentException
     */
    public static function getVersionNumber(\DOMDocument $dom): string
    {
        foreach ($dom->getElementsByTagName('xliff') as $xliff) {
            $version = $xliff->attributes->getNamedItem('version');
            if ($version) {
                return $version->nodeValue;
            }

            $namespace = $xliff->attributes->getNamedItem('xmlns');
            if ($namespace) {
                if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
                    throw new InvalidArgumentException(\sprintf('Not a valid XLIFF namespace "%s".', $namespace));
                }

                return substr($namespace, 34);
            }
        }

        // Falls back to v1.2
        return '1.2';
    }

    /**
     * Validates and parses the given file into a DOMDocument.
     *
     * @throws InvalidResourceException
     */
    public static function validateSchema(\DOMDocument $dom): array
    {
        $xliffVersion = static::getVersionNumber($dom);
        $internalErrors = libxml_use_internal_errors(true);
        if ($shouldEnable = self::shouldEnableEntityLoader()) {
            $disableEntities = libxml_disable_entity_loader(false);
        }
        try {
            $isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion));
            if (!$isValid) {
                return self::getXmlErrors($internalErrors);
            }
        } finally {
            if ($shouldEnable) {
                libxml_disable_entity_loader($disableEntities);
            }
        }

        $dom->normalizeDocument();

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);

        return [];
    }

    public static function getErrorsAsString(array $xmlErrors): string
    {
        $errorsAsString = '';

        foreach ($xmlErrors as $error) {
            $errorsAsString .= \sprintf("[%s %s] %s (in %s - line %d, column %d)\n",
                \LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR',
                $error['code'],
                $error['message'],
                $error['file'],
                $error['line'],
                $error['column']
            );
        }

        return $errorsAsString;
    }

    private static function shouldEnableEntityLoader(): bool
    {
        static $dom, $schema;
        if (null === $dom) {
            $dom = new \DOMDocument();
            $dom->loadXML('<?xml version="1.0"?><test/>');

            $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
            register_shutdown_function(static function () use ($tmpfile) {
                @unlink($tmpfile);
            });
            $schema = '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:include schemaLocation="'.self::getFileUrl($tmpfile).'" />
</xsd:schema>';
            file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="test" type="testType" />
  <xsd:complexType name="testType"/>
</xsd:schema>');
        }

        return !@$dom->schemaValidateSource($schema);
    }

    private static function getFileUrl(string $path): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $parts = explode('/', str_replace('\\', '/', $path));
            $drive = array_shift($parts).'/';
        } else {
            $parts = explode('/', $path);
            $drive = '';
        }

        return 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
    }

    private static function getSchema(string $xliffVersion): string
    {
        if ('1.2' === $xliffVersion) {
            $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-1.2-transitional.xsd');
            $xmlUri = 'http://www.w3.org/2001/xml.xsd';
        } elseif ('2.0' === $xliffVersion) {
            $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd');
            $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
        } else {
            throw new InvalidArgumentException(\sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
        }

        return self::fixXmlLocation($schemaSource, $xmlUri);
    }

    /**
     * Internally changes the URI of a dependent xsd to be loaded locally.
     */
    private static function fixXmlLocation(string $schemaSource, string $xmlUri): string
    {
        $path = __DIR__.'/../Resources/schemas/xml.xsd';

        if (0 === stripos($path, 'phar://')) {
            if ($tmpfile = tempnam(sys_get_temp_dir(), 'symfony')) {
                copy($path, $tmpfile);
                $newPath = self::getFileUrl($tmpfile);
            } else {
                $parts = explode('/', '\\' === \DIRECTORY_SEPARATOR ? str_replace('\\', '/', $path) : $path);
                array_shift($parts);
                $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
                $newPath = 'phar:///'.$drive.implode('/', array_map('rawurlencode', $parts));
            }
        } else {
            $newPath = self::getFileUrl($path);
        }

        return str_replace($xmlUri, $newPath, $schemaSource);
    }

    /**
     * Returns the XML errors of the internal XML parser.
     */
    private static function getXmlErrors(bool $internalErrors): array
    {
        $errors = [];
        foreach (libxml_get_errors() as $error) {
            $errors[] = [
                'level' => \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
                'code' => $error->code,
                'message' => trim($error->message),
                'file' => $error->file ?: 'n/a',
                'line' => $error->line,
                'column' => $error->column,
            ];
        }

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);

        return $errors;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Util;

/**
 * ArrayConverter generates tree like structure from a message catalogue.
 * e.g. this
 *   'foo.bar1' => 'test1',
 *   'foo.bar2' => 'test2'
 * converts to follows:
 *   foo:
 *     bar1: test1
 *     bar2: test2.
 *
 * @author Gennady Telegin <gtelegin@gmail.com>
 */
class ArrayConverter
{
    /**
     * Converts linear messages array to tree-like array.
     * For example: ['foo.bar' => 'value'] will be converted to ['foo' => ['bar' => 'value']].
     *
     * @param array $messages Linear messages array
     */
    public static function expandToTree(array $messages): array
    {
        $tree = [];

        foreach ($messages as $id => $value) {
            $referenceToElement = &self::getElementByPath($tree, self::getKeyParts($id));

            $referenceToElement = $value;

            unset($referenceToElement);
        }

        return $tree;
    }

    private static function &getElementByPath(array &$tree, array $parts): mixed
    {
        $elem = &$tree;
        $parentOfElem = null;

        foreach ($parts as $i => $part) {
            if (isset($elem[$part]) && \is_string($elem[$part])) {
                /* Process next case:
                 *    'foo': 'test1',
                 *    'foo.bar': 'test2'
                 *
                 * $tree['foo'] was string before we found array {bar: test2}.
                 *  Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
                 */
                $elem = &$elem[implode('.', \array_slice($parts, $i))];
                break;
            }

            $parentOfElem = &$elem;
            $elem = &$elem[$part];
        }

        if ($elem && \is_array($elem) && $parentOfElem) {
            /* Process next case:
             *    'foo.bar': 'test1'
             *    'foo': 'test2'
             *
             * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
             * Cancel treating $tree['foo'] as array and cancel back it expansion,
             *  e.g. make it $tree['foo.bar'] = 'test1' again.
             */
            self::cancelExpand($parentOfElem, $part, $elem);
        }

        return $elem;
    }

    private static function cancelExpand(array &$tree, string $prefix, array $node): void
    {
        $prefix .= '.';

        foreach ($node as $id => $value) {
            if (\is_string($value)) {
                $tree[$prefix.$id] = $value;
            } else {
                self::cancelExpand($tree, $prefix.$id, $value);
            }
        }
    }

    /**
     * @return string[]
     */
    private static function getKeyParts(string $key): array
    {
        $parts = explode('.', $key);
        $partsCount = \count($parts);

        $result = [];
        $buffer = '';

        foreach ($parts as $index => $part) {
            if (0 === $index && '' === $part) {
                $buffer = '.';

                continue;
            }

            if ($index === $partsCount - 1 && '' === $part) {
                $buffer .= '.';
                $result[] = $buffer;

                continue;
            }

            if (isset($parts[$index + 1]) && '' === $parts[$index + 1]) {
                $buffer .= $part;

                continue;
            }

            if ($buffer) {
                $result[] = $buffer.$part;
                $buffer = '';

                continue;
            }

            $result[] = $part;
        }

        return $result;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Translation\Catalogue\AbstractOperation;
use Symfony\Component\Translation\Catalogue\TargetOperation;

final class TranslatorBag implements TranslatorBagInterface
{
    /** @var MessageCatalogue[] */
    private array $catalogues = [];

    public function addCatalogue(MessageCatalogue $catalogue): void
    {
        if (null !== $existingCatalogue = $this->getCatalogue($catalogue->getLocale())) {
            $catalogue->addCatalogue($existingCatalogue);
        }

        $this->catalogues[$catalogue->getLocale()] = $catalogue;
    }

    public function addBag(TranslatorBagInterface $bag): void
    {
        foreach ($bag->getCatalogues() as $catalogue) {
            $this->addCatalogue($catalogue);
        }
    }

    public function getCatalogue(?string $locale = null): MessageCatalogueInterface
    {
        if (null === $locale || !isset($this->catalogues[$locale])) {
            $this->catalogues[$locale] = new MessageCatalogue($locale);
        }

        return $this->catalogues[$locale];
    }

    public function getCatalogues(): array
    {
        return array_values($this->catalogues);
    }

    public function diff(TranslatorBagInterface $diffBag): self
    {
        $diff = new self();

        foreach ($this->catalogues as $locale => $catalogue) {
            if (null === $diffCatalogue = $diffBag->getCatalogue($locale)) {
                $diff->addCatalogue($catalogue);

                continue;
            }

            $operation = new TargetOperation($diffCatalogue, $catalogue);
            $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::NEW_BATCH);
            $newCatalogue = new MessageCatalogue($locale);

            foreach ($catalogue->getDomains() as $domain) {
                $newCatalogue->add($operation->getNewMessages($domain), $domain);
            }

            $diff->addCatalogue($newCatalogue);
        }

        return $diff;
    }

    public function intersect(TranslatorBagInterface $intersectBag): self
    {
        $diff = new self();

        foreach ($this->catalogues as $locale => $catalogue) {
            if (null === $intersectCatalogue = $intersectBag->getCatalogue($locale)) {
                continue;
            }

            $operation = new TargetOperation($catalogue, $intersectCatalogue);
            $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::OBSOLETE_BATCH);
            $obsoleteCatalogue = new MessageCatalogue($locale);

            foreach ($operation->getDomains() as $domain) {
                $obsoleteCatalogue->add(
                    array_diff($operation->getMessages($domain), $operation->getNewMessages($domain)),
                    $domain
                );
            }

            $diff->addCatalogue($obsoleteCatalogue);
        }

        return $diff;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\Exception\UnsupportedSchemeException;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
class TranslationProviderCollectionFactory
{
    /**
     * @param iterable<mixed, ProviderFactoryInterface> $factories
     */
    public function __construct(
        private iterable $factories,
        private array $enabledLocales,
    ) {
    }

    public function fromConfig(array $config): TranslationProviderCollection
    {
        $providers = [];
        foreach ($config as $name => $currentConfig) {
            $providers[$name] = $this->fromDsnObject(
                new Dsn($currentConfig['dsn']),
                !$currentConfig['locales'] ? $this->enabledLocales : $currentConfig['locales'],
                !$currentConfig['domains'] ? [] : $currentConfig['domains']
            );
        }

        return new TranslationProviderCollection($providers);
    }

    public function fromDsnObject(Dsn $dsn, array $locales, array $domains = []): ProviderInterface
    {
        foreach ($this->factories as $factory) {
            if ($factory->supports($dsn)) {
                return new FilteringProvider($factory->create($dsn), $locales, $domains);
            }
        }

        throw new UnsupportedSchemeException($dsn);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\Exception\InvalidArgumentException;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
final class TranslationProviderCollection
{
    /**
     * @var array<string, ProviderInterface>
     */
    private array $providers;

    /**
     * @param array<string, ProviderInterface> $providers
     */
    public function __construct(iterable $providers)
    {
        $this->providers = \is_array($providers) ? $providers : iterator_to_array($providers);
    }

    public function __toString(): string
    {
        return '['.implode(',', array_keys($this->providers)).']';
    }

    public function has(string $name): bool
    {
        return isset($this->providers[$name]);
    }

    public function get(string $name): ProviderInterface
    {
        if (!$this->has($name)) {
            throw new InvalidArgumentException(\sprintf('Provider "%s" not found. Available: "%s".', $name, (string) $this));
        }

        return $this->providers[$name];
    }

    public function keys(): array
    {
        return array_keys($this->providers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\Exception\InvalidArgumentException;
use Symfony\Component\Translation\Exception\MissingRequiredOptionException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Oskar Stark <oskarstark@googlemail.com>
 */
final class Dsn
{
    private ?string $scheme;
    private ?string $host;
    private ?string $user;
    private ?string $password;
    private ?int $port;
    private ?string $path;
    private array $options = [];
    private string $originalDsn;

    public function __construct(#[\SensitiveParameter] string $dsn)
    {
        $this->originalDsn = $dsn;

        if (false === $params = parse_url($dsn)) {
            throw new InvalidArgumentException('The translation provider DSN is invalid.');
        }

        if (!isset($params['scheme'])) {
            throw new InvalidArgumentException('The translation provider DSN must contain a scheme.');
        }
        $this->scheme = $params['scheme'];

        if (!isset($params['host'])) {
            throw new InvalidArgumentException('The translation provider DSN must contain a host (use "default" by default).');
        }
        $this->host = $params['host'];

        $this->user = '' !== ($params['user'] ?? '') ? rawurldecode($params['user']) : null;
        $this->password = '' !== ($params['pass'] ?? '') ? rawurldecode($params['pass']) : null;
        $this->port = $params['port'] ?? null;
        $this->path = $params['path'] ?? null;
        parse_str($params['query'] ?? '', $this->options);
    }

    public function getScheme(): string
    {
        return $this->scheme;
    }

    public function getHost(): string
    {
        return $this->host;
    }

    public function getUser(): ?string
    {
        return $this->user;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function getPort(?int $default = null): ?int
    {
        return $this->port ?? $default;
    }

    public function getOption(string $key, mixed $default = null): mixed
    {
        return $this->options[$key] ?? $default;
    }

    public function getRequiredOption(string $key): mixed
    {
        if (!\array_key_exists($key, $this->options) || '' === trim($this->options[$key])) {
            throw new MissingRequiredOptionException($key);
        }

        return $this->options[$key];
    }

    public function getOptions(): array
    {
        return $this->options;
    }

    public function getPath(): ?string
    {
        return $this->path;
    }

    public function getOriginalDsn(): string
    {
        return $this->originalDsn;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\Exception\IncompleteDsnException;

abstract class AbstractProviderFactory implements ProviderFactoryInterface
{
    public function supports(Dsn $dsn): bool
    {
        return \in_array($dsn->getScheme(), $this->getSupportedSchemes(), true);
    }

    /**
     * @return string[]
     */
    abstract protected function getSupportedSchemes(): array;

    protected function getUser(Dsn $dsn): string
    {
        return $dsn->getUser() ?? throw new IncompleteDsnException('User is not set.', $dsn->getScheme().'://'.$dsn->getHost());
    }

    protected function getPassword(Dsn $dsn): string
    {
        return $dsn->getPassword() ?? throw new IncompleteDsnException('Password is not set.', $dsn->getOriginalDsn());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\TranslatorBag;
use Symfony\Component\Translation\TranslatorBagInterface;

/**
 * Filters domains and locales between the Translator config values and those specific to each provider.
 *
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
class FilteringProvider implements ProviderInterface
{
    public function __construct(
        private ProviderInterface $provider,
        private array $locales,
        private array $domains = [],
    ) {
    }

    public function __toString(): string
    {
        return (string) $this->provider;
    }

    public function write(TranslatorBagInterface $translatorBag): void
    {
        $this->provider->write($translatorBag);
    }

    public function read(array $domains, array $locales): TranslatorBag
    {
        $domains = !$this->domains ? $domains : array_intersect($this->domains, $domains);
        $locales = array_intersect($this->locales, $locales);

        return $this->provider->read($domains, $locales);
    }

    public function delete(TranslatorBagInterface $translatorBag): void
    {
        $this->provider->delete($translatorBag);
    }

    public function getDomains(): array
    {
        return $this->domains;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\Exception\IncompleteDsnException;
use Symfony\Component\Translation\Exception\UnsupportedSchemeException;

interface ProviderFactoryInterface
{
    /**
     * @throws UnsupportedSchemeException
     * @throws IncompleteDsnException
     */
    public function create(Dsn $dsn): ProviderInterface;

    public function supports(Dsn $dsn): bool;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\Exception\UnsupportedSchemeException;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
final class NullProviderFactory extends AbstractProviderFactory
{
    public function create(Dsn $dsn): ProviderInterface
    {
        if ('null' === $dsn->getScheme()) {
            return new NullProvider();
        }

        throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes());
    }

    protected function getSupportedSchemes(): array
    {
        return ['null'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\TranslatorBag;
use Symfony\Component\Translation\TranslatorBagInterface;

interface ProviderInterface extends \Stringable
{
    /**
     * Translations available in the TranslatorBag only must be created.
     * Translations available in both the TranslatorBag and on the provider
     * must be overwritten.
     * Translations available on the provider only must be kept.
     */
    public function write(TranslatorBagInterface $translatorBag): void;

    public function read(array $domains, array $locales): TranslatorBag;

    public function delete(TranslatorBagInterface $translatorBag): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Provider;

use Symfony\Component\Translation\TranslatorBag;
use Symfony\Component\Translation\TranslatorBagInterface;

/**
 * @author Mathieu Santostefano <msantostefano@protonmail.com>
 */
class NullProvider implements ProviderInterface
{
    public function __toString(): string
    {
        return 'null';
    }

    public function write(TranslatorBagInterface $translatorBag, bool $override = false): void
    {
    }

    public function read(array $domains, array $locales): TranslatorBag
    {
        return new TranslatorBag();
    }

    public function delete(TranslatorBagInterface $translatorBag): void
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * This interface is used to get, set, and delete metadata about the translation messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface MetadataAwareInterface
{
    /**
     * Gets metadata for the given domain and key.
     *
     * Passing an empty domain will return an array with all metadata indexed by
     * domain and then by key. Passing an empty key will return an array with all
     * metadata for the given domain.
     *
     * @return mixed The value that was set or an array with the domains/keys or null
     */
    public function getMetadata(string $key = '', string $domain = 'messages'): mixed;

    /**
     * Adds metadata to a message domain.
     */
    public function setMetadata(string $key, mixed $value, string $domain = 'messages'): void;

    /**
     * Deletes metadata for the given key and domain.
     *
     * Passing an empty domain will delete all metadata. Passing an empty key will
     * delete all metadata for the given domain.
     */
    public function deleteMetadata(string $key = '', string $domain = 'messages'): void;
}
<?php

return [
    'İ' => 'i̇',
    'µ' => 'μ',
    'ſ' => 's',
    'ͅ' => 'ι',
    'ς' => 'σ',
    'ϐ' => 'β',
    'ϑ' => 'θ',
    'ϕ' => 'φ',
    'ϖ' => 'π',
    'ϰ' => 'κ',
    'ϱ' => 'ρ',
    'ϵ' => 'ε',
    'ẛ' => 'ṡ',
    'ι' => 'ι',
    'ß' => 'ss',
    'ŉ' => 'ʼn',
    'ǰ' => 'ǰ',
    'ΐ' => 'ΐ',
    'ΰ' => 'ΰ',
    'և' => 'եւ',
    'ẖ' => 'ẖ',
    'ẗ' => 'ẗ',
    'ẘ' => 'ẘ',
    'ẙ' => 'ẙ',
    'ẚ' => 'aʾ',
    'ẞ' => 'ss',
    'ὐ' => 'ὐ',
    'ὒ' => 'ὒ',
    'ὔ' => 'ὔ',
    'ὖ' => 'ὖ',
    'ᾀ' => 'ἀι',
    'ᾁ' => 'ἁι',
    'ᾂ' => 'ἂι',
    'ᾃ' => 'ἃι',
    'ᾄ' => 'ἄι',
    'ᾅ' => 'ἅι',
    'ᾆ' => 'ἆι',
    'ᾇ' => 'ἇι',
    'ᾈ' => 'ἀι',
    'ᾉ' => 'ἁι',
    'ᾊ' => 'ἂι',
    'ᾋ' => 'ἃι',
    'ᾌ' => 'ἄι',
    'ᾍ' => 'ἅι',
    'ᾎ' => 'ἆι',
    'ᾏ' => 'ἇι',
    'ᾐ' => 'ἠι',
    'ᾑ' => 'ἡι',
    'ᾒ' => 'ἢι',
    'ᾓ' => 'ἣι',
    'ᾔ' => 'ἤι',
    'ᾕ' => 'ἥι',
    'ᾖ' => 'ἦι',
    'ᾗ' => 'ἧι',
    'ᾘ' => 'ἠι',
    'ᾙ' => 'ἡι',
    'ᾚ' => 'ἢι',
    'ᾛ' => 'ἣι',
    'ᾜ' => 'ἤι',
    'ᾝ' => 'ἥι',
    'ᾞ' => 'ἦι',
    'ᾟ' => 'ἧι',
    'ᾠ' => 'ὠι',
    'ᾡ' => 'ὡι',
    'ᾢ' => 'ὢι',
    'ᾣ' => 'ὣι',
    'ᾤ' => 'ὤι',
    'ᾥ' => 'ὥι',
    'ᾦ' => 'ὦι',
    'ᾧ' => 'ὧι',
    'ᾨ' => 'ὠι',
    'ᾩ' => 'ὡι',
    'ᾪ' => 'ὢι',
    'ᾫ' => 'ὣι',
    'ᾬ' => 'ὤι',
    'ᾭ' => 'ὥι',
    'ᾮ' => 'ὦι',
    'ᾯ' => 'ὧι',
    'ᾲ' => 'ὰι',
    'ᾳ' => 'αι',
    'ᾴ' => 'άι',
    'ᾶ' => 'ᾶ',
    'ᾷ' => 'ᾶι',
    'ᾼ' => 'αι',
    'ῂ' => 'ὴι',
    'ῃ' => 'ηι',
    'ῄ' => 'ήι',
    'ῆ' => 'ῆ',
    'ῇ' => 'ῆι',
    'ῌ' => 'ηι',
    'ῒ' => 'ῒ',
    'ῖ' => 'ῖ',
    'ῗ' => 'ῗ',
    'ῢ' => 'ῢ',
    'ῤ' => 'ῤ',
    'ῦ' => 'ῦ',
    'ῧ' => 'ῧ',
    'ῲ' => 'ὼι',
    'ῳ' => 'ωι',
    'ῴ' => 'ώι',
    'ῶ' => 'ῶ',
    'ῷ' => 'ῶι',
    'ῼ' => 'ωι',
    'ﬀ' => 'ff',
    'ﬁ' => 'fi',
    'ﬂ' => 'fl',
    'ﬃ' => 'ffi',
    'ﬄ' => 'ffl',
    'ﬅ' => 'st',
    'ﬆ' => 'st',
    'ﬓ' => 'մն',
    'ﬔ' => 'մե',
    'ﬕ' => 'մի',
    'ﬖ' => 'վն',
    'ﬗ' => 'մխ',
];
<?php

// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt

return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';
<?php

return array (
  'A' => 'a',
  'B' => 'b',
  'C' => 'c',
  'D' => 'd',
  'E' => 'e',
  'F' => 'f',
  'G' => 'g',
  'H' => 'h',
  'I' => 'i',
  'J' => 'j',
  'K' => 'k',
  'L' => 'l',
  'M' => 'm',
  'N' => 'n',
  'O' => 'o',
  'P' => 'p',
  'Q' => 'q',
  'R' => 'r',
  'S' => 's',
  'T' => 't',
  'U' => 'u',
  'V' => 'v',
  'W' => 'w',
  'X' => 'x',
  'Y' => 'y',
  'Z' => 'z',
  'À' => 'à',
  'Á' => 'á',
  'Â' => 'â',
  'Ã' => 'ã',
  'Ä' => 'ä',
  'Å' => 'å',
  'Æ' => 'æ',
  'Ç' => 'ç',
  'È' => 'è',
  'É' => 'é',
  'Ê' => 'ê',
  'Ë' => 'ë',
  'Ì' => 'ì',
  'Í' => 'í',
  'Î' => 'î',
  'Ï' => 'ï',
  'Ð' => 'ð',
  'Ñ' => 'ñ',
  'Ò' => 'ò',
  'Ó' => 'ó',
  'Ô' => 'ô',
  'Õ' => 'õ',
  'Ö' => 'ö',
  'Ø' => 'ø',
  'Ù' => 'ù',
  'Ú' => 'ú',
  'Û' => 'û',
  'Ü' => 'ü',
  'Ý' => 'ý',
  'Þ' => 'þ',
  'Ā' => 'ā',
  'Ă' => 'ă',
  'Ą' => 'ą',
  'Ć' => 'ć',
  'Ĉ' => 'ĉ',
  'Ċ' => 'ċ',
  'Č' => 'č',
  'Ď' => 'ď',
  'Đ' => 'đ',
  'Ē' => 'ē',
  'Ĕ' => 'ĕ',
  'Ė' => 'ė',
  'Ę' => 'ę',
  'Ě' => 'ě',
  'Ĝ' => 'ĝ',
  'Ğ' => 'ğ',
  'Ġ' => 'ġ',
  'Ģ' => 'ģ',
  'Ĥ' => 'ĥ',
  'Ħ' => 'ħ',
  'Ĩ' => 'ĩ',
  'Ī' => 'ī',
  'Ĭ' => 'ĭ',
  'Į' => 'į',
  'İ' => 'i̇',
  'Ĳ' => 'ĳ',
  'Ĵ' => 'ĵ',
  'Ķ' => 'ķ',
  'Ĺ' => 'ĺ',
  'Ļ' => 'ļ',
  'Ľ' => 'ľ',
  'Ŀ' => 'ŀ',
  'Ł' => 'ł',
  'Ń' => 'ń',
  'Ņ' => 'ņ',
  'Ň' => 'ň',
  'Ŋ' => 'ŋ',
  'Ō' => 'ō',
  'Ŏ' => 'ŏ',
  'Ő' => 'ő',
  'Œ' => 'œ',
  'Ŕ' => 'ŕ',
  'Ŗ' => 'ŗ',
  'Ř' => 'ř',
  'Ś' => 'ś',
  'Ŝ' => 'ŝ',
  'Ş' => 'ş',
  'Š' => 'š',
  'Ţ' => 'ţ',
  'Ť' => 'ť',
  'Ŧ' => 'ŧ',
  'Ũ' => 'ũ',
  'Ū' => 'ū',
  'Ŭ' => 'ŭ',
  'Ů' => 'ů',
  'Ű' => 'ű',
  'Ų' => 'ų',
  'Ŵ' => 'ŵ',
  'Ŷ' => 'ŷ',
  'Ÿ' => 'ÿ',
  'Ź' => 'ź',
  'Ż' => 'ż',
  'Ž' => 'ž',
  'Ɓ' => 'ɓ',
  'Ƃ' => 'ƃ',
  'Ƅ' => 'ƅ',
  'Ɔ' => 'ɔ',
  'Ƈ' => 'ƈ',
  'Ɖ' => 'ɖ',
  'Ɗ' => 'ɗ',
  'Ƌ' => 'ƌ',
  'Ǝ' => 'ǝ',
  'Ə' => 'ə',
  'Ɛ' => 'ɛ',
  'Ƒ' => 'ƒ',
  'Ɠ' => 'ɠ',
  'Ɣ' => 'ɣ',
  'Ɩ' => 'ɩ',
  'Ɨ' => 'ɨ',
  'Ƙ' => 'ƙ',
  'Ɯ' => 'ɯ',
  'Ɲ' => 'ɲ',
  'Ɵ' => 'ɵ',
  'Ơ' => 'ơ',
  'Ƣ' => 'ƣ',
  'Ƥ' => 'ƥ',
  'Ʀ' => 'ʀ',
  'Ƨ' => 'ƨ',
  'Ʃ' => 'ʃ',
  'Ƭ' => 'ƭ',
  'Ʈ' => 'ʈ',
  'Ư' => 'ư',
  'Ʊ' => 'ʊ',
  'Ʋ' => 'ʋ',
  'Ƴ' => 'ƴ',
  'Ƶ' => 'ƶ',
  'Ʒ' => 'ʒ',
  'Ƹ' => 'ƹ',
  'Ƽ' => 'ƽ',
  'Ǆ' => 'ǆ',
  'ǅ' => 'ǆ',
  'Ǉ' => 'ǉ',
  'ǈ' => 'ǉ',
  'Ǌ' => 'ǌ',
  'ǋ' => 'ǌ',
  'Ǎ' => 'ǎ',
  'Ǐ' => 'ǐ',
  'Ǒ' => 'ǒ',
  'Ǔ' => 'ǔ',
  'Ǖ' => 'ǖ',
  'Ǘ' => 'ǘ',
  'Ǚ' => 'ǚ',
  'Ǜ' => 'ǜ',
  'Ǟ' => 'ǟ',
  'Ǡ' => 'ǡ',
  'Ǣ' => 'ǣ',
  'Ǥ' => 'ǥ',
  'Ǧ' => 'ǧ',
  'Ǩ' => 'ǩ',
  'Ǫ' => 'ǫ',
  'Ǭ' => 'ǭ',
  'Ǯ' => 'ǯ',
  'Ǳ' => 'ǳ',
  'ǲ' => 'ǳ',
  'Ǵ' => 'ǵ',
  'Ƕ' => 'ƕ',
  'Ƿ' => 'ƿ',
  'Ǹ' => 'ǹ',
  'Ǻ' => 'ǻ',
  'Ǽ' => 'ǽ',
  'Ǿ' => 'ǿ',
  'Ȁ' => 'ȁ',
  'Ȃ' => 'ȃ',
  'Ȅ' => 'ȅ',
  'Ȇ' => 'ȇ',
  'Ȉ' => 'ȉ',
  'Ȋ' => 'ȋ',
  'Ȍ' => 'ȍ',
  'Ȏ' => 'ȏ',
  'Ȑ' => 'ȑ',
  'Ȓ' => 'ȓ',
  'Ȕ' => 'ȕ',
  'Ȗ' => 'ȗ',
  'Ș' => 'ș',
  'Ț' => 'ț',
  'Ȝ' => 'ȝ',
  'Ȟ' => 'ȟ',
  'Ƞ' => 'ƞ',
  'Ȣ' => 'ȣ',
  'Ȥ' => 'ȥ',
  'Ȧ' => 'ȧ',
  'Ȩ' => 'ȩ',
  'Ȫ' => 'ȫ',
  'Ȭ' => 'ȭ',
  'Ȯ' => 'ȯ',
  'Ȱ' => 'ȱ',
  'Ȳ' => 'ȳ',
  'Ⱥ' => 'ⱥ',
  'Ȼ' => 'ȼ',
  'Ƚ' => 'ƚ',
  'Ⱦ' => 'ⱦ',
  'Ɂ' => 'ɂ',
  'Ƀ' => 'ƀ',
  'Ʉ' => 'ʉ',
  'Ʌ' => 'ʌ',
  'Ɇ' => 'ɇ',
  'Ɉ' => 'ɉ',
  'Ɋ' => 'ɋ',
  'Ɍ' => 'ɍ',
  'Ɏ' => 'ɏ',
  'Ͱ' => 'ͱ',
  'Ͳ' => 'ͳ',
  'Ͷ' => 'ͷ',
  'Ϳ' => 'ϳ',
  'Ά' => 'ά',
  'Έ' => 'έ',
  'Ή' => 'ή',
  'Ί' => 'ί',
  'Ό' => 'ό',
  'Ύ' => 'ύ',
  'Ώ' => 'ώ',
  'Α' => 'α',
  'Β' => 'β',
  'Γ' => 'γ',
  'Δ' => 'δ',
  'Ε' => 'ε',
  'Ζ' => 'ζ',
  'Η' => 'η',
  'Θ' => 'θ',
  'Ι' => 'ι',
  'Κ' => 'κ',
  'Λ' => 'λ',
  'Μ' => 'μ',
  'Ν' => 'ν',
  'Ξ' => 'ξ',
  'Ο' => 'ο',
  'Π' => 'π',
  'Ρ' => 'ρ',
  'Σ' => 'σ',
  'Τ' => 'τ',
  'Υ' => 'υ',
  'Φ' => 'φ',
  'Χ' => 'χ',
  'Ψ' => 'ψ',
  'Ω' => 'ω',
  'Ϊ' => 'ϊ',
  'Ϋ' => 'ϋ',
  'Ϗ' => 'ϗ',
  'Ϙ' => 'ϙ',
  'Ϛ' => 'ϛ',
  'Ϝ' => 'ϝ',
  'Ϟ' => 'ϟ',
  'Ϡ' => 'ϡ',
  'Ϣ' => 'ϣ',
  'Ϥ' => 'ϥ',
  'Ϧ' => 'ϧ',
  'Ϩ' => 'ϩ',
  'Ϫ' => 'ϫ',
  'Ϭ' => 'ϭ',
  'Ϯ' => 'ϯ',
  'ϴ' => 'θ',
  'Ϸ' => 'ϸ',
  'Ϲ' => 'ϲ',
  'Ϻ' => 'ϻ',
  'Ͻ' => 'ͻ',
  'Ͼ' => 'ͼ',
  'Ͽ' => 'ͽ',
  'Ѐ' => 'ѐ',
  'Ё' => 'ё',
  'Ђ' => 'ђ',
  'Ѓ' => 'ѓ',
  'Є' => 'є',
  'Ѕ' => 'ѕ',
  'І' => 'і',
  'Ї' => 'ї',
  'Ј' => 'ј',
  'Љ' => 'љ',
  'Њ' => 'њ',
  'Ћ' => 'ћ',
  'Ќ' => 'ќ',
  'Ѝ' => 'ѝ',
  'Ў' => 'ў',
  'Џ' => 'џ',
  'А' => 'а',
  'Б' => 'б',
  'В' => 'в',
  'Г' => 'г',
  'Д' => 'д',
  'Е' => 'е',
  'Ж' => 'ж',
  'З' => 'з',
  'И' => 'и',
  'Й' => 'й',
  'К' => 'к',
  'Л' => 'л',
  'М' => 'м',
  'Н' => 'н',
  'О' => 'о',
  'П' => 'п',
  'Р' => 'р',
  'С' => 'с',
  'Т' => 'т',
  'У' => 'у',
  'Ф' => 'ф',
  'Х' => 'х',
  'Ц' => 'ц',
  'Ч' => 'ч',
  'Ш' => 'ш',
  'Щ' => 'щ',
  'Ъ' => 'ъ',
  'Ы' => 'ы',
  'Ь' => 'ь',
  'Э' => 'э',
  'Ю' => 'ю',
  'Я' => 'я',
  'Ѡ' => 'ѡ',
  'Ѣ' => 'ѣ',
  'Ѥ' => 'ѥ',
  'Ѧ' => 'ѧ',
  'Ѩ' => 'ѩ',
  'Ѫ' => 'ѫ',
  'Ѭ' => 'ѭ',
  'Ѯ' => 'ѯ',
  'Ѱ' => 'ѱ',
  'Ѳ' => 'ѳ',
  'Ѵ' => 'ѵ',
  'Ѷ' => 'ѷ',
  'Ѹ' => 'ѹ',
  'Ѻ' => 'ѻ',
  'Ѽ' => 'ѽ',
  'Ѿ' => 'ѿ',
  'Ҁ' => 'ҁ',
  'Ҋ' => 'ҋ',
  'Ҍ' => 'ҍ',
  'Ҏ' => 'ҏ',
  'Ґ' => 'ґ',
  'Ғ' => 'ғ',
  'Ҕ' => 'ҕ',
  'Җ' => 'җ',
  'Ҙ' => 'ҙ',
  'Қ' => 'қ',
  'Ҝ' => 'ҝ',
  'Ҟ' => 'ҟ',
  'Ҡ' => 'ҡ',
  'Ң' => 'ң',
  'Ҥ' => 'ҥ',
  'Ҧ' => 'ҧ',
  'Ҩ' => 'ҩ',
  'Ҫ' => 'ҫ',
  'Ҭ' => 'ҭ',
  'Ү' => 'ү',
  'Ұ' => 'ұ',
  'Ҳ' => 'ҳ',
  'Ҵ' => 'ҵ',
  'Ҷ' => 'ҷ',
  'Ҹ' => 'ҹ',
  'Һ' => 'һ',
  'Ҽ' => 'ҽ',
  'Ҿ' => 'ҿ',
  'Ӏ' => 'ӏ',
  'Ӂ' => 'ӂ',
  'Ӄ' => 'ӄ',
  'Ӆ' => 'ӆ',
  'Ӈ' => 'ӈ',
  'Ӊ' => 'ӊ',
  'Ӌ' => 'ӌ',
  'Ӎ' => 'ӎ',
  'Ӑ' => 'ӑ',
  'Ӓ' => 'ӓ',
  'Ӕ' => 'ӕ',
  'Ӗ' => 'ӗ',
  'Ә' => 'ә',
  'Ӛ' => 'ӛ',
  'Ӝ' => 'ӝ',
  'Ӟ' => 'ӟ',
  'Ӡ' => 'ӡ',
  'Ӣ' => 'ӣ',
  'Ӥ' => 'ӥ',
  'Ӧ' => 'ӧ',
  'Ө' => 'ө',
  'Ӫ' => 'ӫ',
  'Ӭ' => 'ӭ',
  'Ӯ' => 'ӯ',
  'Ӱ' => 'ӱ',
  'Ӳ' => 'ӳ',
  'Ӵ' => 'ӵ',
  'Ӷ' => 'ӷ',
  'Ӹ' => 'ӹ',
  'Ӻ' => 'ӻ',
  'Ӽ' => 'ӽ',
  'Ӿ' => 'ӿ',
  'Ԁ' => 'ԁ',
  'Ԃ' => 'ԃ',
  'Ԅ' => 'ԅ',
  'Ԇ' => 'ԇ',
  'Ԉ' => 'ԉ',
  'Ԋ' => 'ԋ',
  'Ԍ' => 'ԍ',
  'Ԏ' => 'ԏ',
  'Ԑ' => 'ԑ',
  'Ԓ' => 'ԓ',
  'Ԕ' => 'ԕ',
  'Ԗ' => 'ԗ',
  'Ԙ' => 'ԙ',
  'Ԛ' => 'ԛ',
  'Ԝ' => 'ԝ',
  'Ԟ' => 'ԟ',
  'Ԡ' => 'ԡ',
  'Ԣ' => 'ԣ',
  'Ԥ' => 'ԥ',
  'Ԧ' => 'ԧ',
  'Ԩ' => 'ԩ',
  'Ԫ' => 'ԫ',
  'Ԭ' => 'ԭ',
  'Ԯ' => 'ԯ',
  'Ա' => 'ա',
  'Բ' => 'բ',
  'Գ' => 'գ',
  'Դ' => 'դ',
  'Ե' => 'ե',
  'Զ' => 'զ',
  'Է' => 'է',
  'Ը' => 'ը',
  'Թ' => 'թ',
  'Ժ' => 'ժ',
  'Ի' => 'ի',
  'Լ' => 'լ',
  'Խ' => 'խ',
  'Ծ' => 'ծ',
  'Կ' => 'կ',
  'Հ' => 'հ',
  'Ձ' => 'ձ',
  'Ղ' => 'ղ',
  'Ճ' => 'ճ',
  'Մ' => 'մ',
  'Յ' => 'յ',
  'Ն' => 'ն',
  'Շ' => 'շ',
  'Ո' => 'ո',
  'Չ' => 'չ',
  'Պ' => 'պ',
  'Ջ' => 'ջ',
  'Ռ' => 'ռ',
  'Ս' => 'ս',
  'Վ' => 'վ',
  'Տ' => 'տ',
  'Ր' => 'ր',
  'Ց' => 'ց',
  'Ւ' => 'ւ',
  'Փ' => 'փ',
  'Ք' => 'ք',
  'Օ' => 'օ',
  'Ֆ' => 'ֆ',
  'Ⴀ' => 'ⴀ',
  'Ⴁ' => 'ⴁ',
  'Ⴂ' => 'ⴂ',
  'Ⴃ' => 'ⴃ',
  'Ⴄ' => 'ⴄ',
  'Ⴅ' => 'ⴅ',
  'Ⴆ' => 'ⴆ',
  'Ⴇ' => 'ⴇ',
  'Ⴈ' => 'ⴈ',
  'Ⴉ' => 'ⴉ',
  'Ⴊ' => 'ⴊ',
  'Ⴋ' => 'ⴋ',
  'Ⴌ' => 'ⴌ',
  'Ⴍ' => 'ⴍ',
  'Ⴎ' => 'ⴎ',
  'Ⴏ' => 'ⴏ',
  'Ⴐ' => 'ⴐ',
  'Ⴑ' => 'ⴑ',
  'Ⴒ' => 'ⴒ',
  'Ⴓ' => 'ⴓ',
  'Ⴔ' => 'ⴔ',
  'Ⴕ' => 'ⴕ',
  'Ⴖ' => 'ⴖ',
  'Ⴗ' => 'ⴗ',
  'Ⴘ' => 'ⴘ',
  'Ⴙ' => 'ⴙ',
  'Ⴚ' => 'ⴚ',
  'Ⴛ' => 'ⴛ',
  'Ⴜ' => 'ⴜ',
  'Ⴝ' => 'ⴝ',
  'Ⴞ' => 'ⴞ',
  'Ⴟ' => 'ⴟ',
  'Ⴠ' => 'ⴠ',
  'Ⴡ' => 'ⴡ',
  'Ⴢ' => 'ⴢ',
  'Ⴣ' => 'ⴣ',
  'Ⴤ' => 'ⴤ',
  'Ⴥ' => 'ⴥ',
  'Ⴧ' => 'ⴧ',
  'Ⴭ' => 'ⴭ',
  'Ꭰ' => 'ꭰ',
  'Ꭱ' => 'ꭱ',
  'Ꭲ' => 'ꭲ',
  'Ꭳ' => 'ꭳ',
  'Ꭴ' => 'ꭴ',
  'Ꭵ' => 'ꭵ',
  'Ꭶ' => 'ꭶ',
  'Ꭷ' => 'ꭷ',
  'Ꭸ' => 'ꭸ',
  'Ꭹ' => 'ꭹ',
  'Ꭺ' => 'ꭺ',
  'Ꭻ' => 'ꭻ',
  'Ꭼ' => 'ꭼ',
  'Ꭽ' => 'ꭽ',
  'Ꭾ' => 'ꭾ',
  'Ꭿ' => 'ꭿ',
  'Ꮀ' => 'ꮀ',
  'Ꮁ' => 'ꮁ',
  'Ꮂ' => 'ꮂ',
  'Ꮃ' => 'ꮃ',
  'Ꮄ' => 'ꮄ',
  'Ꮅ' => 'ꮅ',
  'Ꮆ' => 'ꮆ',
  'Ꮇ' => 'ꮇ',
  'Ꮈ' => 'ꮈ',
  'Ꮉ' => 'ꮉ',
  'Ꮊ' => 'ꮊ',
  'Ꮋ' => 'ꮋ',
  'Ꮌ' => 'ꮌ',
  'Ꮍ' => 'ꮍ',
  'Ꮎ' => 'ꮎ',
  'Ꮏ' => 'ꮏ',
  'Ꮐ' => 'ꮐ',
  'Ꮑ' => 'ꮑ',
  'Ꮒ' => 'ꮒ',
  'Ꮓ' => 'ꮓ',
  'Ꮔ' => 'ꮔ',
  'Ꮕ' => 'ꮕ',
  'Ꮖ' => 'ꮖ',
  'Ꮗ' => 'ꮗ',
  'Ꮘ' => 'ꮘ',
  'Ꮙ' => 'ꮙ',
  'Ꮚ' => 'ꮚ',
  'Ꮛ' => 'ꮛ',
  'Ꮜ' => 'ꮜ',
  'Ꮝ' => 'ꮝ',
  'Ꮞ' => 'ꮞ',
  'Ꮟ' => 'ꮟ',
  'Ꮠ' => 'ꮠ',
  'Ꮡ' => 'ꮡ',
  'Ꮢ' => 'ꮢ',
  'Ꮣ' => 'ꮣ',
  'Ꮤ' => 'ꮤ',
  'Ꮥ' => 'ꮥ',
  'Ꮦ' => 'ꮦ',
  'Ꮧ' => 'ꮧ',
  'Ꮨ' => 'ꮨ',
  'Ꮩ' => 'ꮩ',
  'Ꮪ' => 'ꮪ',
  'Ꮫ' => 'ꮫ',
  'Ꮬ' => 'ꮬ',
  'Ꮭ' => 'ꮭ',
  'Ꮮ' => 'ꮮ',
  'Ꮯ' => 'ꮯ',
  'Ꮰ' => 'ꮰ',
  'Ꮱ' => 'ꮱ',
  'Ꮲ' => 'ꮲ',
  'Ꮳ' => 'ꮳ',
  'Ꮴ' => 'ꮴ',
  'Ꮵ' => 'ꮵ',
  'Ꮶ' => 'ꮶ',
  'Ꮷ' => 'ꮷ',
  'Ꮸ' => 'ꮸ',
  'Ꮹ' => 'ꮹ',
  'Ꮺ' => 'ꮺ',
  'Ꮻ' => 'ꮻ',
  'Ꮼ' => 'ꮼ',
  'Ꮽ' => 'ꮽ',
  'Ꮾ' => 'ꮾ',
  'Ꮿ' => 'ꮿ',
  'Ᏸ' => 'ᏸ',
  'Ᏹ' => 'ᏹ',
  'Ᏺ' => 'ᏺ',
  'Ᏻ' => 'ᏻ',
  'Ᏼ' => 'ᏼ',
  'Ᏽ' => 'ᏽ',
  'Ა' => 'ა',
  'Ბ' => 'ბ',
  'Გ' => 'გ',
  'Დ' => 'დ',
  'Ე' => 'ე',
  'Ვ' => 'ვ',
  'Ზ' => 'ზ',
  'Თ' => 'თ',
  'Ი' => 'ი',
  'Კ' => 'კ',
  'Ლ' => 'ლ',
  'Მ' => 'მ',
  'Ნ' => 'ნ',
  'Ო' => 'ო',
  'Პ' => 'პ',
  'Ჟ' => 'ჟ',
  'Რ' => 'რ',
  'Ს' => 'ს',
  'Ტ' => 'ტ',
  'Უ' => 'უ',
  'Ფ' => 'ფ',
  'Ქ' => 'ქ',
  'Ღ' => 'ღ',
  'Ყ' => 'ყ',
  'Შ' => 'შ',
  'Ჩ' => 'ჩ',
  'Ც' => 'ც',
  'Ძ' => 'ძ',
  'Წ' => 'წ',
  'Ჭ' => 'ჭ',
  'Ხ' => 'ხ',
  'Ჯ' => 'ჯ',
  'Ჰ' => 'ჰ',
  'Ჱ' => 'ჱ',
  'Ჲ' => 'ჲ',
  'Ჳ' => 'ჳ',
  'Ჴ' => 'ჴ',
  'Ჵ' => 'ჵ',
  'Ჶ' => 'ჶ',
  'Ჷ' => 'ჷ',
  'Ჸ' => 'ჸ',
  'Ჹ' => 'ჹ',
  'Ჺ' => 'ჺ',
  'Ჽ' => 'ჽ',
  'Ჾ' => 'ჾ',
  'Ჿ' => 'ჿ',
  'Ḁ' => 'ḁ',
  'Ḃ' => 'ḃ',
  'Ḅ' => 'ḅ',
  'Ḇ' => 'ḇ',
  'Ḉ' => 'ḉ',
  'Ḋ' => 'ḋ',
  'Ḍ' => 'ḍ',
  'Ḏ' => 'ḏ',
  'Ḑ' => 'ḑ',
  'Ḓ' => 'ḓ',
  'Ḕ' => 'ḕ',
  'Ḗ' => 'ḗ',
  'Ḙ' => 'ḙ',
  'Ḛ' => 'ḛ',
  'Ḝ' => 'ḝ',
  'Ḟ' => 'ḟ',
  'Ḡ' => 'ḡ',
  'Ḣ' => 'ḣ',
  'Ḥ' => 'ḥ',
  'Ḧ' => 'ḧ',
  'Ḩ' => 'ḩ',
  'Ḫ' => 'ḫ',
  'Ḭ' => 'ḭ',
  'Ḯ' => 'ḯ',
  'Ḱ' => 'ḱ',
  'Ḳ' => 'ḳ',
  'Ḵ' => 'ḵ',
  'Ḷ' => 'ḷ',
  'Ḹ' => 'ḹ',
  'Ḻ' => 'ḻ',
  'Ḽ' => 'ḽ',
  'Ḿ' => 'ḿ',
  'Ṁ' => 'ṁ',
  'Ṃ' => 'ṃ',
  'Ṅ' => 'ṅ',
  'Ṇ' => 'ṇ',
  'Ṉ' => 'ṉ',
  'Ṋ' => 'ṋ',
  'Ṍ' => 'ṍ',
  'Ṏ' => 'ṏ',
  'Ṑ' => 'ṑ',
  'Ṓ' => 'ṓ',
  'Ṕ' => 'ṕ',
  'Ṗ' => 'ṗ',
  'Ṙ' => 'ṙ',
  'Ṛ' => 'ṛ',
  'Ṝ' => 'ṝ',
  'Ṟ' => 'ṟ',
  'Ṡ' => 'ṡ',
  'Ṣ' => 'ṣ',
  'Ṥ' => 'ṥ',
  'Ṧ' => 'ṧ',
  'Ṩ' => 'ṩ',
  'Ṫ' => 'ṫ',
  'Ṭ' => 'ṭ',
  'Ṯ' => 'ṯ',
  'Ṱ' => 'ṱ',
  'Ṳ' => 'ṳ',
  'Ṵ' => 'ṵ',
  'Ṷ' => 'ṷ',
  'Ṹ' => 'ṹ',
  'Ṻ' => 'ṻ',
  'Ṽ' => 'ṽ',
  'Ṿ' => 'ṿ',
  'Ẁ' => 'ẁ',
  'Ẃ' => 'ẃ',
  'Ẅ' => 'ẅ',
  'Ẇ' => 'ẇ',
  'Ẉ' => 'ẉ',
  'Ẋ' => 'ẋ',
  'Ẍ' => 'ẍ',
  'Ẏ' => 'ẏ',
  'Ẑ' => 'ẑ',
  'Ẓ' => 'ẓ',
  'Ẕ' => 'ẕ',
  'ẞ' => 'ß',
  'Ạ' => 'ạ',
  'Ả' => 'ả',
  'Ấ' => 'ấ',
  'Ầ' => 'ầ',
  'Ẩ' => 'ẩ',
  'Ẫ' => 'ẫ',
  'Ậ' => 'ậ',
  'Ắ' => 'ắ',
  'Ằ' => 'ằ',
  'Ẳ' => 'ẳ',
  'Ẵ' => 'ẵ',
  'Ặ' => 'ặ',
  'Ẹ' => 'ẹ',
  'Ẻ' => 'ẻ',
  'Ẽ' => 'ẽ',
  'Ế' => 'ế',
  'Ề' => 'ề',
  'Ể' => 'ể',
  'Ễ' => 'ễ',
  'Ệ' => 'ệ',
  'Ỉ' => 'ỉ',
  'Ị' => 'ị',
  'Ọ' => 'ọ',
  'Ỏ' => 'ỏ',
  'Ố' => 'ố',
  'Ồ' => 'ồ',
  'Ổ' => 'ổ',
  'Ỗ' => 'ỗ',
  'Ộ' => 'ộ',
  'Ớ' => 'ớ',
  'Ờ' => 'ờ',
  'Ở' => 'ở',
  'Ỡ' => 'ỡ',
  'Ợ' => 'ợ',
  'Ụ' => 'ụ',
  'Ủ' => 'ủ',
  'Ứ' => 'ứ',
  'Ừ' => 'ừ',
  'Ử' => 'ử',
  'Ữ' => 'ữ',
  'Ự' => 'ự',
  'Ỳ' => 'ỳ',
  'Ỵ' => 'ỵ',
  'Ỷ' => 'ỷ',
  'Ỹ' => 'ỹ',
  'Ỻ' => 'ỻ',
  'Ỽ' => 'ỽ',
  'Ỿ' => 'ỿ',
  'Ἀ' => 'ἀ',
  'Ἁ' => 'ἁ',
  'Ἂ' => 'ἂ',
  'Ἃ' => 'ἃ',
  'Ἄ' => 'ἄ',
  'Ἅ' => 'ἅ',
  'Ἆ' => 'ἆ',
  'Ἇ' => 'ἇ',
  'Ἐ' => 'ἐ',
  'Ἑ' => 'ἑ',
  'Ἒ' => 'ἒ',
  'Ἓ' => 'ἓ',
  'Ἔ' => 'ἔ',
  'Ἕ' => 'ἕ',
  'Ἠ' => 'ἠ',
  'Ἡ' => 'ἡ',
  'Ἢ' => 'ἢ',
  'Ἣ' => 'ἣ',
  'Ἤ' => 'ἤ',
  'Ἥ' => 'ἥ',
  'Ἦ' => 'ἦ',
  'Ἧ' => 'ἧ',
  'Ἰ' => 'ἰ',
  'Ἱ' => 'ἱ',
  'Ἲ' => 'ἲ',
  'Ἳ' => 'ἳ',
  'Ἴ' => 'ἴ',
  'Ἵ' => 'ἵ',
  'Ἶ' => 'ἶ',
  'Ἷ' => 'ἷ',
  'Ὀ' => 'ὀ',
  'Ὁ' => 'ὁ',
  'Ὂ' => 'ὂ',
  'Ὃ' => 'ὃ',
  'Ὄ' => 'ὄ',
  'Ὅ' => 'ὅ',
  'Ὑ' => 'ὑ',
  'Ὓ' => 'ὓ',
  'Ὕ' => 'ὕ',
  'Ὗ' => 'ὗ',
  'Ὠ' => 'ὠ',
  'Ὡ' => 'ὡ',
  'Ὢ' => 'ὢ',
  'Ὣ' => 'ὣ',
  'Ὤ' => 'ὤ',
  'Ὥ' => 'ὥ',
  'Ὦ' => 'ὦ',
  'Ὧ' => 'ὧ',
  'ᾈ' => 'ᾀ',
  'ᾉ' => 'ᾁ',
  'ᾊ' => 'ᾂ',
  'ᾋ' => 'ᾃ',
  'ᾌ' => 'ᾄ',
  'ᾍ' => 'ᾅ',
  'ᾎ' => 'ᾆ',
  'ᾏ' => 'ᾇ',
  'ᾘ' => 'ᾐ',
  'ᾙ' => 'ᾑ',
  'ᾚ' => 'ᾒ',
  'ᾛ' => 'ᾓ',
  'ᾜ' => 'ᾔ',
  'ᾝ' => 'ᾕ',
  'ᾞ' => 'ᾖ',
  'ᾟ' => 'ᾗ',
  'ᾨ' => 'ᾠ',
  'ᾩ' => 'ᾡ',
  'ᾪ' => 'ᾢ',
  'ᾫ' => 'ᾣ',
  'ᾬ' => 'ᾤ',
  'ᾭ' => 'ᾥ',
  'ᾮ' => 'ᾦ',
  'ᾯ' => 'ᾧ',
  'Ᾰ' => 'ᾰ',
  'Ᾱ' => 'ᾱ',
  'Ὰ' => 'ὰ',
  'Ά' => 'ά',
  'ᾼ' => 'ᾳ',
  'Ὲ' => 'ὲ',
  'Έ' => 'έ',
  'Ὴ' => 'ὴ',
  'Ή' => 'ή',
  'ῌ' => 'ῃ',
  'Ῐ' => 'ῐ',
  'Ῑ' => 'ῑ',
  'Ὶ' => 'ὶ',
  'Ί' => 'ί',
  'Ῠ' => 'ῠ',
  'Ῡ' => 'ῡ',
  'Ὺ' => 'ὺ',
  'Ύ' => 'ύ',
  'Ῥ' => 'ῥ',
  'Ὸ' => 'ὸ',
  'Ό' => 'ό',
  'Ὼ' => 'ὼ',
  'Ώ' => 'ώ',
  'ῼ' => 'ῳ',
  'Ω' => 'ω',
  'K' => 'k',
  'Å' => 'å',
  'Ⅎ' => 'ⅎ',
  'Ⅰ' => 'ⅰ',
  'Ⅱ' => 'ⅱ',
  'Ⅲ' => 'ⅲ',
  'Ⅳ' => 'ⅳ',
  'Ⅴ' => 'ⅴ',
  'Ⅵ' => 'ⅵ',
  'Ⅶ' => 'ⅶ',
  'Ⅷ' => 'ⅷ',
  'Ⅸ' => 'ⅸ',
  'Ⅹ' => 'ⅹ',
  'Ⅺ' => 'ⅺ',
  'Ⅻ' => 'ⅻ',
  'Ⅼ' => 'ⅼ',
  'Ⅽ' => 'ⅽ',
  'Ⅾ' => 'ⅾ',
  'Ⅿ' => 'ⅿ',
  'Ↄ' => 'ↄ',
  'Ⓐ' => 'ⓐ',
  'Ⓑ' => 'ⓑ',
  'Ⓒ' => 'ⓒ',
  'Ⓓ' => 'ⓓ',
  'Ⓔ' => 'ⓔ',
  'Ⓕ' => 'ⓕ',
  'Ⓖ' => 'ⓖ',
  'Ⓗ' => 'ⓗ',
  'Ⓘ' => 'ⓘ',
  'Ⓙ' => 'ⓙ',
  'Ⓚ' => 'ⓚ',
  'Ⓛ' => 'ⓛ',
  'Ⓜ' => 'ⓜ',
  'Ⓝ' => 'ⓝ',
  'Ⓞ' => 'ⓞ',
  'Ⓟ' => 'ⓟ',
  'Ⓠ' => 'ⓠ',
  'Ⓡ' => 'ⓡ',
  'Ⓢ' => 'ⓢ',
  'Ⓣ' => 'ⓣ',
  'Ⓤ' => 'ⓤ',
  'Ⓥ' => 'ⓥ',
  'Ⓦ' => 'ⓦ',
  'Ⓧ' => 'ⓧ',
  'Ⓨ' => 'ⓨ',
  'Ⓩ' => 'ⓩ',
  'Ⰰ' => 'ⰰ',
  'Ⰱ' => 'ⰱ',
  'Ⰲ' => 'ⰲ',
  'Ⰳ' => 'ⰳ',
  'Ⰴ' => 'ⰴ',
  'Ⰵ' => 'ⰵ',
  'Ⰶ' => 'ⰶ',
  'Ⰷ' => 'ⰷ',
  'Ⰸ' => 'ⰸ',
  'Ⰹ' => 'ⰹ',
  'Ⰺ' => 'ⰺ',
  'Ⰻ' => 'ⰻ',
  'Ⰼ' => 'ⰼ',
  'Ⰽ' => 'ⰽ',
  'Ⰾ' => 'ⰾ',
  'Ⰿ' => 'ⰿ',
  'Ⱀ' => 'ⱀ',
  'Ⱁ' => 'ⱁ',
  'Ⱂ' => 'ⱂ',
  'Ⱃ' => 'ⱃ',
  'Ⱄ' => 'ⱄ',
  'Ⱅ' => 'ⱅ',
  'Ⱆ' => 'ⱆ',
  'Ⱇ' => 'ⱇ',
  'Ⱈ' => 'ⱈ',
  'Ⱉ' => 'ⱉ',
  'Ⱊ' => 'ⱊ',
  'Ⱋ' => 'ⱋ',
  'Ⱌ' => 'ⱌ',
  'Ⱍ' => 'ⱍ',
  'Ⱎ' => 'ⱎ',
  'Ⱏ' => 'ⱏ',
  'Ⱐ' => 'ⱐ',
  'Ⱑ' => 'ⱑ',
  'Ⱒ' => 'ⱒ',
  'Ⱓ' => 'ⱓ',
  'Ⱔ' => 'ⱔ',
  'Ⱕ' => 'ⱕ',
  'Ⱖ' => 'ⱖ',
  'Ⱗ' => 'ⱗ',
  'Ⱘ' => 'ⱘ',
  'Ⱙ' => 'ⱙ',
  'Ⱚ' => 'ⱚ',
  'Ⱛ' => 'ⱛ',
  'Ⱜ' => 'ⱜ',
  'Ⱝ' => 'ⱝ',
  'Ⱞ' => 'ⱞ',
  'Ⱡ' => 'ⱡ',
  'Ɫ' => 'ɫ',
  'Ᵽ' => 'ᵽ',
  'Ɽ' => 'ɽ',
  'Ⱨ' => 'ⱨ',
  'Ⱪ' => 'ⱪ',
  'Ⱬ' => 'ⱬ',
  'Ɑ' => 'ɑ',
  'Ɱ' => 'ɱ',
  'Ɐ' => 'ɐ',
  'Ɒ' => 'ɒ',
  'Ⱳ' => 'ⱳ',
  'Ⱶ' => 'ⱶ',
  'Ȿ' => 'ȿ',
  'Ɀ' => 'ɀ',
  'Ⲁ' => 'ⲁ',
  'Ⲃ' => 'ⲃ',
  'Ⲅ' => 'ⲅ',
  'Ⲇ' => 'ⲇ',
  'Ⲉ' => 'ⲉ',
  'Ⲋ' => 'ⲋ',
  'Ⲍ' => 'ⲍ',
  'Ⲏ' => 'ⲏ',
  'Ⲑ' => 'ⲑ',
  'Ⲓ' => 'ⲓ',
  'Ⲕ' => 'ⲕ',
  'Ⲗ' => 'ⲗ',
  'Ⲙ' => 'ⲙ',
  'Ⲛ' => 'ⲛ',
  'Ⲝ' => 'ⲝ',
  'Ⲟ' => 'ⲟ',
  'Ⲡ' => 'ⲡ',
  'Ⲣ' => 'ⲣ',
  'Ⲥ' => 'ⲥ',
  'Ⲧ' => 'ⲧ',
  'Ⲩ' => 'ⲩ',
  'Ⲫ' => 'ⲫ',
  'Ⲭ' => 'ⲭ',
  'Ⲯ' => 'ⲯ',
  'Ⲱ' => 'ⲱ',
  'Ⲳ' => 'ⲳ',
  'Ⲵ' => 'ⲵ',
  'Ⲷ' => 'ⲷ',
  'Ⲹ' => 'ⲹ',
  'Ⲻ' => 'ⲻ',
  'Ⲽ' => 'ⲽ',
  'Ⲿ' => 'ⲿ',
  'Ⳁ' => 'ⳁ',
  'Ⳃ' => 'ⳃ',
  'Ⳅ' => 'ⳅ',
  'Ⳇ' => 'ⳇ',
  'Ⳉ' => 'ⳉ',
  'Ⳋ' => 'ⳋ',
  'Ⳍ' => 'ⳍ',
  'Ⳏ' => 'ⳏ',
  'Ⳑ' => 'ⳑ',
  'Ⳓ' => 'ⳓ',
  'Ⳕ' => 'ⳕ',
  'Ⳗ' => 'ⳗ',
  'Ⳙ' => 'ⳙ',
  'Ⳛ' => 'ⳛ',
  'Ⳝ' => 'ⳝ',
  'Ⳟ' => 'ⳟ',
  'Ⳡ' => 'ⳡ',
  'Ⳣ' => 'ⳣ',
  'Ⳬ' => 'ⳬ',
  'Ⳮ' => 'ⳮ',
  'Ⳳ' => 'ⳳ',
  'Ꙁ' => 'ꙁ',
  'Ꙃ' => 'ꙃ',
  'Ꙅ' => 'ꙅ',
  'Ꙇ' => 'ꙇ',
  'Ꙉ' => 'ꙉ',
  'Ꙋ' => 'ꙋ',
  'Ꙍ' => 'ꙍ',
  'Ꙏ' => 'ꙏ',
  'Ꙑ' => 'ꙑ',
  'Ꙓ' => 'ꙓ',
  'Ꙕ' => 'ꙕ',
  'Ꙗ' => 'ꙗ',
  'Ꙙ' => 'ꙙ',
  'Ꙛ' => 'ꙛ',
  'Ꙝ' => 'ꙝ',
  'Ꙟ' => 'ꙟ',
  'Ꙡ' => 'ꙡ',
  'Ꙣ' => 'ꙣ',
  'Ꙥ' => 'ꙥ',
  'Ꙧ' => 'ꙧ',
  'Ꙩ' => 'ꙩ',
  'Ꙫ' => 'ꙫ',
  'Ꙭ' => 'ꙭ',
  'Ꚁ' => 'ꚁ',
  'Ꚃ' => 'ꚃ',
  'Ꚅ' => 'ꚅ',
  'Ꚇ' => 'ꚇ',
  'Ꚉ' => 'ꚉ',
  'Ꚋ' => 'ꚋ',
  'Ꚍ' => 'ꚍ',
  'Ꚏ' => 'ꚏ',
  'Ꚑ' => 'ꚑ',
  'Ꚓ' => 'ꚓ',
  'Ꚕ' => 'ꚕ',
  'Ꚗ' => 'ꚗ',
  'Ꚙ' => 'ꚙ',
  'Ꚛ' => 'ꚛ',
  'Ꜣ' => 'ꜣ',
  'Ꜥ' => 'ꜥ',
  'Ꜧ' => 'ꜧ',
  'Ꜩ' => 'ꜩ',
  'Ꜫ' => 'ꜫ',
  'Ꜭ' => 'ꜭ',
  'Ꜯ' => 'ꜯ',
  'Ꜳ' => 'ꜳ',
  'Ꜵ' => 'ꜵ',
  'Ꜷ' => 'ꜷ',
  'Ꜹ' => 'ꜹ',
  'Ꜻ' => 'ꜻ',
  'Ꜽ' => 'ꜽ',
  'Ꜿ' => 'ꜿ',
  'Ꝁ' => 'ꝁ',
  'Ꝃ' => 'ꝃ',
  'Ꝅ' => 'ꝅ',
  'Ꝇ' => 'ꝇ',
  'Ꝉ' => 'ꝉ',
  'Ꝋ' => 'ꝋ',
  'Ꝍ' => 'ꝍ',
  'Ꝏ' => 'ꝏ',
  'Ꝑ' => 'ꝑ',
  'Ꝓ' => 'ꝓ',
  'Ꝕ' => 'ꝕ',
  'Ꝗ' => 'ꝗ',
  'Ꝙ' => 'ꝙ',
  'Ꝛ' => 'ꝛ',
  'Ꝝ' => 'ꝝ',
  'Ꝟ' => 'ꝟ',
  'Ꝡ' => 'ꝡ',
  'Ꝣ' => 'ꝣ',
  'Ꝥ' => 'ꝥ',
  'Ꝧ' => 'ꝧ',
  'Ꝩ' => 'ꝩ',
  'Ꝫ' => 'ꝫ',
  'Ꝭ' => 'ꝭ',
  'Ꝯ' => 'ꝯ',
  'Ꝺ' => 'ꝺ',
  'Ꝼ' => 'ꝼ',
  'Ᵹ' => 'ᵹ',
  'Ꝿ' => 'ꝿ',
  'Ꞁ' => 'ꞁ',
  'Ꞃ' => 'ꞃ',
  'Ꞅ' => 'ꞅ',
  'Ꞇ' => 'ꞇ',
  'Ꞌ' => 'ꞌ',
  'Ɥ' => 'ɥ',
  'Ꞑ' => 'ꞑ',
  'Ꞓ' => 'ꞓ',
  'Ꞗ' => 'ꞗ',
  'Ꞙ' => 'ꞙ',
  'Ꞛ' => 'ꞛ',
  'Ꞝ' => 'ꞝ',
  'Ꞟ' => 'ꞟ',
  'Ꞡ' => 'ꞡ',
  'Ꞣ' => 'ꞣ',
  'Ꞥ' => 'ꞥ',
  'Ꞧ' => 'ꞧ',
  'Ꞩ' => 'ꞩ',
  'Ɦ' => 'ɦ',
  'Ɜ' => 'ɜ',
  'Ɡ' => 'ɡ',
  'Ɬ' => 'ɬ',
  'Ɪ' => 'ɪ',
  'Ʞ' => 'ʞ',
  'Ʇ' => 'ʇ',
  'Ʝ' => 'ʝ',
  'Ꭓ' => 'ꭓ',
  'Ꞵ' => 'ꞵ',
  'Ꞷ' => 'ꞷ',
  'Ꞹ' => 'ꞹ',
  'Ꞻ' => 'ꞻ',
  'Ꞽ' => 'ꞽ',
  'Ꞿ' => 'ꞿ',
  'Ꟃ' => 'ꟃ',
  'Ꞔ' => 'ꞔ',
  'Ʂ' => 'ʂ',
  'Ᶎ' => 'ᶎ',
  'Ꟈ' => 'ꟈ',
  'Ꟊ' => 'ꟊ',
  'Ꟶ' => 'ꟶ',
  'Ａ' => 'ａ',
  'Ｂ' => 'ｂ',
  'Ｃ' => 'ｃ',
  'Ｄ' => 'ｄ',
  'Ｅ' => 'ｅ',
  'Ｆ' => 'ｆ',
  'Ｇ' => 'ｇ',
  'Ｈ' => 'ｈ',
  'Ｉ' => 'ｉ',
  'Ｊ' => 'ｊ',
  'Ｋ' => 'ｋ',
  'Ｌ' => 'ｌ',
  'Ｍ' => 'ｍ',
  'Ｎ' => 'ｎ',
  'Ｏ' => 'ｏ',
  'Ｐ' => 'ｐ',
  'Ｑ' => 'ｑ',
  'Ｒ' => 'ｒ',
  'Ｓ' => 'ｓ',
  'Ｔ' => 'ｔ',
  'Ｕ' => 'ｕ',
  'Ｖ' => 'ｖ',
  'Ｗ' => 'ｗ',
  'Ｘ' => 'ｘ',
  'Ｙ' => 'ｙ',
  'Ｚ' => 'ｚ',
  '𐐀' => '𐐨',
  '𐐁' => '𐐩',
  '𐐂' => '𐐪',
  '𐐃' => '𐐫',
  '𐐄' => '𐐬',
  '𐐅' => '𐐭',
  '𐐆' => '𐐮',
  '𐐇' => '𐐯',
  '𐐈' => '𐐰',
  '𐐉' => '𐐱',
  '𐐊' => '𐐲',
  '𐐋' => '𐐳',
  '𐐌' => '𐐴',
  '𐐍' => '𐐵',
  '𐐎' => '𐐶',
  '𐐏' => '𐐷',
  '𐐐' => '𐐸',
  '𐐑' => '𐐹',
  '𐐒' => '𐐺',
  '𐐓' => '𐐻',
  '𐐔' => '𐐼',
  '𐐕' => '𐐽',
  '𐐖' => '𐐾',
  '𐐗' => '𐐿',
  '𐐘' => '𐑀',
  '𐐙' => '𐑁',
  '𐐚' => '𐑂',
  '𐐛' => '𐑃',
  '𐐜' => '𐑄',
  '𐐝' => '𐑅',
  '𐐞' => '𐑆',
  '𐐟' => '𐑇',
  '𐐠' => '𐑈',
  '𐐡' => '𐑉',
  '𐐢' => '𐑊',
  '𐐣' => '𐑋',
  '𐐤' => '𐑌',
  '𐐥' => '𐑍',
  '𐐦' => '𐑎',
  '𐐧' => '𐑏',
  '𐒰' => '𐓘',
  '𐒱' => '𐓙',
  '𐒲' => '𐓚',
  '𐒳' => '𐓛',
  '𐒴' => '𐓜',
  '𐒵' => '𐓝',
  '𐒶' => '𐓞',
  '𐒷' => '𐓟',
  '𐒸' => '𐓠',
  '𐒹' => '𐓡',
  '𐒺' => '𐓢',
  '𐒻' => '𐓣',
  '𐒼' => '𐓤',
  '𐒽' => '𐓥',
  '𐒾' => '𐓦',
  '𐒿' => '𐓧',
  '𐓀' => '𐓨',
  '𐓁' => '𐓩',
  '𐓂' => '𐓪',
  '𐓃' => '𐓫',
  '𐓄' => '𐓬',
  '𐓅' => '𐓭',
  '𐓆' => '𐓮',
  '𐓇' => '𐓯',
  '𐓈' => '𐓰',
  '𐓉' => '𐓱',
  '𐓊' => '𐓲',
  '𐓋' => '𐓳',
  '𐓌' => '𐓴',
  '𐓍' => '𐓵',
  '𐓎' => '𐓶',
  '𐓏' => '𐓷',
  '𐓐' => '𐓸',
  '𐓑' => '𐓹',
  '𐓒' => '𐓺',
  '𐓓' => '𐓻',
  '𐲀' => '𐳀',
  '𐲁' => '𐳁',
  '𐲂' => '𐳂',
  '𐲃' => '𐳃',
  '𐲄' => '𐳄',
  '𐲅' => '𐳅',
  '𐲆' => '𐳆',
  '𐲇' => '𐳇',
  '𐲈' => '𐳈',
  '𐲉' => '𐳉',
  '𐲊' => '𐳊',
  '𐲋' => '𐳋',
  '𐲌' => '𐳌',
  '𐲍' => '𐳍',
  '𐲎' => '𐳎',
  '𐲏' => '𐳏',
  '𐲐' => '𐳐',
  '𐲑' => '𐳑',
  '𐲒' => '𐳒',
  '𐲓' => '𐳓',
  '𐲔' => '𐳔',
  '𐲕' => '𐳕',
  '𐲖' => '𐳖',
  '𐲗' => '𐳗',
  '𐲘' => '𐳘',
  '𐲙' => '𐳙',
  '𐲚' => '𐳚',
  '𐲛' => '𐳛',
  '𐲜' => '𐳜',
  '𐲝' => '𐳝',
  '𐲞' => '𐳞',
  '𐲟' => '𐳟',
  '𐲠' => '𐳠',
  '𐲡' => '𐳡',
  '𐲢' => '𐳢',
  '𐲣' => '𐳣',
  '𐲤' => '𐳤',
  '𐲥' => '𐳥',
  '𐲦' => '𐳦',
  '𐲧' => '𐳧',
  '𐲨' => '𐳨',
  '𐲩' => '𐳩',
  '𐲪' => '𐳪',
  '𐲫' => '𐳫',
  '𐲬' => '𐳬',
  '𐲭' => '𐳭',
  '𐲮' => '𐳮',
  '𐲯' => '𐳯',
  '𐲰' => '𐳰',
  '𐲱' => '𐳱',
  '𐲲' => '𐳲',
  '𑢠' => '𑣀',
  '𑢡' => '𑣁',
  '𑢢' => '𑣂',
  '𑢣' => '𑣃',
  '𑢤' => '𑣄',
  '𑢥' => '𑣅',
  '𑢦' => '𑣆',
  '𑢧' => '𑣇',
  '𑢨' => '𑣈',
  '𑢩' => '𑣉',
  '𑢪' => '𑣊',
  '𑢫' => '𑣋',
  '𑢬' => '𑣌',
  '𑢭' => '𑣍',
  '𑢮' => '𑣎',
  '𑢯' => '𑣏',
  '𑢰' => '𑣐',
  '𑢱' => '𑣑',
  '𑢲' => '𑣒',
  '𑢳' => '𑣓',
  '𑢴' => '𑣔',
  '𑢵' => '𑣕',
  '𑢶' => '𑣖',
  '𑢷' => '𑣗',
  '𑢸' => '𑣘',
  '𑢹' => '𑣙',
  '𑢺' => '𑣚',
  '𑢻' => '𑣛',
  '𑢼' => '𑣜',
  '𑢽' => '𑣝',
  '𑢾' => '𑣞',
  '𑢿' => '𑣟',
  '𖹀' => '𖹠',
  '𖹁' => '𖹡',
  '𖹂' => '𖹢',
  '𖹃' => '𖹣',
  '𖹄' => '𖹤',
  '𖹅' => '𖹥',
  '𖹆' => '𖹦',
  '𖹇' => '𖹧',
  '𖹈' => '𖹨',
  '𖹉' => '𖹩',
  '𖹊' => '𖹪',
  '𖹋' => '𖹫',
  '𖹌' => '𖹬',
  '𖹍' => '𖹭',
  '𖹎' => '𖹮',
  '𖹏' => '𖹯',
  '𖹐' => '𖹰',
  '𖹑' => '𖹱',
  '𖹒' => '𖹲',
  '𖹓' => '𖹳',
  '𖹔' => '𖹴',
  '𖹕' => '𖹵',
  '𖹖' => '𖹶',
  '𖹗' => '𖹷',
  '𖹘' => '𖹸',
  '𖹙' => '𖹹',
  '𖹚' => '𖹺',
  '𖹛' => '𖹻',
  '𖹜' => '𖹼',
  '𖹝' => '𖹽',
  '𖹞' => '𖹾',
  '𖹟' => '𖹿',
  '𞤀' => '𞤢',
  '𞤁' => '𞤣',
  '𞤂' => '𞤤',
  '𞤃' => '𞤥',
  '𞤄' => '𞤦',
  '𞤅' => '𞤧',
  '𞤆' => '𞤨',
  '𞤇' => '𞤩',
  '𞤈' => '𞤪',
  '𞤉' => '𞤫',
  '𞤊' => '𞤬',
  '𞤋' => '𞤭',
  '𞤌' => '𞤮',
  '𞤍' => '𞤯',
  '𞤎' => '𞤰',
  '𞤏' => '𞤱',
  '𞤐' => '𞤲',
  '𞤑' => '𞤳',
  '𞤒' => '𞤴',
  '𞤓' => '𞤵',
  '𞤔' => '𞤶',
  '𞤕' => '𞤷',
  '𞤖' => '𞤸',
  '𞤗' => '𞤹',
  '𞤘' => '𞤺',
  '𞤙' => '𞤻',
  '𞤚' => '𞤼',
  '𞤛' => '𞤽',
  '𞤜' => '𞤾',
  '𞤝' => '𞤿',
  '𞤞' => '𞥀',
  '𞤟' => '𞥁',
  '𞤠' => '𞥂',
  '𞤡' => '𞥃',
);
<?php

return array (
  'a' => 'A',
  'b' => 'B',
  'c' => 'C',
  'd' => 'D',
  'e' => 'E',
  'f' => 'F',
  'g' => 'G',
  'h' => 'H',
  'i' => 'I',
  'j' => 'J',
  'k' => 'K',
  'l' => 'L',
  'm' => 'M',
  'n' => 'N',
  'o' => 'O',
  'p' => 'P',
  'q' => 'Q',
  'r' => 'R',
  's' => 'S',
  't' => 'T',
  'u' => 'U',
  'v' => 'V',
  'w' => 'W',
  'x' => 'X',
  'y' => 'Y',
  'z' => 'Z',
  'µ' => 'Μ',
  'à' => 'À',
  'á' => 'Á',
  'â' => 'Â',
  'ã' => 'Ã',
  'ä' => 'Ä',
  'å' => 'Å',
  'æ' => 'Æ',
  'ç' => 'Ç',
  'è' => 'È',
  'é' => 'É',
  'ê' => 'Ê',
  'ë' => 'Ë',
  'ì' => 'Ì',
  'í' => 'Í',
  'î' => 'Î',
  'ï' => 'Ï',
  'ð' => 'Ð',
  'ñ' => 'Ñ',
  'ò' => 'Ò',
  'ó' => 'Ó',
  'ô' => 'Ô',
  'õ' => 'Õ',
  'ö' => 'Ö',
  'ø' => 'Ø',
  'ù' => 'Ù',
  'ú' => 'Ú',
  'û' => 'Û',
  'ü' => 'Ü',
  'ý' => 'Ý',
  'þ' => 'Þ',
  'ÿ' => 'Ÿ',
  'ā' => 'Ā',
  'ă' => 'Ă',
  'ą' => 'Ą',
  'ć' => 'Ć',
  'ĉ' => 'Ĉ',
  'ċ' => 'Ċ',
  'č' => 'Č',
  'ď' => 'Ď',
  'đ' => 'Đ',
  'ē' => 'Ē',
  'ĕ' => 'Ĕ',
  'ė' => 'Ė',
  'ę' => 'Ę',
  'ě' => 'Ě',
  'ĝ' => 'Ĝ',
  'ğ' => 'Ğ',
  'ġ' => 'Ġ',
  'ģ' => 'Ģ',
  'ĥ' => 'Ĥ',
  'ħ' => 'Ħ',
  'ĩ' => 'Ĩ',
  'ī' => 'Ī',
  'ĭ' => 'Ĭ',
  'į' => 'Į',
  'ı' => 'I',
  'ĳ' => 'Ĳ',
  'ĵ' => 'Ĵ',
  'ķ' => 'Ķ',
  'ĺ' => 'Ĺ',
  'ļ' => 'Ļ',
  'ľ' => 'Ľ',
  'ŀ' => 'Ŀ',
  'ł' => 'Ł',
  'ń' => 'Ń',
  'ņ' => 'Ņ',
  'ň' => 'Ň',
  'ŋ' => 'Ŋ',
  'ō' => 'Ō',
  'ŏ' => 'Ŏ',
  'ő' => 'Ő',
  'œ' => 'Œ',
  'ŕ' => 'Ŕ',
  'ŗ' => 'Ŗ',
  'ř' => 'Ř',
  'ś' => 'Ś',
  'ŝ' => 'Ŝ',
  'ş' => 'Ş',
  'š' => 'Š',
  'ţ' => 'Ţ',
  'ť' => 'Ť',
  'ŧ' => 'Ŧ',
  'ũ' => 'Ũ',
  'ū' => 'Ū',
  'ŭ' => 'Ŭ',
  'ů' => 'Ů',
  'ű' => 'Ű',
  'ų' => 'Ų',
  'ŵ' => 'Ŵ',
  'ŷ' => 'Ŷ',
  'ź' => 'Ź',
  'ż' => 'Ż',
  'ž' => 'Ž',
  'ſ' => 'S',
  'ƀ' => 'Ƀ',
  'ƃ' => 'Ƃ',
  'ƅ' => 'Ƅ',
  'ƈ' => 'Ƈ',
  'ƌ' => 'Ƌ',
  'ƒ' => 'Ƒ',
  'ƕ' => 'Ƕ',
  'ƙ' => 'Ƙ',
  'ƚ' => 'Ƚ',
  'ƞ' => 'Ƞ',
  'ơ' => 'Ơ',
  'ƣ' => 'Ƣ',
  'ƥ' => 'Ƥ',
  'ƨ' => 'Ƨ',
  'ƭ' => 'Ƭ',
  'ư' => 'Ư',
  'ƴ' => 'Ƴ',
  'ƶ' => 'Ƶ',
  'ƹ' => 'Ƹ',
  'ƽ' => 'Ƽ',
  'ƿ' => 'Ƿ',
  'ǅ' => 'Ǆ',
  'ǆ' => 'Ǆ',
  'ǈ' => 'Ǉ',
  'ǉ' => 'Ǉ',
  'ǋ' => 'Ǌ',
  'ǌ' => 'Ǌ',
  'ǎ' => 'Ǎ',
  'ǐ' => 'Ǐ',
  'ǒ' => 'Ǒ',
  'ǔ' => 'Ǔ',
  'ǖ' => 'Ǖ',
  'ǘ' => 'Ǘ',
  'ǚ' => 'Ǚ',
  'ǜ' => 'Ǜ',
  'ǝ' => 'Ǝ',
  'ǟ' => 'Ǟ',
  'ǡ' => 'Ǡ',
  'ǣ' => 'Ǣ',
  'ǥ' => 'Ǥ',
  'ǧ' => 'Ǧ',
  'ǩ' => 'Ǩ',
  'ǫ' => 'Ǫ',
  'ǭ' => 'Ǭ',
  'ǯ' => 'Ǯ',
  'ǲ' => 'Ǳ',
  'ǳ' => 'Ǳ',
  'ǵ' => 'Ǵ',
  'ǹ' => 'Ǹ',
  'ǻ' => 'Ǻ',
  'ǽ' => 'Ǽ',
  'ǿ' => 'Ǿ',
  'ȁ' => 'Ȁ',
  'ȃ' => 'Ȃ',
  'ȅ' => 'Ȅ',
  'ȇ' => 'Ȇ',
  'ȉ' => 'Ȉ',
  'ȋ' => 'Ȋ',
  'ȍ' => 'Ȍ',
  'ȏ' => 'Ȏ',
  'ȑ' => 'Ȑ',
  'ȓ' => 'Ȓ',
  'ȕ' => 'Ȕ',
  'ȗ' => 'Ȗ',
  'ș' => 'Ș',
  'ț' => 'Ț',
  'ȝ' => 'Ȝ',
  'ȟ' => 'Ȟ',
  'ȣ' => 'Ȣ',
  'ȥ' => 'Ȥ',
  'ȧ' => 'Ȧ',
  'ȩ' => 'Ȩ',
  'ȫ' => 'Ȫ',
  'ȭ' => 'Ȭ',
  'ȯ' => 'Ȯ',
  'ȱ' => 'Ȱ',
  'ȳ' => 'Ȳ',
  'ȼ' => 'Ȼ',
  'ȿ' => 'Ȿ',
  'ɀ' => 'Ɀ',
  'ɂ' => 'Ɂ',
  'ɇ' => 'Ɇ',
  'ɉ' => 'Ɉ',
  'ɋ' => 'Ɋ',
  'ɍ' => 'Ɍ',
  'ɏ' => 'Ɏ',
  'ɐ' => 'Ɐ',
  'ɑ' => 'Ɑ',
  'ɒ' => 'Ɒ',
  'ɓ' => 'Ɓ',
  'ɔ' => 'Ɔ',
  'ɖ' => 'Ɖ',
  'ɗ' => 'Ɗ',
  'ə' => 'Ə',
  'ɛ' => 'Ɛ',
  'ɜ' => 'Ɜ',
  'ɠ' => 'Ɠ',
  'ɡ' => 'Ɡ',
  'ɣ' => 'Ɣ',
  'ɥ' => 'Ɥ',
  'ɦ' => 'Ɦ',
  'ɨ' => 'Ɨ',
  'ɩ' => 'Ɩ',
  'ɪ' => 'Ɪ',
  'ɫ' => 'Ɫ',
  'ɬ' => 'Ɬ',
  'ɯ' => 'Ɯ',
  'ɱ' => 'Ɱ',
  'ɲ' => 'Ɲ',
  'ɵ' => 'Ɵ',
  'ɽ' => 'Ɽ',
  'ʀ' => 'Ʀ',
  'ʂ' => 'Ʂ',
  'ʃ' => 'Ʃ',
  'ʇ' => 'Ʇ',
  'ʈ' => 'Ʈ',
  'ʉ' => 'Ʉ',
  'ʊ' => 'Ʊ',
  'ʋ' => 'Ʋ',
  'ʌ' => 'Ʌ',
  'ʒ' => 'Ʒ',
  'ʝ' => 'Ʝ',
  'ʞ' => 'Ʞ',
  'ͅ' => 'Ι',
  'ͱ' => 'Ͱ',
  'ͳ' => 'Ͳ',
  'ͷ' => 'Ͷ',
  'ͻ' => 'Ͻ',
  'ͼ' => 'Ͼ',
  'ͽ' => 'Ͽ',
  'ά' => 'Ά',
  'έ' => 'Έ',
  'ή' => 'Ή',
  'ί' => 'Ί',
  'α' => 'Α',
  'β' => 'Β',
  'γ' => 'Γ',
  'δ' => 'Δ',
  'ε' => 'Ε',
  'ζ' => 'Ζ',
  'η' => 'Η',
  'θ' => 'Θ',
  'ι' => 'Ι',
  'κ' => 'Κ',
  'λ' => 'Λ',
  'μ' => 'Μ',
  'ν' => 'Ν',
  'ξ' => 'Ξ',
  'ο' => 'Ο',
  'π' => 'Π',
  'ρ' => 'Ρ',
  'ς' => 'Σ',
  'σ' => 'Σ',
  'τ' => 'Τ',
  'υ' => 'Υ',
  'φ' => 'Φ',
  'χ' => 'Χ',
  'ψ' => 'Ψ',
  'ω' => 'Ω',
  'ϊ' => 'Ϊ',
  'ϋ' => 'Ϋ',
  'ό' => 'Ό',
  'ύ' => 'Ύ',
  'ώ' => 'Ώ',
  'ϐ' => 'Β',
  'ϑ' => 'Θ',
  'ϕ' => 'Φ',
  'ϖ' => 'Π',
  'ϗ' => 'Ϗ',
  'ϙ' => 'Ϙ',
  'ϛ' => 'Ϛ',
  'ϝ' => 'Ϝ',
  'ϟ' => 'Ϟ',
  'ϡ' => 'Ϡ',
  'ϣ' => 'Ϣ',
  'ϥ' => 'Ϥ',
  'ϧ' => 'Ϧ',
  'ϩ' => 'Ϩ',
  'ϫ' => 'Ϫ',
  'ϭ' => 'Ϭ',
  'ϯ' => 'Ϯ',
  'ϰ' => 'Κ',
  'ϱ' => 'Ρ',
  'ϲ' => 'Ϲ',
  'ϳ' => 'Ϳ',
  'ϵ' => 'Ε',
  'ϸ' => 'Ϸ',
  'ϻ' => 'Ϻ',
  'а' => 'А',
  'б' => 'Б',
  'в' => 'В',
  'г' => 'Г',
  'д' => 'Д',
  'е' => 'Е',
  'ж' => 'Ж',
  'з' => 'З',
  'и' => 'И',
  'й' => 'Й',
  'к' => 'К',
  'л' => 'Л',
  'м' => 'М',
  'н' => 'Н',
  'о' => 'О',
  'п' => 'П',
  'р' => 'Р',
  'с' => 'С',
  'т' => 'Т',
  'у' => 'У',
  'ф' => 'Ф',
  'х' => 'Х',
  'ц' => 'Ц',
  'ч' => 'Ч',
  'ш' => 'Ш',
  'щ' => 'Щ',
  'ъ' => 'Ъ',
  'ы' => 'Ы',
  'ь' => 'Ь',
  'э' => 'Э',
  'ю' => 'Ю',
  'я' => 'Я',
  'ѐ' => 'Ѐ',
  'ё' => 'Ё',
  'ђ' => 'Ђ',
  'ѓ' => 'Ѓ',
  'є' => 'Є',
  'ѕ' => 'Ѕ',
  'і' => 'І',
  'ї' => 'Ї',
  'ј' => 'Ј',
  'љ' => 'Љ',
  'њ' => 'Њ',
  'ћ' => 'Ћ',
  'ќ' => 'Ќ',
  'ѝ' => 'Ѝ',
  'ў' => 'Ў',
  'џ' => 'Џ',
  'ѡ' => 'Ѡ',
  'ѣ' => 'Ѣ',
  'ѥ' => 'Ѥ',
  'ѧ' => 'Ѧ',
  'ѩ' => 'Ѩ',
  'ѫ' => 'Ѫ',
  'ѭ' => 'Ѭ',
  'ѯ' => 'Ѯ',
  'ѱ' => 'Ѱ',
  'ѳ' => 'Ѳ',
  'ѵ' => 'Ѵ',
  'ѷ' => 'Ѷ',
  'ѹ' => 'Ѹ',
  'ѻ' => 'Ѻ',
  'ѽ' => 'Ѽ',
  'ѿ' => 'Ѿ',
  'ҁ' => 'Ҁ',
  'ҋ' => 'Ҋ',
  'ҍ' => 'Ҍ',
  'ҏ' => 'Ҏ',
  'ґ' => 'Ґ',
  'ғ' => 'Ғ',
  'ҕ' => 'Ҕ',
  'җ' => 'Җ',
  'ҙ' => 'Ҙ',
  'қ' => 'Қ',
  'ҝ' => 'Ҝ',
  'ҟ' => 'Ҟ',
  'ҡ' => 'Ҡ',
  'ң' => 'Ң',
  'ҥ' => 'Ҥ',
  'ҧ' => 'Ҧ',
  'ҩ' => 'Ҩ',
  'ҫ' => 'Ҫ',
  'ҭ' => 'Ҭ',
  'ү' => 'Ү',
  'ұ' => 'Ұ',
  'ҳ' => 'Ҳ',
  'ҵ' => 'Ҵ',
  'ҷ' => 'Ҷ',
  'ҹ' => 'Ҹ',
  'һ' => 'Һ',
  'ҽ' => 'Ҽ',
  'ҿ' => 'Ҿ',
  'ӂ' => 'Ӂ',
  'ӄ' => 'Ӄ',
  'ӆ' => 'Ӆ',
  'ӈ' => 'Ӈ',
  'ӊ' => 'Ӊ',
  'ӌ' => 'Ӌ',
  'ӎ' => 'Ӎ',
  'ӏ' => 'Ӏ',
  'ӑ' => 'Ӑ',
  'ӓ' => 'Ӓ',
  'ӕ' => 'Ӕ',
  'ӗ' => 'Ӗ',
  'ә' => 'Ә',
  'ӛ' => 'Ӛ',
  'ӝ' => 'Ӝ',
  'ӟ' => 'Ӟ',
  'ӡ' => 'Ӡ',
  'ӣ' => 'Ӣ',
  'ӥ' => 'Ӥ',
  'ӧ' => 'Ӧ',
  'ө' => 'Ө',
  'ӫ' => 'Ӫ',
  'ӭ' => 'Ӭ',
  'ӯ' => 'Ӯ',
  'ӱ' => 'Ӱ',
  'ӳ' => 'Ӳ',
  'ӵ' => 'Ӵ',
  'ӷ' => 'Ӷ',
  'ӹ' => 'Ӹ',
  'ӻ' => 'Ӻ',
  'ӽ' => 'Ӽ',
  'ӿ' => 'Ӿ',
  'ԁ' => 'Ԁ',
  'ԃ' => 'Ԃ',
  'ԅ' => 'Ԅ',
  'ԇ' => 'Ԇ',
  'ԉ' => 'Ԉ',
  'ԋ' => 'Ԋ',
  'ԍ' => 'Ԍ',
  'ԏ' => 'Ԏ',
  'ԑ' => 'Ԑ',
  'ԓ' => 'Ԓ',
  'ԕ' => 'Ԕ',
  'ԗ' => 'Ԗ',
  'ԙ' => 'Ԙ',
  'ԛ' => 'Ԛ',
  'ԝ' => 'Ԝ',
  'ԟ' => 'Ԟ',
  'ԡ' => 'Ԡ',
  'ԣ' => 'Ԣ',
  'ԥ' => 'Ԥ',
  'ԧ' => 'Ԧ',
  'ԩ' => 'Ԩ',
  'ԫ' => 'Ԫ',
  'ԭ' => 'Ԭ',
  'ԯ' => 'Ԯ',
  'ա' => 'Ա',
  'բ' => 'Բ',
  'գ' => 'Գ',
  'դ' => 'Դ',
  'ե' => 'Ե',
  'զ' => 'Զ',
  'է' => 'Է',
  'ը' => 'Ը',
  'թ' => 'Թ',
  'ժ' => 'Ժ',
  'ի' => 'Ի',
  'լ' => 'Լ',
  'խ' => 'Խ',
  'ծ' => 'Ծ',
  'կ' => 'Կ',
  'հ' => 'Հ',
  'ձ' => 'Ձ',
  'ղ' => 'Ղ',
  'ճ' => 'Ճ',
  'մ' => 'Մ',
  'յ' => 'Յ',
  'ն' => 'Ն',
  'շ' => 'Շ',
  'ո' => 'Ո',
  'չ' => 'Չ',
  'պ' => 'Պ',
  'ջ' => 'Ջ',
  'ռ' => 'Ռ',
  'ս' => 'Ս',
  'վ' => 'Վ',
  'տ' => 'Տ',
  'ր' => 'Ր',
  'ց' => 'Ց',
  'ւ' => 'Ւ',
  'փ' => 'Փ',
  'ք' => 'Ք',
  'օ' => 'Օ',
  'ֆ' => 'Ֆ',
  'ა' => 'Ა',
  'ბ' => 'Ბ',
  'გ' => 'Გ',
  'დ' => 'Დ',
  'ე' => 'Ე',
  'ვ' => 'Ვ',
  'ზ' => 'Ზ',
  'თ' => 'Თ',
  'ი' => 'Ი',
  'კ' => 'Კ',
  'ლ' => 'Ლ',
  'მ' => 'Მ',
  'ნ' => 'Ნ',
  'ო' => 'Ო',
  'პ' => 'Პ',
  'ჟ' => 'Ჟ',
  'რ' => 'Რ',
  'ს' => 'Ს',
  'ტ' => 'Ტ',
  'უ' => 'Უ',
  'ფ' => 'Ფ',
  'ქ' => 'Ქ',
  'ღ' => 'Ღ',
  'ყ' => 'Ყ',
  'შ' => 'Შ',
  'ჩ' => 'Ჩ',
  'ც' => 'Ც',
  'ძ' => 'Ძ',
  'წ' => 'Წ',
  'ჭ' => 'Ჭ',
  'ხ' => 'Ხ',
  'ჯ' => 'Ჯ',
  'ჰ' => 'Ჰ',
  'ჱ' => 'Ჱ',
  'ჲ' => 'Ჲ',
  'ჳ' => 'Ჳ',
  'ჴ' => 'Ჴ',
  'ჵ' => 'Ჵ',
  'ჶ' => 'Ჶ',
  'ჷ' => 'Ჷ',
  'ჸ' => 'Ჸ',
  'ჹ' => 'Ჹ',
  'ჺ' => 'Ჺ',
  'ჽ' => 'Ჽ',
  'ჾ' => 'Ჾ',
  'ჿ' => 'Ჿ',
  'ᏸ' => 'Ᏸ',
  'ᏹ' => 'Ᏹ',
  'ᏺ' => 'Ᏺ',
  'ᏻ' => 'Ᏻ',
  'ᏼ' => 'Ᏼ',
  'ᏽ' => 'Ᏽ',
  'ᲀ' => 'В',
  'ᲁ' => 'Д',
  'ᲂ' => 'О',
  'ᲃ' => 'С',
  'ᲄ' => 'Т',
  'ᲅ' => 'Т',
  'ᲆ' => 'Ъ',
  'ᲇ' => 'Ѣ',
  'ᲈ' => 'Ꙋ',
  'ᵹ' => 'Ᵹ',
  'ᵽ' => 'Ᵽ',
  'ᶎ' => 'Ᶎ',
  'ḁ' => 'Ḁ',
  'ḃ' => 'Ḃ',
  'ḅ' => 'Ḅ',
  'ḇ' => 'Ḇ',
  'ḉ' => 'Ḉ',
  'ḋ' => 'Ḋ',
  'ḍ' => 'Ḍ',
  'ḏ' => 'Ḏ',
  'ḑ' => 'Ḑ',
  'ḓ' => 'Ḓ',
  'ḕ' => 'Ḕ',
  'ḗ' => 'Ḗ',
  'ḙ' => 'Ḙ',
  'ḛ' => 'Ḛ',
  'ḝ' => 'Ḝ',
  'ḟ' => 'Ḟ',
  'ḡ' => 'Ḡ',
  'ḣ' => 'Ḣ',
  'ḥ' => 'Ḥ',
  'ḧ' => 'Ḧ',
  'ḩ' => 'Ḩ',
  'ḫ' => 'Ḫ',
  'ḭ' => 'Ḭ',
  'ḯ' => 'Ḯ',
  'ḱ' => 'Ḱ',
  'ḳ' => 'Ḳ',
  'ḵ' => 'Ḵ',
  'ḷ' => 'Ḷ',
  'ḹ' => 'Ḹ',
  'ḻ' => 'Ḻ',
  'ḽ' => 'Ḽ',
  'ḿ' => 'Ḿ',
  'ṁ' => 'Ṁ',
  'ṃ' => 'Ṃ',
  'ṅ' => 'Ṅ',
  'ṇ' => 'Ṇ',
  'ṉ' => 'Ṉ',
  'ṋ' => 'Ṋ',
  'ṍ' => 'Ṍ',
  'ṏ' => 'Ṏ',
  'ṑ' => 'Ṑ',
  'ṓ' => 'Ṓ',
  'ṕ' => 'Ṕ',
  'ṗ' => 'Ṗ',
  'ṙ' => 'Ṙ',
  'ṛ' => 'Ṛ',
  'ṝ' => 'Ṝ',
  'ṟ' => 'Ṟ',
  'ṡ' => 'Ṡ',
  'ṣ' => 'Ṣ',
  'ṥ' => 'Ṥ',
  'ṧ' => 'Ṧ',
  'ṩ' => 'Ṩ',
  'ṫ' => 'Ṫ',
  'ṭ' => 'Ṭ',
  'ṯ' => 'Ṯ',
  'ṱ' => 'Ṱ',
  'ṳ' => 'Ṳ',
  'ṵ' => 'Ṵ',
  'ṷ' => 'Ṷ',
  'ṹ' => 'Ṹ',
  'ṻ' => 'Ṻ',
  'ṽ' => 'Ṽ',
  'ṿ' => 'Ṿ',
  'ẁ' => 'Ẁ',
  'ẃ' => 'Ẃ',
  'ẅ' => 'Ẅ',
  'ẇ' => 'Ẇ',
  'ẉ' => 'Ẉ',
  'ẋ' => 'Ẋ',
  'ẍ' => 'Ẍ',
  'ẏ' => 'Ẏ',
  'ẑ' => 'Ẑ',
  'ẓ' => 'Ẓ',
  'ẕ' => 'Ẕ',
  'ẛ' => 'Ṡ',
  'ạ' => 'Ạ',
  'ả' => 'Ả',
  'ấ' => 'Ấ',
  'ầ' => 'Ầ',
  'ẩ' => 'Ẩ',
  'ẫ' => 'Ẫ',
  'ậ' => 'Ậ',
  'ắ' => 'Ắ',
  'ằ' => 'Ằ',
  'ẳ' => 'Ẳ',
  'ẵ' => 'Ẵ',
  'ặ' => 'Ặ',
  'ẹ' => 'Ẹ',
  'ẻ' => 'Ẻ',
  'ẽ' => 'Ẽ',
  'ế' => 'Ế',
  'ề' => 'Ề',
  'ể' => 'Ể',
  'ễ' => 'Ễ',
  'ệ' => 'Ệ',
  'ỉ' => 'Ỉ',
  'ị' => 'Ị',
  'ọ' => 'Ọ',
  'ỏ' => 'Ỏ',
  'ố' => 'Ố',
  'ồ' => 'Ồ',
  'ổ' => 'Ổ',
  'ỗ' => 'Ỗ',
  'ộ' => 'Ộ',
  'ớ' => 'Ớ',
  'ờ' => 'Ờ',
  'ở' => 'Ở',
  'ỡ' => 'Ỡ',
  'ợ' => 'Ợ',
  'ụ' => 'Ụ',
  'ủ' => 'Ủ',
  'ứ' => 'Ứ',
  'ừ' => 'Ừ',
  'ử' => 'Ử',
  'ữ' => 'Ữ',
  'ự' => 'Ự',
  'ỳ' => 'Ỳ',
  'ỵ' => 'Ỵ',
  'ỷ' => 'Ỷ',
  'ỹ' => 'Ỹ',
  'ỻ' => 'Ỻ',
  'ỽ' => 'Ỽ',
  'ỿ' => 'Ỿ',
  'ἀ' => 'Ἀ',
  'ἁ' => 'Ἁ',
  'ἂ' => 'Ἂ',
  'ἃ' => 'Ἃ',
  'ἄ' => 'Ἄ',
  'ἅ' => 'Ἅ',
  'ἆ' => 'Ἆ',
  'ἇ' => 'Ἇ',
  'ἐ' => 'Ἐ',
  'ἑ' => 'Ἑ',
  'ἒ' => 'Ἒ',
  'ἓ' => 'Ἓ',
  'ἔ' => 'Ἔ',
  'ἕ' => 'Ἕ',
  'ἠ' => 'Ἠ',
  'ἡ' => 'Ἡ',
  'ἢ' => 'Ἢ',
  'ἣ' => 'Ἣ',
  'ἤ' => 'Ἤ',
  'ἥ' => 'Ἥ',
  'ἦ' => 'Ἦ',
  'ἧ' => 'Ἧ',
  'ἰ' => 'Ἰ',
  'ἱ' => 'Ἱ',
  'ἲ' => 'Ἲ',
  'ἳ' => 'Ἳ',
  'ἴ' => 'Ἴ',
  'ἵ' => 'Ἵ',
  'ἶ' => 'Ἶ',
  'ἷ' => 'Ἷ',
  'ὀ' => 'Ὀ',
  'ὁ' => 'Ὁ',
  'ὂ' => 'Ὂ',
  'ὃ' => 'Ὃ',
  'ὄ' => 'Ὄ',
  'ὅ' => 'Ὅ',
  'ὑ' => 'Ὑ',
  'ὓ' => 'Ὓ',
  'ὕ' => 'Ὕ',
  'ὗ' => 'Ὗ',
  'ὠ' => 'Ὠ',
  'ὡ' => 'Ὡ',
  'ὢ' => 'Ὢ',
  'ὣ' => 'Ὣ',
  'ὤ' => 'Ὤ',
  'ὥ' => 'Ὥ',
  'ὦ' => 'Ὦ',
  'ὧ' => 'Ὧ',
  'ὰ' => 'Ὰ',
  'ά' => 'Ά',
  'ὲ' => 'Ὲ',
  'έ' => 'Έ',
  'ὴ' => 'Ὴ',
  'ή' => 'Ή',
  'ὶ' => 'Ὶ',
  'ί' => 'Ί',
  'ὸ' => 'Ὸ',
  'ό' => 'Ό',
  'ὺ' => 'Ὺ',
  'ύ' => 'Ύ',
  'ὼ' => 'Ὼ',
  'ώ' => 'Ώ',
  'ᾀ' => 'ἈΙ',
  'ᾁ' => 'ἉΙ',
  'ᾂ' => 'ἊΙ',
  'ᾃ' => 'ἋΙ',
  'ᾄ' => 'ἌΙ',
  'ᾅ' => 'ἍΙ',
  'ᾆ' => 'ἎΙ',
  'ᾇ' => 'ἏΙ',
  'ᾐ' => 'ἨΙ',
  'ᾑ' => 'ἩΙ',
  'ᾒ' => 'ἪΙ',
  'ᾓ' => 'ἫΙ',
  'ᾔ' => 'ἬΙ',
  'ᾕ' => 'ἭΙ',
  'ᾖ' => 'ἮΙ',
  'ᾗ' => 'ἯΙ',
  'ᾠ' => 'ὨΙ',
  'ᾡ' => 'ὩΙ',
  'ᾢ' => 'ὪΙ',
  'ᾣ' => 'ὫΙ',
  'ᾤ' => 'ὬΙ',
  'ᾥ' => 'ὭΙ',
  'ᾦ' => 'ὮΙ',
  'ᾧ' => 'ὯΙ',
  'ᾰ' => 'Ᾰ',
  'ᾱ' => 'Ᾱ',
  'ᾳ' => 'ΑΙ',
  'ι' => 'Ι',
  'ῃ' => 'ΗΙ',
  'ῐ' => 'Ῐ',
  'ῑ' => 'Ῑ',
  'ῠ' => 'Ῠ',
  'ῡ' => 'Ῡ',
  'ῥ' => 'Ῥ',
  'ῳ' => 'ΩΙ',
  'ⅎ' => 'Ⅎ',
  'ⅰ' => 'Ⅰ',
  'ⅱ' => 'Ⅱ',
  'ⅲ' => 'Ⅲ',
  'ⅳ' => 'Ⅳ',
  'ⅴ' => 'Ⅴ',
  'ⅵ' => 'Ⅵ',
  'ⅶ' => 'Ⅶ',
  'ⅷ' => 'Ⅷ',
  'ⅸ' => 'Ⅸ',
  'ⅹ' => 'Ⅹ',
  'ⅺ' => 'Ⅺ',
  'ⅻ' => 'Ⅻ',
  'ⅼ' => 'Ⅼ',
  'ⅽ' => 'Ⅽ',
  'ⅾ' => 'Ⅾ',
  'ⅿ' => 'Ⅿ',
  'ↄ' => 'Ↄ',
  'ⓐ' => 'Ⓐ',
  'ⓑ' => 'Ⓑ',
  'ⓒ' => 'Ⓒ',
  'ⓓ' => 'Ⓓ',
  'ⓔ' => 'Ⓔ',
  'ⓕ' => 'Ⓕ',
  'ⓖ' => 'Ⓖ',
  'ⓗ' => 'Ⓗ',
  'ⓘ' => 'Ⓘ',
  'ⓙ' => 'Ⓙ',
  'ⓚ' => 'Ⓚ',
  'ⓛ' => 'Ⓛ',
  'ⓜ' => 'Ⓜ',
  'ⓝ' => 'Ⓝ',
  'ⓞ' => 'Ⓞ',
  'ⓟ' => 'Ⓟ',
  'ⓠ' => 'Ⓠ',
  'ⓡ' => 'Ⓡ',
  'ⓢ' => 'Ⓢ',
  'ⓣ' => 'Ⓣ',
  'ⓤ' => 'Ⓤ',
  'ⓥ' => 'Ⓥ',
  'ⓦ' => 'Ⓦ',
  'ⓧ' => 'Ⓧ',
  'ⓨ' => 'Ⓨ',
  'ⓩ' => 'Ⓩ',
  'ⰰ' => 'Ⰰ',
  'ⰱ' => 'Ⰱ',
  'ⰲ' => 'Ⰲ',
  'ⰳ' => 'Ⰳ',
  'ⰴ' => 'Ⰴ',
  'ⰵ' => 'Ⰵ',
  'ⰶ' => 'Ⰶ',
  'ⰷ' => 'Ⰷ',
  'ⰸ' => 'Ⰸ',
  'ⰹ' => 'Ⰹ',
  'ⰺ' => 'Ⰺ',
  'ⰻ' => 'Ⰻ',
  'ⰼ' => 'Ⰼ',
  'ⰽ' => 'Ⰽ',
  'ⰾ' => 'Ⰾ',
  'ⰿ' => 'Ⰿ',
  'ⱀ' => 'Ⱀ',
  'ⱁ' => 'Ⱁ',
  'ⱂ' => 'Ⱂ',
  'ⱃ' => 'Ⱃ',
  'ⱄ' => 'Ⱄ',
  'ⱅ' => 'Ⱅ',
  'ⱆ' => 'Ⱆ',
  'ⱇ' => 'Ⱇ',
  'ⱈ' => 'Ⱈ',
  'ⱉ' => 'Ⱉ',
  'ⱊ' => 'Ⱊ',
  'ⱋ' => 'Ⱋ',
  'ⱌ' => 'Ⱌ',
  'ⱍ' => 'Ⱍ',
  'ⱎ' => 'Ⱎ',
  'ⱏ' => 'Ⱏ',
  'ⱐ' => 'Ⱐ',
  'ⱑ' => 'Ⱑ',
  'ⱒ' => 'Ⱒ',
  'ⱓ' => 'Ⱓ',
  'ⱔ' => 'Ⱔ',
  'ⱕ' => 'Ⱕ',
  'ⱖ' => 'Ⱖ',
  'ⱗ' => 'Ⱗ',
  'ⱘ' => 'Ⱘ',
  'ⱙ' => 'Ⱙ',
  'ⱚ' => 'Ⱚ',
  'ⱛ' => 'Ⱛ',
  'ⱜ' => 'Ⱜ',
  'ⱝ' => 'Ⱝ',
  'ⱞ' => 'Ⱞ',
  'ⱡ' => 'Ⱡ',
  'ⱥ' => 'Ⱥ',
  'ⱦ' => 'Ⱦ',
  'ⱨ' => 'Ⱨ',
  'ⱪ' => 'Ⱪ',
  'ⱬ' => 'Ⱬ',
  'ⱳ' => 'Ⱳ',
  'ⱶ' => 'Ⱶ',
  'ⲁ' => 'Ⲁ',
  'ⲃ' => 'Ⲃ',
  'ⲅ' => 'Ⲅ',
  'ⲇ' => 'Ⲇ',
  'ⲉ' => 'Ⲉ',
  'ⲋ' => 'Ⲋ',
  'ⲍ' => 'Ⲍ',
  'ⲏ' => 'Ⲏ',
  'ⲑ' => 'Ⲑ',
  'ⲓ' => 'Ⲓ',
  'ⲕ' => 'Ⲕ',
  'ⲗ' => 'Ⲗ',
  'ⲙ' => 'Ⲙ',
  'ⲛ' => 'Ⲛ',
  'ⲝ' => 'Ⲝ',
  'ⲟ' => 'Ⲟ',
  'ⲡ' => 'Ⲡ',
  'ⲣ' => 'Ⲣ',
  'ⲥ' => 'Ⲥ',
  'ⲧ' => 'Ⲧ',
  'ⲩ' => 'Ⲩ',
  'ⲫ' => 'Ⲫ',
  'ⲭ' => 'Ⲭ',
  'ⲯ' => 'Ⲯ',
  'ⲱ' => 'Ⲱ',
  'ⲳ' => 'Ⲳ',
  'ⲵ' => 'Ⲵ',
  'ⲷ' => 'Ⲷ',
  'ⲹ' => 'Ⲹ',
  'ⲻ' => 'Ⲻ',
  'ⲽ' => 'Ⲽ',
  'ⲿ' => 'Ⲿ',
  'ⳁ' => 'Ⳁ',
  'ⳃ' => 'Ⳃ',
  'ⳅ' => 'Ⳅ',
  'ⳇ' => 'Ⳇ',
  'ⳉ' => 'Ⳉ',
  'ⳋ' => 'Ⳋ',
  'ⳍ' => 'Ⳍ',
  'ⳏ' => 'Ⳏ',
  'ⳑ' => 'Ⳑ',
  'ⳓ' => 'Ⳓ',
  'ⳕ' => 'Ⳕ',
  'ⳗ' => 'Ⳗ',
  'ⳙ' => 'Ⳙ',
  'ⳛ' => 'Ⳛ',
  'ⳝ' => 'Ⳝ',
  'ⳟ' => 'Ⳟ',
  'ⳡ' => 'Ⳡ',
  'ⳣ' => 'Ⳣ',
  'ⳬ' => 'Ⳬ',
  'ⳮ' => 'Ⳮ',
  'ⳳ' => 'Ⳳ',
  'ⴀ' => 'Ⴀ',
  'ⴁ' => 'Ⴁ',
  'ⴂ' => 'Ⴂ',
  'ⴃ' => 'Ⴃ',
  'ⴄ' => 'Ⴄ',
  'ⴅ' => 'Ⴅ',
  'ⴆ' => 'Ⴆ',
  'ⴇ' => 'Ⴇ',
  'ⴈ' => 'Ⴈ',
  'ⴉ' => 'Ⴉ',
  'ⴊ' => 'Ⴊ',
  'ⴋ' => 'Ⴋ',
  'ⴌ' => 'Ⴌ',
  'ⴍ' => 'Ⴍ',
  'ⴎ' => 'Ⴎ',
  'ⴏ' => 'Ⴏ',
  'ⴐ' => 'Ⴐ',
  'ⴑ' => 'Ⴑ',
  'ⴒ' => 'Ⴒ',
  'ⴓ' => 'Ⴓ',
  'ⴔ' => 'Ⴔ',
  'ⴕ' => 'Ⴕ',
  'ⴖ' => 'Ⴖ',
  'ⴗ' => 'Ⴗ',
  'ⴘ' => 'Ⴘ',
  'ⴙ' => 'Ⴙ',
  'ⴚ' => 'Ⴚ',
  'ⴛ' => 'Ⴛ',
  'ⴜ' => 'Ⴜ',
  'ⴝ' => 'Ⴝ',
  'ⴞ' => 'Ⴞ',
  'ⴟ' => 'Ⴟ',
  'ⴠ' => 'Ⴠ',
  'ⴡ' => 'Ⴡ',
  'ⴢ' => 'Ⴢ',
  'ⴣ' => 'Ⴣ',
  'ⴤ' => 'Ⴤ',
  'ⴥ' => 'Ⴥ',
  'ⴧ' => 'Ⴧ',
  'ⴭ' => 'Ⴭ',
  'ꙁ' => 'Ꙁ',
  'ꙃ' => 'Ꙃ',
  'ꙅ' => 'Ꙅ',
  'ꙇ' => 'Ꙇ',
  'ꙉ' => 'Ꙉ',
  'ꙋ' => 'Ꙋ',
  'ꙍ' => 'Ꙍ',
  'ꙏ' => 'Ꙏ',
  'ꙑ' => 'Ꙑ',
  'ꙓ' => 'Ꙓ',
  'ꙕ' => 'Ꙕ',
  'ꙗ' => 'Ꙗ',
  'ꙙ' => 'Ꙙ',
  'ꙛ' => 'Ꙛ',
  'ꙝ' => 'Ꙝ',
  'ꙟ' => 'Ꙟ',
  'ꙡ' => 'Ꙡ',
  'ꙣ' => 'Ꙣ',
  'ꙥ' => 'Ꙥ',
  'ꙧ' => 'Ꙧ',
  'ꙩ' => 'Ꙩ',
  'ꙫ' => 'Ꙫ',
  'ꙭ' => 'Ꙭ',
  'ꚁ' => 'Ꚁ',
  'ꚃ' => 'Ꚃ',
  'ꚅ' => 'Ꚅ',
  'ꚇ' => 'Ꚇ',
  'ꚉ' => 'Ꚉ',
  'ꚋ' => 'Ꚋ',
  'ꚍ' => 'Ꚍ',
  'ꚏ' => 'Ꚏ',
  'ꚑ' => 'Ꚑ',
  'ꚓ' => 'Ꚓ',
  'ꚕ' => 'Ꚕ',
  'ꚗ' => 'Ꚗ',
  'ꚙ' => 'Ꚙ',
  'ꚛ' => 'Ꚛ',
  'ꜣ' => 'Ꜣ',
  'ꜥ' => 'Ꜥ',
  'ꜧ' => 'Ꜧ',
  'ꜩ' => 'Ꜩ',
  'ꜫ' => 'Ꜫ',
  'ꜭ' => 'Ꜭ',
  'ꜯ' => 'Ꜯ',
  'ꜳ' => 'Ꜳ',
  'ꜵ' => 'Ꜵ',
  'ꜷ' => 'Ꜷ',
  'ꜹ' => 'Ꜹ',
  'ꜻ' => 'Ꜻ',
  'ꜽ' => 'Ꜽ',
  'ꜿ' => 'Ꜿ',
  'ꝁ' => 'Ꝁ',
  'ꝃ' => 'Ꝃ',
  'ꝅ' => 'Ꝅ',
  'ꝇ' => 'Ꝇ',
  'ꝉ' => 'Ꝉ',
  'ꝋ' => 'Ꝋ',
  'ꝍ' => 'Ꝍ',
  'ꝏ' => 'Ꝏ',
  'ꝑ' => 'Ꝑ',
  'ꝓ' => 'Ꝓ',
  'ꝕ' => 'Ꝕ',
  'ꝗ' => 'Ꝗ',
  'ꝙ' => 'Ꝙ',
  'ꝛ' => 'Ꝛ',
  'ꝝ' => 'Ꝝ',
  'ꝟ' => 'Ꝟ',
  'ꝡ' => 'Ꝡ',
  'ꝣ' => 'Ꝣ',
  'ꝥ' => 'Ꝥ',
  'ꝧ' => 'Ꝧ',
  'ꝩ' => 'Ꝩ',
  'ꝫ' => 'Ꝫ',
  'ꝭ' => 'Ꝭ',
  'ꝯ' => 'Ꝯ',
  'ꝺ' => 'Ꝺ',
  'ꝼ' => 'Ꝼ',
  'ꝿ' => 'Ꝿ',
  'ꞁ' => 'Ꞁ',
  'ꞃ' => 'Ꞃ',
  'ꞅ' => 'Ꞅ',
  'ꞇ' => 'Ꞇ',
  'ꞌ' => 'Ꞌ',
  'ꞑ' => 'Ꞑ',
  'ꞓ' => 'Ꞓ',
  'ꞔ' => 'Ꞔ',
  'ꞗ' => 'Ꞗ',
  'ꞙ' => 'Ꞙ',
  'ꞛ' => 'Ꞛ',
  'ꞝ' => 'Ꞝ',
  'ꞟ' => 'Ꞟ',
  'ꞡ' => 'Ꞡ',
  'ꞣ' => 'Ꞣ',
  'ꞥ' => 'Ꞥ',
  'ꞧ' => 'Ꞧ',
  'ꞩ' => 'Ꞩ',
  'ꞵ' => 'Ꞵ',
  'ꞷ' => 'Ꞷ',
  'ꞹ' => 'Ꞹ',
  'ꞻ' => 'Ꞻ',
  'ꞽ' => 'Ꞽ',
  'ꞿ' => 'Ꞿ',
  'ꟃ' => 'Ꟃ',
  'ꟈ' => 'Ꟈ',
  'ꟊ' => 'Ꟊ',
  'ꟶ' => 'Ꟶ',
  'ꭓ' => 'Ꭓ',
  'ꭰ' => 'Ꭰ',
  'ꭱ' => 'Ꭱ',
  'ꭲ' => 'Ꭲ',
  'ꭳ' => 'Ꭳ',
  'ꭴ' => 'Ꭴ',
  'ꭵ' => 'Ꭵ',
  'ꭶ' => 'Ꭶ',
  'ꭷ' => 'Ꭷ',
  'ꭸ' => 'Ꭸ',
  'ꭹ' => 'Ꭹ',
  'ꭺ' => 'Ꭺ',
  'ꭻ' => 'Ꭻ',
  'ꭼ' => 'Ꭼ',
  'ꭽ' => 'Ꭽ',
  'ꭾ' => 'Ꭾ',
  'ꭿ' => 'Ꭿ',
  'ꮀ' => 'Ꮀ',
  'ꮁ' => 'Ꮁ',
  'ꮂ' => 'Ꮂ',
  'ꮃ' => 'Ꮃ',
  'ꮄ' => 'Ꮄ',
  'ꮅ' => 'Ꮅ',
  'ꮆ' => 'Ꮆ',
  'ꮇ' => 'Ꮇ',
  'ꮈ' => 'Ꮈ',
  'ꮉ' => 'Ꮉ',
  'ꮊ' => 'Ꮊ',
  'ꮋ' => 'Ꮋ',
  'ꮌ' => 'Ꮌ',
  'ꮍ' => 'Ꮍ',
  'ꮎ' => 'Ꮎ',
  'ꮏ' => 'Ꮏ',
  'ꮐ' => 'Ꮐ',
  'ꮑ' => 'Ꮑ',
  'ꮒ' => 'Ꮒ',
  'ꮓ' => 'Ꮓ',
  'ꮔ' => 'Ꮔ',
  'ꮕ' => 'Ꮕ',
  'ꮖ' => 'Ꮖ',
  'ꮗ' => 'Ꮗ',
  'ꮘ' => 'Ꮘ',
  'ꮙ' => 'Ꮙ',
  'ꮚ' => 'Ꮚ',
  'ꮛ' => 'Ꮛ',
  'ꮜ' => 'Ꮜ',
  'ꮝ' => 'Ꮝ',
  'ꮞ' => 'Ꮞ',
  'ꮟ' => 'Ꮟ',
  'ꮠ' => 'Ꮠ',
  'ꮡ' => 'Ꮡ',
  'ꮢ' => 'Ꮢ',
  'ꮣ' => 'Ꮣ',
  'ꮤ' => 'Ꮤ',
  'ꮥ' => 'Ꮥ',
  'ꮦ' => 'Ꮦ',
  'ꮧ' => 'Ꮧ',
  'ꮨ' => 'Ꮨ',
  'ꮩ' => 'Ꮩ',
  'ꮪ' => 'Ꮪ',
  'ꮫ' => 'Ꮫ',
  'ꮬ' => 'Ꮬ',
  'ꮭ' => 'Ꮭ',
  'ꮮ' => 'Ꮮ',
  'ꮯ' => 'Ꮯ',
  'ꮰ' => 'Ꮰ',
  'ꮱ' => 'Ꮱ',
  'ꮲ' => 'Ꮲ',
  'ꮳ' => 'Ꮳ',
  'ꮴ' => 'Ꮴ',
  'ꮵ' => 'Ꮵ',
  'ꮶ' => 'Ꮶ',
  'ꮷ' => 'Ꮷ',
  'ꮸ' => 'Ꮸ',
  'ꮹ' => 'Ꮹ',
  'ꮺ' => 'Ꮺ',
  'ꮻ' => 'Ꮻ',
  'ꮼ' => 'Ꮼ',
  'ꮽ' => 'Ꮽ',
  'ꮾ' => 'Ꮾ',
  'ꮿ' => 'Ꮿ',
  'ａ' => 'Ａ',
  'ｂ' => 'Ｂ',
  'ｃ' => 'Ｃ',
  'ｄ' => 'Ｄ',
  'ｅ' => 'Ｅ',
  'ｆ' => 'Ｆ',
  'ｇ' => 'Ｇ',
  'ｈ' => 'Ｈ',
  'ｉ' => 'Ｉ',
  'ｊ' => 'Ｊ',
  'ｋ' => 'Ｋ',
  'ｌ' => 'Ｌ',
  'ｍ' => 'Ｍ',
  'ｎ' => 'Ｎ',
  'ｏ' => 'Ｏ',
  'ｐ' => 'Ｐ',
  'ｑ' => 'Ｑ',
  'ｒ' => 'Ｒ',
  'ｓ' => 'Ｓ',
  'ｔ' => 'Ｔ',
  'ｕ' => 'Ｕ',
  'ｖ' => 'Ｖ',
  'ｗ' => 'Ｗ',
  'ｘ' => 'Ｘ',
  'ｙ' => 'Ｙ',
  'ｚ' => 'Ｚ',
  '𐐨' => '𐐀',
  '𐐩' => '𐐁',
  '𐐪' => '𐐂',
  '𐐫' => '𐐃',
  '𐐬' => '𐐄',
  '𐐭' => '𐐅',
  '𐐮' => '𐐆',
  '𐐯' => '𐐇',
  '𐐰' => '𐐈',
  '𐐱' => '𐐉',
  '𐐲' => '𐐊',
  '𐐳' => '𐐋',
  '𐐴' => '𐐌',
  '𐐵' => '𐐍',
  '𐐶' => '𐐎',
  '𐐷' => '𐐏',
  '𐐸' => '𐐐',
  '𐐹' => '𐐑',
  '𐐺' => '𐐒',
  '𐐻' => '𐐓',
  '𐐼' => '𐐔',
  '𐐽' => '𐐕',
  '𐐾' => '𐐖',
  '𐐿' => '𐐗',
  '𐑀' => '𐐘',
  '𐑁' => '𐐙',
  '𐑂' => '𐐚',
  '𐑃' => '𐐛',
  '𐑄' => '𐐜',
  '𐑅' => '𐐝',
  '𐑆' => '𐐞',
  '𐑇' => '𐐟',
  '𐑈' => '𐐠',
  '𐑉' => '𐐡',
  '𐑊' => '𐐢',
  '𐑋' => '𐐣',
  '𐑌' => '𐐤',
  '𐑍' => '𐐥',
  '𐑎' => '𐐦',
  '𐑏' => '𐐧',
  '𐓘' => '𐒰',
  '𐓙' => '𐒱',
  '𐓚' => '𐒲',
  '𐓛' => '𐒳',
  '𐓜' => '𐒴',
  '𐓝' => '𐒵',
  '𐓞' => '𐒶',
  '𐓟' => '𐒷',
  '𐓠' => '𐒸',
  '𐓡' => '𐒹',
  '𐓢' => '𐒺',
  '𐓣' => '𐒻',
  '𐓤' => '𐒼',
  '𐓥' => '𐒽',
  '𐓦' => '𐒾',
  '𐓧' => '𐒿',
  '𐓨' => '𐓀',
  '𐓩' => '𐓁',
  '𐓪' => '𐓂',
  '𐓫' => '𐓃',
  '𐓬' => '𐓄',
  '𐓭' => '𐓅',
  '𐓮' => '𐓆',
  '𐓯' => '𐓇',
  '𐓰' => '𐓈',
  '𐓱' => '𐓉',
  '𐓲' => '𐓊',
  '𐓳' => '𐓋',
  '𐓴' => '𐓌',
  '𐓵' => '𐓍',
  '𐓶' => '𐓎',
  '𐓷' => '𐓏',
  '𐓸' => '𐓐',
  '𐓹' => '𐓑',
  '𐓺' => '𐓒',
  '𐓻' => '𐓓',
  '𐳀' => '𐲀',
  '𐳁' => '𐲁',
  '𐳂' => '𐲂',
  '𐳃' => '𐲃',
  '𐳄' => '𐲄',
  '𐳅' => '𐲅',
  '𐳆' => '𐲆',
  '𐳇' => '𐲇',
  '𐳈' => '𐲈',
  '𐳉' => '𐲉',
  '𐳊' => '𐲊',
  '𐳋' => '𐲋',
  '𐳌' => '𐲌',
  '𐳍' => '𐲍',
  '𐳎' => '𐲎',
  '𐳏' => '𐲏',
  '𐳐' => '𐲐',
  '𐳑' => '𐲑',
  '𐳒' => '𐲒',
  '𐳓' => '𐲓',
  '𐳔' => '𐲔',
  '𐳕' => '𐲕',
  '𐳖' => '𐲖',
  '𐳗' => '𐲗',
  '𐳘' => '𐲘',
  '𐳙' => '𐲙',
  '𐳚' => '𐲚',
  '𐳛' => '𐲛',
  '𐳜' => '𐲜',
  '𐳝' => '𐲝',
  '𐳞' => '𐲞',
  '𐳟' => '𐲟',
  '𐳠' => '𐲠',
  '𐳡' => '𐲡',
  '𐳢' => '𐲢',
  '𐳣' => '𐲣',
  '𐳤' => '𐲤',
  '𐳥' => '𐲥',
  '𐳦' => '𐲦',
  '𐳧' => '𐲧',
  '𐳨' => '𐲨',
  '𐳩' => '𐲩',
  '𐳪' => '𐲪',
  '𐳫' => '𐲫',
  '𐳬' => '𐲬',
  '𐳭' => '𐲭',
  '𐳮' => '𐲮',
  '𐳯' => '𐲯',
  '𐳰' => '𐲰',
  '𐳱' => '𐲱',
  '𐳲' => '𐲲',
  '𑣀' => '𑢠',
  '𑣁' => '𑢡',
  '𑣂' => '𑢢',
  '𑣃' => '𑢣',
  '𑣄' => '𑢤',
  '𑣅' => '𑢥',
  '𑣆' => '𑢦',
  '𑣇' => '𑢧',
  '𑣈' => '𑢨',
  '𑣉' => '𑢩',
  '𑣊' => '𑢪',
  '𑣋' => '𑢫',
  '𑣌' => '𑢬',
  '𑣍' => '𑢭',
  '𑣎' => '𑢮',
  '𑣏' => '𑢯',
  '𑣐' => '𑢰',
  '𑣑' => '𑢱',
  '𑣒' => '𑢲',
  '𑣓' => '𑢳',
  '𑣔' => '𑢴',
  '𑣕' => '𑢵',
  '𑣖' => '𑢶',
  '𑣗' => '𑢷',
  '𑣘' => '𑢸',
  '𑣙' => '𑢹',
  '𑣚' => '𑢺',
  '𑣛' => '𑢻',
  '𑣜' => '𑢼',
  '𑣝' => '𑢽',
  '𑣞' => '𑢾',
  '𑣟' => '𑢿',
  '𖹠' => '𖹀',
  '𖹡' => '𖹁',
  '𖹢' => '𖹂',
  '𖹣' => '𖹃',
  '𖹤' => '𖹄',
  '𖹥' => '𖹅',
  '𖹦' => '𖹆',
  '𖹧' => '𖹇',
  '𖹨' => '𖹈',
  '𖹩' => '𖹉',
  '𖹪' => '𖹊',
  '𖹫' => '𖹋',
  '𖹬' => '𖹌',
  '𖹭' => '𖹍',
  '𖹮' => '𖹎',
  '𖹯' => '𖹏',
  '𖹰' => '𖹐',
  '𖹱' => '𖹑',
  '𖹲' => '𖹒',
  '𖹳' => '𖹓',
  '𖹴' => '𖹔',
  '𖹵' => '𖹕',
  '𖹶' => '𖹖',
  '𖹷' => '𖹗',
  '𖹸' => '𖹘',
  '𖹹' => '𖹙',
  '𖹺' => '𖹚',
  '𖹻' => '𖹛',
  '𖹼' => '𖹜',
  '𖹽' => '𖹝',
  '𖹾' => '𖹞',
  '𖹿' => '𖹟',
  '𞤢' => '𞤀',
  '𞤣' => '𞤁',
  '𞤤' => '𞤂',
  '𞤥' => '𞤃',
  '𞤦' => '𞤄',
  '𞤧' => '𞤅',
  '𞤨' => '𞤆',
  '𞤩' => '𞤇',
  '𞤪' => '𞤈',
  '𞤫' => '𞤉',
  '𞤬' => '𞤊',
  '𞤭' => '𞤋',
  '𞤮' => '𞤌',
  '𞤯' => '𞤍',
  '𞤰' => '𞤎',
  '𞤱' => '𞤏',
  '𞤲' => '𞤐',
  '𞤳' => '𞤑',
  '𞤴' => '𞤒',
  '𞤵' => '𞤓',
  '𞤶' => '𞤔',
  '𞤷' => '𞤕',
  '𞤸' => '𞤖',
  '𞤹' => '𞤗',
  '𞤺' => '𞤘',
  '𞤻' => '𞤙',
  '𞤼' => '𞤚',
  '𞤽' => '𞤛',
  '𞤾' => '𞤜',
  '𞤿' => '𞤝',
  '𞥀' => '𞤞',
  '𞥁' => '𞤟',
  '𞥂' => '𞤠',
  '𞥃' => '𞤡',
  'ß' => 'SS',
  'ﬀ' => 'FF',
  'ﬁ' => 'FI',
  'ﬂ' => 'FL',
  'ﬃ' => 'FFI',
  'ﬄ' => 'FFL',
  'ﬅ' => 'ST',
  'ﬆ' => 'ST',
  'և' => 'ԵՒ',
  'ﬓ' => 'ՄՆ',
  'ﬔ' => 'ՄԵ',
  'ﬕ' => 'ՄԻ',
  'ﬖ' => 'ՎՆ',
  'ﬗ' => 'ՄԽ',
  'ŉ' => 'ʼN',
  'ΐ' => 'Ϊ́',
  'ΰ' => 'Ϋ́',
  'ǰ' => 'J̌',
  'ẖ' => 'H̱',
  'ẗ' => 'T̈',
  'ẘ' => 'W̊',
  'ẙ' => 'Y̊',
  'ẚ' => 'Aʾ',
  'ὐ' => 'Υ̓',
  'ὒ' => 'Υ̓̀',
  'ὔ' => 'Υ̓́',
  'ὖ' => 'Υ̓͂',
  'ᾶ' => 'Α͂',
  'ῆ' => 'Η͂',
  'ῒ' => 'Ϊ̀',
  'ΐ' => 'Ϊ́',
  'ῖ' => 'Ι͂',
  'ῗ' => 'Ϊ͂',
  'ῢ' => 'Ϋ̀',
  'ΰ' => 'Ϋ́',
  'ῤ' => 'Ρ̓',
  'ῦ' => 'Υ͂',
  'ῧ' => 'Ϋ͂',
  'ῶ' => 'Ω͂',
  'ᾈ' => 'ἈΙ',
  'ᾉ' => 'ἉΙ',
  'ᾊ' => 'ἊΙ',
  'ᾋ' => 'ἋΙ',
  'ᾌ' => 'ἌΙ',
  'ᾍ' => 'ἍΙ',
  'ᾎ' => 'ἎΙ',
  'ᾏ' => 'ἏΙ',
  'ᾘ' => 'ἨΙ',
  'ᾙ' => 'ἩΙ',
  'ᾚ' => 'ἪΙ',
  'ᾛ' => 'ἫΙ',
  'ᾜ' => 'ἬΙ',
  'ᾝ' => 'ἭΙ',
  'ᾞ' => 'ἮΙ',
  'ᾟ' => 'ἯΙ',
  'ᾨ' => 'ὨΙ',
  'ᾩ' => 'ὩΙ',
  'ᾪ' => 'ὪΙ',
  'ᾫ' => 'ὫΙ',
  'ᾬ' => 'ὬΙ',
  'ᾭ' => 'ὭΙ',
  'ᾮ' => 'ὮΙ',
  'ᾯ' => 'ὯΙ',
  'ᾼ' => 'ΑΙ',
  'ῌ' => 'ΗΙ',
  'ῼ' => 'ΩΙ',
  'ᾲ' => 'ᾺΙ',
  'ᾴ' => 'ΆΙ',
  'ῂ' => 'ῊΙ',
  'ῄ' => 'ΉΙ',
  'ῲ' => 'ῺΙ',
  'ῴ' => 'ΏΙ',
  'ᾷ' => 'Α͂Ι',
  'ῇ' => 'Η͂Ι',
  'ῷ' => 'Ω͂Ι',
);
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Mbstring;

/**
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
 *
 * Implemented:
 * - mb_chr                  - Returns a specific character from its Unicode code point
 * - mb_convert_encoding     - Convert character encoding
 * - mb_convert_variables    - Convert character code in variable(s)
 * - mb_decode_mimeheader    - Decode string in MIME header field
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
 * - mb_convert_case         - Perform case folding on a string
 * - mb_detect_encoding      - Detect character encoding
 * - mb_get_info             - Get internal settings of mbstring
 * - mb_http_input           - Detect HTTP input character encoding
 * - mb_http_output          - Set/Get HTTP output character encoding
 * - mb_internal_encoding    - Set/Get internal character encoding
 * - mb_list_encodings       - Returns an array of all supported encodings
 * - mb_ord                  - Returns the Unicode code point of a character
 * - mb_output_handler       - Callback function converts character encoding in output buffer
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
 * - mb_strlen               - Get string length
 * - mb_strpos               - Find position of first occurrence of string in a string
 * - mb_strrpos              - Find position of last occurrence of a string in a string
 * - mb_str_split            - Convert a string to an array
 * - mb_strtolower           - Make a string lowercase
 * - mb_strtoupper           - Make a string uppercase
 * - mb_substitute_character - Set/Get substitution character
 * - mb_substr               - Get part of string
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
 * - mb_strstr               - Finds first occurrence of a string within another
 * - mb_strwidth             - Return width of string
 * - mb_substr_count         - Count the number of substring occurrences
 * - mb_ucfirst              - Make a string's first character uppercase
 * - mb_lcfirst              - Make a string's first character lowercase
 * - mb_trim                 - Strip whitespace (or other characters) from the beginning and end of a string
 * - mb_ltrim                - Strip whitespace (or other characters) from the beginning of a string
 * - mb_rtrim                - Strip whitespace (or other characters) from the end of a string
 *
 * Not implemented:
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
 * - mb_ereg_*               - Regular expression with multibyte support
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
 * - mb_preferred_mime_name  - Get MIME charset string
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
 * - mb_send_mail            - Send encoded mail
 * - mb_split                - Split multibyte string using regular expression
 * - mb_strcut               - Get part of string
 * - mb_strimwidth           - Get truncated string with specified width
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Mbstring
{
    public const MB_CASE_FOLD = \PHP_INT_MAX;

    private const SIMPLE_CASE_FOLD = [
        ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
        ['μ', 's', 'ι',        'σ', 'β',        'θ',        'φ',        'π',        'κ',        'ρ',        'ε',        "\xE1\xB9\xA1", 'ι'],
    ];

    private static $encodingList = ['ASCII', 'UTF-8'];
    private static $language = 'neutral';
    private static $internalEncoding = 'UTF-8';

    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
    {
        if (\is_array($s)) {
            $r = [];
            foreach ($s as $str) {
                $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding);
            }

            return $r;
        }

        if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) {
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
        } else {
            $fromEncoding = self::getEncoding($fromEncoding);
        }

        $toEncoding = self::getEncoding($toEncoding);

        if ('BASE64' === $fromEncoding) {
            $s = base64_decode($s);
            $fromEncoding = $toEncoding;
        }

        if ('BASE64' === $toEncoding) {
            return base64_encode($s);
        }

        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
                $fromEncoding = 'Windows-1252';
            }
            if ('UTF-8' !== $fromEncoding) {
                $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
            }

            return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
        }

        if ('HTML-ENTITIES' === $fromEncoding) {
            $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
            $fromEncoding = 'UTF-8';
        }

        return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
    }

    public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
    {
        $ok = true;
        array_walk_recursive($vars, static function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
            if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
                $ok = false;
            }
        });

        return $ok ? $fromEncoding : false;
    }

    public static function mb_decode_mimeheader($s)
    {
        return iconv_mime_decode($s, 2, self::$internalEncoding);
    }

    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
    {
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
    }

    public static function mb_decode_numericentity($s, $convmap, $encoding = null)
    {
        if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);

            return null;
        }

        if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
            return false;
        }

        if (null !== $encoding && !\is_scalar($encoding)) {
            trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);

            return '';  // Instead of null (cf. mb_encode_numericentity).
        }

        $s = (string) $s;
        if ('' === $s) {
            return '';
        }

        $encoding = self::getEncoding($encoding);

        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }

        $cnt = floor(\count($convmap) / 4) * 4;

        for ($i = 0; $i < $cnt; $i += 4) {
            // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
            $convmap[$i] += $convmap[$i + 2];
            $convmap[$i + 1] += $convmap[$i + 2];
        }

        $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))'.(\PHP_VERSION_ID >= 80200 ? '' : '(?!&)').';?/', static function (array $m) use ($cnt, $convmap) {
            $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
            for ($i = 0; $i < $cnt; $i += 4) {
                if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
                    return self::mb_chr($c - $convmap[$i + 2]);
                }
            }

            return $m[0];
        }, $s);

        if (null === $encoding) {
            return $s;
        }

        return iconv('UTF-8', $encoding.'//IGNORE', $s);
    }

    public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
    {
        if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);

            return null;
        }

        if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
            return false;
        }

        if (null !== $encoding && !\is_scalar($encoding)) {
            trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);

            return null;  // Instead of '' (cf. mb_decode_numericentity).
        }

        if (null !== $is_hex && !\is_scalar($is_hex)) {
            trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);

            return null;
        }

        $s = (string) $s;
        if ('' === $s) {
            return '';
        }

        $encoding = self::getEncoding($encoding);

        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }

        static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];

        $cnt = floor(\count($convmap) / 4) * 4;
        $i = 0;
        $len = \strlen($s);
        $result = '';

        while ($i < $len) {
            $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
            $uchr = substr($s, $i, $ulen);
            $i += $ulen;
            $c = self::mb_ord($uchr);

            for ($j = 0; $j < $cnt; $j += 4) {
                if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
                    $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
                    $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
                    continue 2;
                }
            }
            $result .= $uchr;
        }

        if (null === $encoding) {
            return $result;
        }

        return iconv('UTF-8', $encoding.'//IGNORE', $result);
    }

    public static function mb_convert_case($s, $mode, $encoding = null)
    {
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }

        $encoding = self::getEncoding($encoding);

        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }

        if (\MB_CASE_TITLE == $mode) {
            static $titleRegexp = null;
            if (null === $titleRegexp) {
                $titleRegexp = self::getData('titleCaseRegexp');
            }
            $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
        } else {
            if (\MB_CASE_UPPER == $mode) {
                static $upper = null;
                if (null === $upper) {
                    $upper = self::getData('upperCase');
                }
                $map = $upper;
            } else {
                if (self::MB_CASE_FOLD === $mode) {
                    static $caseFolding = null;
                    if (null === $caseFolding) {
                        $caseFolding = self::getData('caseFolding');
                    }
                    $s = strtr($s, $caseFolding);
                }

                static $lower = null;
                if (null === $lower) {
                    $lower = self::getData('lowerCase');
                }
                $map = $lower;
            }

            static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];

            $i = 0;
            $len = \strlen($s);

            while ($i < $len) {
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
                $uchr = substr($s, $i, $ulen);
                $i += $ulen;

                if (isset($map[$uchr])) {
                    $uchr = $map[$uchr];
                    $nlen = \strlen($uchr);

                    if ($nlen == $ulen) {
                        $nlen = $i;
                        do {
                            $s[--$nlen] = $uchr[--$ulen];
                        } while ($ulen);
                    } else {
                        $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
                        $len += $nlen - $ulen;
                        $i += $nlen - $ulen;
                    }
                }
            }
        }

        if (null === $encoding) {
            return $s;
        }

        return iconv('UTF-8', $encoding.'//IGNORE', $s);
    }

    public static function mb_internal_encoding($encoding = null)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }

        $normalizedEncoding = self::getEncoding($encoding);

        if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
            self::$internalEncoding = $normalizedEncoding;

            return true;
        }

        if (80000 > \PHP_VERSION_ID) {
            return false;
        }

        throw new \ValueError(\sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
    }

    public static function mb_language($lang = null)
    {
        if (null === $lang) {
            return self::$language;
        }

        switch ($normalizedLang = strtolower($lang)) {
            case 'uni':
            case 'neutral':
                self::$language = $normalizedLang;

                return true;
        }

        if (80000 > \PHP_VERSION_ID) {
            return false;
        }

        throw new \ValueError(\sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
    }

    public static function mb_list_encodings()
    {
        return ['UTF-8'];
    }

    public static function mb_encoding_aliases($encoding)
    {
        switch (strtoupper($encoding)) {
            case 'UTF8':
            case 'UTF-8':
                return ['utf8'];
        }

        return false;
    }

    public static function mb_check_encoding($var = null, $encoding = null)
    {
        if (null === $encoding) {
            if (null === $var) {
                return false;
            }
            $encoding = self::$internalEncoding;
        }

        if (!\is_array($var)) {
            return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var);
        }

        foreach ($var as $key => $value) {
            if (!self::mb_check_encoding($key, $encoding)) {
                return false;
            }
            if (!self::mb_check_encoding($value, $encoding)) {
                return false;
            }
        }

        return true;
    }

    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
    {
        if (null === $encodingList) {
            $encodingList = self::$encodingList;
        } else {
            if (!\is_array($encodingList)) {
                $encodingList = array_map('trim', explode(',', $encodingList));
            }
            $encodingList = array_map('strtoupper', $encodingList);
        }

        foreach ($encodingList as $enc) {
            switch ($enc) {
                case 'ASCII':
                    if (!preg_match('/[\x80-\xFF]/', $str)) {
                        return $enc;
                    }
                    break;

                case 'UTF8':
                case 'UTF-8':
                    if (preg_match('//u', $str)) {
                        return 'UTF-8';
                    }
                    break;

                default:
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
                        return $enc;
                    }
            }
        }

        return false;
    }

    public static function mb_detect_order($encodingList = null)
    {
        if (null === $encodingList) {
            return self::$encodingList;
        }

        if (!\is_array($encodingList)) {
            $encodingList = array_map('trim', explode(',', $encodingList));
        }
        $encodingList = array_map('strtoupper', $encodingList);

        foreach ($encodingList as $enc) {
            switch ($enc) {
                default:
                    if (strncmp($enc, 'ISO-8859-', 9)) {
                        return false;
                    }
                    // no break
                case 'ASCII':
                case 'UTF8':
                case 'UTF-8':
            }
        }

        self::$encodingList = $encodingList;

        return true;
    }

    public static function mb_strlen($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return \strlen($s);
        }

        return @iconv_strlen($s, $encoding);
    }

    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strpos($haystack, $needle, $offset);
        }

        $needle = (string) $needle;
        if ('' === $needle) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);

                return false;
            }

            return 0;
        }

        return iconv_strpos($haystack, $needle, $offset, $encoding);
    }

    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrpos($haystack, $needle, $offset);
        }

        if ($offset != (int) $offset) {
            $offset = 0;
        } elseif ($offset = (int) $offset) {
            if ($offset < 0) {
                if (0 > $offset += self::mb_strlen($needle)) {
                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
                }
                $offset = 0;
            } else {
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
            }
        }

        $pos = '' !== $needle || 80000 > \PHP_VERSION_ID
            ? iconv_strrpos($haystack, $needle, $encoding)
            : self::mb_strlen($haystack, $encoding);

        return false !== $pos ? $offset + $pos : false;
    }

    public static function mb_str_split($string, $split_length = 1, $encoding = null)
    {
        if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
            trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);

            return null;
        }

        if (1 > $split_length = (int) $split_length) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);

                return false;
            }

            throw new \ValueError('Argument #2 ($length) must be greater than 0');
        }

        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }

        if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
            $rx = '/(';
            while (65535 < $split_length) {
                $rx .= '.{65535}';
                $split_length -= 65535;
            }
            $rx .= '.{'.$split_length.'})/us';

            return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
        }

        $result = [];
        $length = mb_strlen($string, $encoding);

        for ($i = 0; $i < $length; $i += $split_length) {
            $result[] = mb_substr($string, $i, $split_length, $encoding);
        }

        return $result;
    }

    public static function mb_strtolower($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
    }

    public static function mb_strtoupper($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
    }

    public static function mb_substitute_character($c = null)
    {
        if (null === $c) {
            return 'none';
        }
        if (0 === strcasecmp($c, 'none')) {
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        if (\is_int($c) || 'long' === $c || 'entity' === $c) {
            return false;
        }

        throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
    }

    public static function mb_substr($s, $start, $length = null, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return (string) substr($s, $start, null === $length ? 2147483647 : $length);
        }

        if ($start < 0) {
            $start = iconv_strlen($s, $encoding) + $start;
            if ($start < 0) {
                $start = 0;
            }
        }

        if (null === $length) {
            $length = 2147483647;
        } elseif ($length < 0) {
            $length = iconv_strlen($s, $encoding) + $length - $start;
            if ($length < 0) {
                return '';
            }
        }

        return (string) iconv_substr($s, $start, $length, $encoding);
    }

    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [
            self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding),
            self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding),
        ]);

        return self::mb_strpos($haystack, $needle, $offset, $encoding);
    }

    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);

        return self::getSubpart($pos, $part, $haystack, $encoding);
    }

    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            $pos = strrpos($haystack, $needle);
        } else {
            $needle = self::mb_substr($needle, 0, 1, $encoding);
            $pos = iconv_strrpos($haystack, $needle, $encoding);
        }

        return self::getSubpart($pos, $part, $haystack, $encoding);
    }

    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
    {
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = self::mb_strripos($haystack, $needle, $encoding);

        return self::getSubpart($pos, $part, $haystack, $encoding);
    }

    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding);
        $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding);

        $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack);
        $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle);

        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
    }

    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = strpos($haystack, $needle);
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return substr($haystack, 0, $pos);
        }

        return substr($haystack, $pos);
    }

    public static function mb_get_info($type = 'all')
    {
        $info = [
            'internal_encoding' => self::$internalEncoding,
            'http_output' => 'pass',
            'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
            'func_overload' => 0,
            'func_overload_list' => 'no overload',
            'mail_charset' => 'UTF-8',
            'mail_header_encoding' => 'BASE64',
            'mail_body_encoding' => 'BASE64',
            'illegal_chars' => 0,
            'encoding_translation' => 'Off',
            'language' => self::$language,
            'detect_order' => self::$encodingList,
            'substitute_character' => 'none',
            'strict_detection' => 'Off',
        ];

        if ('all' === $type) {
            return $info;
        }
        if (isset($info[$type])) {
            return $info[$type];
        }

        return false;
    }

    public static function mb_http_input($type = '')
    {
        return false;
    }

    public static function mb_http_output($encoding = null)
    {
        return null !== $encoding ? 'pass' === $encoding : 'pass';
    }

    public static function mb_strwidth($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);

        if ('UTF-8' !== $encoding) {
            $s = iconv($encoding, 'UTF-8//IGNORE', $s);
        }

        $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);

        return ($wide << 1) + iconv_strlen($s, 'UTF-8');
    }

    public static function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return substr_count($haystack, $needle);
    }

    public static function mb_output_handler($contents, $status)
    {
        return $contents;
    }

    public static function mb_chr($code, $encoding = null)
    {
        if (0x80 > $code %= 0x200000) {
            $s = \chr($code);
        } elseif (0x800 > $code) {
            $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
        } elseif (0x10000 > $code) {
            $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
        } else {
            $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
        }

        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
        }

        return $s;
    }

    public static function mb_ord($s, $encoding = null)
    {
        if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
        }

        if (1 === \strlen($s)) {
            return \ord($s);
        }

        $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
        if (0xF0 <= $code) {
            return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
        }
        if (0xE0 <= $code) {
            return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
        }
        if (0xC0 <= $code) {
            return (($code - 0xC0) << 6) + $s[2] - 0x80;
        }

        return $code;
    }

    /** @return string|false */
    public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
    {
        if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
            if (\PHP_VERSION_ID < 80000) {
                trigger_error('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH', \E_USER_WARNING);

                return false;
            }

            throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
        }

        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given')) {
            return false;
        }

        if (self::mb_strlen($pad_string, $encoding) <= 0) {
            if (\PHP_VERSION_ID < 80000) {
                trigger_error('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string', \E_USER_WARNING);

                return false;
            }

            throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string');
        }

        $paddingRequired = $length - self::mb_strlen($string, $encoding);

        if ($paddingRequired < 1) {
            return $string;
        }

        switch ($pad_type) {
            case \STR_PAD_LEFT:
                return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string;
            case \STR_PAD_RIGHT:
                return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
            default:
                $leftPaddingLength = floor($paddingRequired / 2);
                $rightPaddingLength = $paddingRequired - $leftPaddingLength;

                return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
        }
    }

    /** @return string|false */
    public static function mb_ucfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
            return false;
        }

        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);

        return $firstChar.mb_substr($string, 1, null, $encoding);
    }

    /** @return string|false */
    public static function mb_lcfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
            return false;
        }

        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);

        return $firstChar.mb_substr($string, 1, null, $encoding);
    }

    private static function getSubpart($pos, $part, $haystack, $encoding)
    {
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return self::mb_substr($haystack, 0, $pos, $encoding);
        }

        return self::mb_substr($haystack, $pos, null, $encoding);
    }

    private static function html_encoding_callback(array $m)
    {
        $i = 1;
        $entities = '';
        $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));

        while (isset($m[$i])) {
            if (0x80 > $m[$i]) {
                $entities .= \chr($m[$i++]);
                continue;
            }
            if (0xF0 <= $m[$i]) {
                $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
            } elseif (0xE0 <= $m[$i]) {
                $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
            } else {
                $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
            }

            $entities .= '&#'.$c.';';
        }

        return $entities;
    }

    private static function title_case(array $s)
    {
        return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
    }

    private static function getData($file)
    {
        if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
            return require $file;
        }

        return false;
    }

    private static function getEncoding($encoding)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }

        if ('UTF-8' === $encoding) {
            return 'UTF-8';
        }

        $encoding = strtoupper($encoding);

        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
            return 'CP850';
        }

        if ('UTF8' === $encoding) {
            return 'UTF-8';
        }

        if ('UTF-32' === $encoding) {
            return 'UTF-32BE';
        }

        if ('UTF-16' === $encoding) {
            return 'UTF-16BE';
        }

        return $encoding;
    }

    /** @return string|false */
    public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
    }

    /** @return string|false */
    public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
    }

    /** @return string|false */
    public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
    }

    /** @return string|false */
    private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function)
    {
        if (null === $encoding) {
            $encoding = self::mb_internal_encoding();
        } elseif (!self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given')) {
            return false;
        }

        if ('' === $characters) {
            return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding);
        }

        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $string)) {
                $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string);
            }
            if (null !== $characters && !preg_match('//u', $characters)) {
                $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters);
            }
        } else {
            $string = iconv($encoding, 'UTF-8//IGNORE', $string);

            if (null !== $characters) {
                $characters = iconv($encoding, 'UTF-8//IGNORE', $characters);
            }
        }

        if (null === $characters) {
            $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}";
        } else {
            $characters = preg_quote($characters);
        }

        $string = preg_replace(\sprintf($regex, $characters), '', $string);

        if (null === $encoding) {
            return $string;
        }

        return iconv('UTF-8', $encoding.'//IGNORE', $string);
    }

    private static function assertEncoding(string $encoding, string $errorFormat): bool
    {
        try {
            $validEncoding = @self::mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf($errorFormat, $encoding));
        }

        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf($errorFormat, $encoding), \E_USER_WARNING);
            } else {
                throw new \ValueError(\sprintf($errorFormat, $encoding));
            }
        }

        return $validEncoding;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Mbstring as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('mb_convert_encoding')) {
    function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }
}
if (!function_exists('mb_decode_mimeheader')) {
    function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); }
}
if (!function_exists('mb_encode_mimeheader')) {
    function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }
}
if (!function_exists('mb_decode_numericentity')) {
    function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); }
}
if (!function_exists('mb_encode_numericentity')) {
    function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }
}
if (!function_exists('mb_convert_case')) {
    function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); }
}
if (!function_exists('mb_internal_encoding')) {
    function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); }
}
if (!function_exists('mb_language')) {
    function mb_language($language = null) { return p\Mbstring::mb_language($language); }
}
if (!function_exists('mb_list_encodings')) {
    function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
}
if (!function_exists('mb_encoding_aliases')) {
    function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
}
if (!function_exists('mb_check_encoding')) {
    function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); }
}
if (!function_exists('mb_detect_encoding')) {
    function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); }
}
if (!function_exists('mb_detect_order')) {
    function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
}
if (!function_exists('mb_parse_str')) {
    function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }
}
if (!function_exists('mb_strlen')) {
    function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }
}
if (!function_exists('mb_strpos')) {
    function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_strtolower')) {
    function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); }
}
if (!function_exists('mb_strtoupper')) {
    function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); }
}
if (!function_exists('mb_substitute_character')) {
    function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); }
}
if (!function_exists('mb_substr')) {
    function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); }
}
if (!function_exists('mb_stripos')) {
    function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_stristr')) {
    function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_strrchr')) {
    function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_strrichr')) {
    function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_strripos')) {
    function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_strrpos')) {
    function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }
}
if (!function_exists('mb_strstr')) {
    function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }
}
if (!function_exists('mb_get_info')) {
    function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
}
if (!function_exists('mb_http_output')) {
    function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); }
}
if (!function_exists('mb_strwidth')) {
    function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); }
}
if (!function_exists('mb_substr_count')) {
    function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); }
}
if (!function_exists('mb_output_handler')) {
    function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); }
}
if (!function_exists('mb_http_input')) {
    function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); }
}

if (!function_exists('mb_convert_variables')) {
    function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); }
}

if (!function_exists('mb_ord')) {
    function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); }
}
if (!function_exists('mb_chr')) {
    function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); }
}
if (!function_exists('mb_scrub')) {
    function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }
}
if (!function_exists('mb_str_split')) {
    function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); }
}

if (!function_exists('mb_str_pad')) {
    function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null) { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
}

if (!function_exists('mb_ucfirst')) {
    function mb_ucfirst(string $string, ?string $encoding = null) { return p\Mbstring::mb_ucfirst($string, $encoding); }
}

if (!function_exists('mb_lcfirst')) {
    function mb_lcfirst(string $string, ?string $encoding = null) { return p\Mbstring::mb_lcfirst($string, $encoding); }
}

if (!function_exists('mb_trim')) {
    function mb_trim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_trim($string, $characters, $encoding); }
}

if (!function_exists('mb_ltrim')) {
    function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_ltrim($string, $characters, $encoding); }
}

if (!function_exists('mb_rtrim')) {
    function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_rtrim($string, $characters, $encoding); }
}

if (extension_loaded('mbstring')) {
    return;
}

if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Mbstring as p;

if (!function_exists('mb_convert_encoding')) {
    function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); }
}
if (!function_exists('mb_decode_mimeheader')) {
    function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); }
}
if (!function_exists('mb_encode_mimeheader')) {
    function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); }
}
if (!function_exists('mb_decode_numericentity')) {
    function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); }
}
if (!function_exists('mb_encode_numericentity')) {
    function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); }
}
if (!function_exists('mb_convert_case')) {
    function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); }
}
if (!function_exists('mb_internal_encoding')) {
    function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); }
}
if (!function_exists('mb_language')) {
    function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); }
}
if (!function_exists('mb_list_encodings')) {
    function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); }
}
if (!function_exists('mb_encoding_aliases')) {
    function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); }
}
if (!function_exists('mb_check_encoding')) {
    function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); }
}
if (!function_exists('mb_detect_encoding')) {
    function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }
}
if (!function_exists('mb_detect_order')) {
    function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); }
}
if (!function_exists('mb_parse_str')) {
    function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }
}
if (!function_exists('mb_strlen')) {
    function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); }
}
if (!function_exists('mb_strpos')) {
    function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_strtolower')) {
    function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); }
}
if (!function_exists('mb_strtoupper')) {
    function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); }
}
if (!function_exists('mb_substitute_character')) {
    function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); }
}
if (!function_exists('mb_substr')) {
    function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); }
}
if (!function_exists('mb_stripos')) {
    function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_stristr')) {
    function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strrchr')) {
    function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strrichr')) {
    function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strripos')) {
    function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_strrpos')) {
    function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
}
if (!function_exists('mb_strstr')) {
    function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_get_info')) {
    function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); }
}
if (!function_exists('mb_http_output')) {
    function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); }
}
if (!function_exists('mb_strwidth')) {
    function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); }
}
if (!function_exists('mb_substr_count')) {
    function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); }
}
if (!function_exists('mb_output_handler')) {
    function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); }
}
if (!function_exists('mb_http_input')) {
    function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); }
}

if (!function_exists('mb_convert_variables')) {
    function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); }
}

if (!function_exists('mb_ord')) {
    function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); }
}
if (!function_exists('mb_chr')) {
    function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); }
}
if (!function_exists('mb_scrub')) {
    function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); }
}
if (!function_exists('mb_str_split')) {
    function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); }
}

if (!function_exists('mb_str_pad')) {
    function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
}

if (!function_exists('mb_ucfirst')) {
    function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
}

if (!function_exists('mb_lcfirst')) {
    function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
}

if (!function_exists('mb_trim')) {
    function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); }
}

if (!function_exists('mb_ltrim')) {
    function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); }
}

if (!function_exists('mb_rtrim')) {
    function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); }
}

if (extension_loaded('mbstring')) {
    return;
}

if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Ctype;

/**
 * Ctype implementation through regex.
 *
 * @internal
 *
 * @author Gert de Pagter <BackEndTea@gmail.com>
 */
final class Ctype
{
    /**
     * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
     *
     * @see https://php.net/ctype-alnum
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_alnum($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
    }

    /**
     * Returns TRUE if every character in text is a letter, FALSE otherwise.
     *
     * @see https://php.net/ctype-alpha
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_alpha($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
    }

    /**
     * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
     *
     * @see https://php.net/ctype-cntrl
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_cntrl($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
    }

    /**
     * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
     *
     * @see https://php.net/ctype-digit
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_digit($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
    }

    /**
     * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
     *
     * @see https://php.net/ctype-graph
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_graph($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
    }

    /**
     * Returns TRUE if every character in text is a lowercase letter.
     *
     * @see https://php.net/ctype-lower
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_lower($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
    }

    /**
     * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
     *
     * @see https://php.net/ctype-print
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_print($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
    }

    /**
     * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
     *
     * @see https://php.net/ctype-punct
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_punct($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
    }

    /**
     * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
     *
     * @see https://php.net/ctype-space
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_space($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
    }

    /**
     * Returns TRUE if every character in text is an uppercase letter.
     *
     * @see https://php.net/ctype-upper
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_upper($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
    }

    /**
     * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
     *
     * @see https://php.net/ctype-xdigit
     *
     * @param mixed $text
     *
     * @return bool
     */
    public static function ctype_xdigit($text)
    {
        $text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);

        return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
    }

    /**
     * Converts integers to their char versions according to normal ctype behaviour, if needed.
     *
     * If an integer between -128 and 255 inclusive is provided,
     * it is interpreted as the ASCII value of a single character
     * (negative values have 256 added in order to allow characters in the Extended ASCII range).
     * Any other integer is interpreted as a string containing the decimal digits of the integer.
     *
     * @param mixed  $int
     * @param string $function
     *
     * @return mixed
     */
    private static function convert_int_to_char_for_ctype($int, $function)
    {
        if (\PHP_VERSION_ID >= 80100 && !\is_string($int)) {
            @trigger_error($function.'(): Argument of type '.get_debug_type($int).' will be interpreted as string in the future', \E_USER_DEPRECATED);
        }

        if (!\is_int($int)) {
            return $int;
        }

        if ($int < -128 || $int > 255) {
            return (string) $int;
        }

        if ($int < 0) {
            $int += 256;
        }

        return \chr($int);
    }
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Ctype as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('ctype_alnum')) {
    function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
}
if (!function_exists('ctype_alpha')) {
    function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
}
if (!function_exists('ctype_cntrl')) {
    function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
}
if (!function_exists('ctype_digit')) {
    function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
}
if (!function_exists('ctype_graph')) {
    function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
}
if (!function_exists('ctype_lower')) {
    function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
}
if (!function_exists('ctype_print')) {
    function ctype_print($text) { return p\Ctype::ctype_print($text); }
}
if (!function_exists('ctype_punct')) {
    function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
}
if (!function_exists('ctype_space')) {
    function ctype_space($text) { return p\Ctype::ctype_space($text); }
}
if (!function_exists('ctype_upper')) {
    function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
}
if (!function_exists('ctype_xdigit')) {
    function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Ctype as p;

if (!function_exists('ctype_alnum')) {
    function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
}
if (!function_exists('ctype_alpha')) {
    function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
}
if (!function_exists('ctype_cntrl')) {
    function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
}
if (!function_exists('ctype_digit')) {
    function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
}
if (!function_exists('ctype_graph')) {
    function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
}
if (!function_exists('ctype_lower')) {
    function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
}
if (!function_exists('ctype_print')) {
    function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
}
if (!function_exists('ctype_punct')) {
    function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
}
if (!function_exists('ctype_space')) {
    function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
}
if (!function_exists('ctype_upper')) {
    function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
}
if (!function_exists('ctype_xdigit')) {
    function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
}
<?php

class Normalizer extends Symfony\Polyfill\Intl\Normalizer\Normalizer
{
    /**
     * @deprecated since ICU 56 and removed in PHP 8
     */
    public const NONE = 2;
    public const FORM_D = 4;
    public const FORM_KD = 8;
    public const FORM_C = 16;
    public const FORM_KC = 32;
    public const NFD = 4;
    public const NFKD = 8;
    public const NFC = 16;
    public const NFKC = 32;
}
<?php

return array (
  ' ' => ' ',
  '¨' => ' ̈',
  'ª' => 'a',
  '¯' => ' ̄',
  '²' => '2',
  '³' => '3',
  '´' => ' ́',
  'µ' => 'μ',
  '¸' => ' ̧',
  '¹' => '1',
  'º' => 'o',
  '¼' => '1⁄4',
  '½' => '1⁄2',
  '¾' => '3⁄4',
  'Ĳ' => 'IJ',
  'ĳ' => 'ij',
  'Ŀ' => 'L·',
  'ŀ' => 'l·',
  'ŉ' => 'ʼn',
  'ſ' => 's',
  'Ǆ' => 'DŽ',
  'ǅ' => 'Dž',
  'ǆ' => 'dž',
  'Ǉ' => 'LJ',
  'ǈ' => 'Lj',
  'ǉ' => 'lj',
  'Ǌ' => 'NJ',
  'ǋ' => 'Nj',
  'ǌ' => 'nj',
  'Ǳ' => 'DZ',
  'ǲ' => 'Dz',
  'ǳ' => 'dz',
  'ʰ' => 'h',
  'ʱ' => 'ɦ',
  'ʲ' => 'j',
  'ʳ' => 'r',
  'ʴ' => 'ɹ',
  'ʵ' => 'ɻ',
  'ʶ' => 'ʁ',
  'ʷ' => 'w',
  'ʸ' => 'y',
  '˘' => ' ̆',
  '˙' => ' ̇',
  '˚' => ' ̊',
  '˛' => ' ̨',
  '˜' => ' ̃',
  '˝' => ' ̋',
  'ˠ' => 'ɣ',
  'ˡ' => 'l',
  'ˢ' => 's',
  'ˣ' => 'x',
  'ˤ' => 'ʕ',
  'ͺ' => ' ͅ',
  '΄' => ' ́',
  '΅' => ' ̈́',
  'ϐ' => 'β',
  'ϑ' => 'θ',
  'ϒ' => 'Υ',
  'ϓ' => 'Ύ',
  'ϔ' => 'Ϋ',
  'ϕ' => 'φ',
  'ϖ' => 'π',
  'ϰ' => 'κ',
  'ϱ' => 'ρ',
  'ϲ' => 'ς',
  'ϴ' => 'Θ',
  'ϵ' => 'ε',
  'Ϲ' => 'Σ',
  'և' => 'եւ',
  'ٵ' => 'اٴ',
  'ٶ' => 'وٴ',
  'ٷ' => 'ۇٴ',
  'ٸ' => 'يٴ',
  'ำ' => 'ํา',
  'ຳ' => 'ໍາ',
  'ໜ' => 'ຫນ',
  'ໝ' => 'ຫມ',
  '༌' => '་',
  'ཷ' => 'ྲཱྀ',
  'ཹ' => 'ླཱྀ',
  'ჼ' => 'ნ',
  'ᴬ' => 'A',
  'ᴭ' => 'Æ',
  'ᴮ' => 'B',
  'ᴰ' => 'D',
  'ᴱ' => 'E',
  'ᴲ' => 'Ǝ',
  'ᴳ' => 'G',
  'ᴴ' => 'H',
  'ᴵ' => 'I',
  'ᴶ' => 'J',
  'ᴷ' => 'K',
  'ᴸ' => 'L',
  'ᴹ' => 'M',
  'ᴺ' => 'N',
  'ᴼ' => 'O',
  'ᴽ' => 'Ȣ',
  'ᴾ' => 'P',
  'ᴿ' => 'R',
  'ᵀ' => 'T',
  'ᵁ' => 'U',
  'ᵂ' => 'W',
  'ᵃ' => 'a',
  'ᵄ' => 'ɐ',
  'ᵅ' => 'ɑ',
  'ᵆ' => 'ᴂ',
  'ᵇ' => 'b',
  'ᵈ' => 'd',
  'ᵉ' => 'e',
  'ᵊ' => 'ə',
  'ᵋ' => 'ɛ',
  'ᵌ' => 'ɜ',
  'ᵍ' => 'g',
  'ᵏ' => 'k',
  'ᵐ' => 'm',
  'ᵑ' => 'ŋ',
  'ᵒ' => 'o',
  'ᵓ' => 'ɔ',
  'ᵔ' => 'ᴖ',
  'ᵕ' => 'ᴗ',
  'ᵖ' => 'p',
  'ᵗ' => 't',
  'ᵘ' => 'u',
  'ᵙ' => 'ᴝ',
  'ᵚ' => 'ɯ',
  'ᵛ' => 'v',
  'ᵜ' => 'ᴥ',
  'ᵝ' => 'β',
  'ᵞ' => 'γ',
  'ᵟ' => 'δ',
  'ᵠ' => 'φ',
  'ᵡ' => 'χ',
  'ᵢ' => 'i',
  'ᵣ' => 'r',
  'ᵤ' => 'u',
  'ᵥ' => 'v',
  'ᵦ' => 'β',
  'ᵧ' => 'γ',
  'ᵨ' => 'ρ',
  'ᵩ' => 'φ',
  'ᵪ' => 'χ',
  'ᵸ' => 'н',
  'ᶛ' => 'ɒ',
  'ᶜ' => 'c',
  'ᶝ' => 'ɕ',
  'ᶞ' => 'ð',
  'ᶟ' => 'ɜ',
  'ᶠ' => 'f',
  'ᶡ' => 'ɟ',
  'ᶢ' => 'ɡ',
  'ᶣ' => 'ɥ',
  'ᶤ' => 'ɨ',
  'ᶥ' => 'ɩ',
  'ᶦ' => 'ɪ',
  'ᶧ' => 'ᵻ',
  'ᶨ' => 'ʝ',
  'ᶩ' => 'ɭ',
  'ᶪ' => 'ᶅ',
  'ᶫ' => 'ʟ',
  'ᶬ' => 'ɱ',
  'ᶭ' => 'ɰ',
  'ᶮ' => 'ɲ',
  'ᶯ' => 'ɳ',
  'ᶰ' => 'ɴ',
  'ᶱ' => 'ɵ',
  'ᶲ' => 'ɸ',
  'ᶳ' => 'ʂ',
  'ᶴ' => 'ʃ',
  'ᶵ' => 'ƫ',
  'ᶶ' => 'ʉ',
  'ᶷ' => 'ʊ',
  'ᶸ' => 'ᴜ',
  'ᶹ' => 'ʋ',
  'ᶺ' => 'ʌ',
  'ᶻ' => 'z',
  'ᶼ' => 'ʐ',
  'ᶽ' => 'ʑ',
  'ᶾ' => 'ʒ',
  'ᶿ' => 'θ',
  'ẚ' => 'aʾ',
  'ẛ' => 'ṡ',
  '᾽' => ' ̓',
  '᾿' => ' ̓',
  '῀' => ' ͂',
  '῁' => ' ̈͂',
  '῍' => ' ̓̀',
  '῎' => ' ̓́',
  '῏' => ' ̓͂',
  '῝' => ' ̔̀',
  '῞' => ' ̔́',
  '῟' => ' ̔͂',
  '῭' => ' ̈̀',
  '΅' => ' ̈́',
  '´' => ' ́',
  '῾' => ' ̔',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  ' ' => ' ',
  '‑' => '‐',
  '‗' => ' ̳',
  '․' => '.',
  '‥' => '..',
  '…' => '...',
  ' ' => ' ',
  '″' => '′′',
  '‴' => '′′′',
  '‶' => '‵‵',
  '‷' => '‵‵‵',
  '‼' => '!!',
  '‾' => ' ̅',
  '⁇' => '??',
  '⁈' => '?!',
  '⁉' => '!?',
  '⁗' => '′′′′',
  ' ' => ' ',
  '⁰' => '0',
  'ⁱ' => 'i',
  '⁴' => '4',
  '⁵' => '5',
  '⁶' => '6',
  '⁷' => '7',
  '⁸' => '8',
  '⁹' => '9',
  '⁺' => '+',
  '⁻' => '−',
  '⁼' => '=',
  '⁽' => '(',
  '⁾' => ')',
  'ⁿ' => 'n',
  '₀' => '0',
  '₁' => '1',
  '₂' => '2',
  '₃' => '3',
  '₄' => '4',
  '₅' => '5',
  '₆' => '6',
  '₇' => '7',
  '₈' => '8',
  '₉' => '9',
  '₊' => '+',
  '₋' => '−',
  '₌' => '=',
  '₍' => '(',
  '₎' => ')',
  'ₐ' => 'a',
  'ₑ' => 'e',
  'ₒ' => 'o',
  'ₓ' => 'x',
  'ₔ' => 'ə',
  'ₕ' => 'h',
  'ₖ' => 'k',
  'ₗ' => 'l',
  'ₘ' => 'm',
  'ₙ' => 'n',
  'ₚ' => 'p',
  'ₛ' => 's',
  'ₜ' => 't',
  '₨' => 'Rs',
  '℀' => 'a/c',
  '℁' => 'a/s',
  'ℂ' => 'C',
  '℃' => '°C',
  '℅' => 'c/o',
  '℆' => 'c/u',
  'ℇ' => 'Ɛ',
  '℉' => '°F',
  'ℊ' => 'g',
  'ℋ' => 'H',
  'ℌ' => 'H',
  'ℍ' => 'H',
  'ℎ' => 'h',
  'ℏ' => 'ħ',
  'ℐ' => 'I',
  'ℑ' => 'I',
  'ℒ' => 'L',
  'ℓ' => 'l',
  'ℕ' => 'N',
  '№' => 'No',
  'ℙ' => 'P',
  'ℚ' => 'Q',
  'ℛ' => 'R',
  'ℜ' => 'R',
  'ℝ' => 'R',
  '℠' => 'SM',
  '℡' => 'TEL',
  '™' => 'TM',
  'ℤ' => 'Z',
  'ℨ' => 'Z',
  'ℬ' => 'B',
  'ℭ' => 'C',
  'ℯ' => 'e',
  'ℰ' => 'E',
  'ℱ' => 'F',
  'ℳ' => 'M',
  'ℴ' => 'o',
  'ℵ' => 'א',
  'ℶ' => 'ב',
  'ℷ' => 'ג',
  'ℸ' => 'ד',
  'ℹ' => 'i',
  '℻' => 'FAX',
  'ℼ' => 'π',
  'ℽ' => 'γ',
  'ℾ' => 'Γ',
  'ℿ' => 'Π',
  '⅀' => '∑',
  'ⅅ' => 'D',
  'ⅆ' => 'd',
  'ⅇ' => 'e',
  'ⅈ' => 'i',
  'ⅉ' => 'j',
  '⅐' => '1⁄7',
  '⅑' => '1⁄9',
  '⅒' => '1⁄10',
  '⅓' => '1⁄3',
  '⅔' => '2⁄3',
  '⅕' => '1⁄5',
  '⅖' => '2⁄5',
  '⅗' => '3⁄5',
  '⅘' => '4⁄5',
  '⅙' => '1⁄6',
  '⅚' => '5⁄6',
  '⅛' => '1⁄8',
  '⅜' => '3⁄8',
  '⅝' => '5⁄8',
  '⅞' => '7⁄8',
  '⅟' => '1⁄',
  'Ⅰ' => 'I',
  'Ⅱ' => 'II',
  'Ⅲ' => 'III',
  'Ⅳ' => 'IV',
  'Ⅴ' => 'V',
  'Ⅵ' => 'VI',
  'Ⅶ' => 'VII',
  'Ⅷ' => 'VIII',
  'Ⅸ' => 'IX',
  'Ⅹ' => 'X',
  'Ⅺ' => 'XI',
  'Ⅻ' => 'XII',
  'Ⅼ' => 'L',
  'Ⅽ' => 'C',
  'Ⅾ' => 'D',
  'Ⅿ' => 'M',
  'ⅰ' => 'i',
  'ⅱ' => 'ii',
  'ⅲ' => 'iii',
  'ⅳ' => 'iv',
  'ⅴ' => 'v',
  'ⅵ' => 'vi',
  'ⅶ' => 'vii',
  'ⅷ' => 'viii',
  'ⅸ' => 'ix',
  'ⅹ' => 'x',
  'ⅺ' => 'xi',
  'ⅻ' => 'xii',
  'ⅼ' => 'l',
  'ⅽ' => 'c',
  'ⅾ' => 'd',
  'ⅿ' => 'm',
  '↉' => '0⁄3',
  '∬' => '∫∫',
  '∭' => '∫∫∫',
  '∯' => '∮∮',
  '∰' => '∮∮∮',
  '①' => '1',
  '②' => '2',
  '③' => '3',
  '④' => '4',
  '⑤' => '5',
  '⑥' => '6',
  '⑦' => '7',
  '⑧' => '8',
  '⑨' => '9',
  '⑩' => '10',
  '⑪' => '11',
  '⑫' => '12',
  '⑬' => '13',
  '⑭' => '14',
  '⑮' => '15',
  '⑯' => '16',
  '⑰' => '17',
  '⑱' => '18',
  '⑲' => '19',
  '⑳' => '20',
  '⑴' => '(1)',
  '⑵' => '(2)',
  '⑶' => '(3)',
  '⑷' => '(4)',
  '⑸' => '(5)',
  '⑹' => '(6)',
  '⑺' => '(7)',
  '⑻' => '(8)',
  '⑼' => '(9)',
  '⑽' => '(10)',
  '⑾' => '(11)',
  '⑿' => '(12)',
  '⒀' => '(13)',
  '⒁' => '(14)',
  '⒂' => '(15)',
  '⒃' => '(16)',
  '⒄' => '(17)',
  '⒅' => '(18)',
  '⒆' => '(19)',
  '⒇' => '(20)',
  '⒈' => '1.',
  '⒉' => '2.',
  '⒊' => '3.',
  '⒋' => '4.',
  '⒌' => '5.',
  '⒍' => '6.',
  '⒎' => '7.',
  '⒏' => '8.',
  '⒐' => '9.',
  '⒑' => '10.',
  '⒒' => '11.',
  '⒓' => '12.',
  '⒔' => '13.',
  '⒕' => '14.',
  '⒖' => '15.',
  '⒗' => '16.',
  '⒘' => '17.',
  '⒙' => '18.',
  '⒚' => '19.',
  '⒛' => '20.',
  '⒜' => '(a)',
  '⒝' => '(b)',
  '⒞' => '(c)',
  '⒟' => '(d)',
  '⒠' => '(e)',
  '⒡' => '(f)',
  '⒢' => '(g)',
  '⒣' => '(h)',
  '⒤' => '(i)',
  '⒥' => '(j)',
  '⒦' => '(k)',
  '⒧' => '(l)',
  '⒨' => '(m)',
  '⒩' => '(n)',
  '⒪' => '(o)',
  '⒫' => '(p)',
  '⒬' => '(q)',
  '⒭' => '(r)',
  '⒮' => '(s)',
  '⒯' => '(t)',
  '⒰' => '(u)',
  '⒱' => '(v)',
  '⒲' => '(w)',
  '⒳' => '(x)',
  '⒴' => '(y)',
  '⒵' => '(z)',
  'Ⓐ' => 'A',
  'Ⓑ' => 'B',
  'Ⓒ' => 'C',
  'Ⓓ' => 'D',
  'Ⓔ' => 'E',
  'Ⓕ' => 'F',
  'Ⓖ' => 'G',
  'Ⓗ' => 'H',
  'Ⓘ' => 'I',
  'Ⓙ' => 'J',
  'Ⓚ' => 'K',
  'Ⓛ' => 'L',
  'Ⓜ' => 'M',
  'Ⓝ' => 'N',
  'Ⓞ' => 'O',
  'Ⓟ' => 'P',
  'Ⓠ' => 'Q',
  'Ⓡ' => 'R',
  'Ⓢ' => 'S',
  'Ⓣ' => 'T',
  'Ⓤ' => 'U',
  'Ⓥ' => 'V',
  'Ⓦ' => 'W',
  'Ⓧ' => 'X',
  'Ⓨ' => 'Y',
  'Ⓩ' => 'Z',
  'ⓐ' => 'a',
  'ⓑ' => 'b',
  'ⓒ' => 'c',
  'ⓓ' => 'd',
  'ⓔ' => 'e',
  'ⓕ' => 'f',
  'ⓖ' => 'g',
  'ⓗ' => 'h',
  'ⓘ' => 'i',
  'ⓙ' => 'j',
  'ⓚ' => 'k',
  'ⓛ' => 'l',
  'ⓜ' => 'm',
  'ⓝ' => 'n',
  'ⓞ' => 'o',
  'ⓟ' => 'p',
  'ⓠ' => 'q',
  'ⓡ' => 'r',
  'ⓢ' => 's',
  'ⓣ' => 't',
  'ⓤ' => 'u',
  'ⓥ' => 'v',
  'ⓦ' => 'w',
  'ⓧ' => 'x',
  'ⓨ' => 'y',
  'ⓩ' => 'z',
  '⓪' => '0',
  '⨌' => '∫∫∫∫',
  '⩴' => '::=',
  '⩵' => '==',
  '⩶' => '===',
  'ⱼ' => 'j',
  'ⱽ' => 'V',
  'ⵯ' => 'ⵡ',
  '⺟' => '母',
  '⻳' => '龟',
  '⼀' => '一',
  '⼁' => '丨',
  '⼂' => '丶',
  '⼃' => '丿',
  '⼄' => '乙',
  '⼅' => '亅',
  '⼆' => '二',
  '⼇' => '亠',
  '⼈' => '人',
  '⼉' => '儿',
  '⼊' => '入',
  '⼋' => '八',
  '⼌' => '冂',
  '⼍' => '冖',
  '⼎' => '冫',
  '⼏' => '几',
  '⼐' => '凵',
  '⼑' => '刀',
  '⼒' => '力',
  '⼓' => '勹',
  '⼔' => '匕',
  '⼕' => '匚',
  '⼖' => '匸',
  '⼗' => '十',
  '⼘' => '卜',
  '⼙' => '卩',
  '⼚' => '厂',
  '⼛' => '厶',
  '⼜' => '又',
  '⼝' => '口',
  '⼞' => '囗',
  '⼟' => '土',
  '⼠' => '士',
  '⼡' => '夂',
  '⼢' => '夊',
  '⼣' => '夕',
  '⼤' => '大',
  '⼥' => '女',
  '⼦' => '子',
  '⼧' => '宀',
  '⼨' => '寸',
  '⼩' => '小',
  '⼪' => '尢',
  '⼫' => '尸',
  '⼬' => '屮',
  '⼭' => '山',
  '⼮' => '巛',
  '⼯' => '工',
  '⼰' => '己',
  '⼱' => '巾',
  '⼲' => '干',
  '⼳' => '幺',
  '⼴' => '广',
  '⼵' => '廴',
  '⼶' => '廾',
  '⼷' => '弋',
  '⼸' => '弓',
  '⼹' => '彐',
  '⼺' => '彡',
  '⼻' => '彳',
  '⼼' => '心',
  '⼽' => '戈',
  '⼾' => '戶',
  '⼿' => '手',
  '⽀' => '支',
  '⽁' => '攴',
  '⽂' => '文',
  '⽃' => '斗',
  '⽄' => '斤',
  '⽅' => '方',
  '⽆' => '无',
  '⽇' => '日',
  '⽈' => '曰',
  '⽉' => '月',
  '⽊' => '木',
  '⽋' => '欠',
  '⽌' => '止',
  '⽍' => '歹',
  '⽎' => '殳',
  '⽏' => '毋',
  '⽐' => '比',
  '⽑' => '毛',
  '⽒' => '氏',
  '⽓' => '气',
  '⽔' => '水',
  '⽕' => '火',
  '⽖' => '爪',
  '⽗' => '父',
  '⽘' => '爻',
  '⽙' => '爿',
  '⽚' => '片',
  '⽛' => '牙',
  '⽜' => '牛',
  '⽝' => '犬',
  '⽞' => '玄',
  '⽟' => '玉',
  '⽠' => '瓜',
  '⽡' => '瓦',
  '⽢' => '甘',
  '⽣' => '生',
  '⽤' => '用',
  '⽥' => '田',
  '⽦' => '疋',
  '⽧' => '疒',
  '⽨' => '癶',
  '⽩' => '白',
  '⽪' => '皮',
  '⽫' => '皿',
  '⽬' => '目',
  '⽭' => '矛',
  '⽮' => '矢',
  '⽯' => '石',
  '⽰' => '示',
  '⽱' => '禸',
  '⽲' => '禾',
  '⽳' => '穴',
  '⽴' => '立',
  '⽵' => '竹',
  '⽶' => '米',
  '⽷' => '糸',
  '⽸' => '缶',
  '⽹' => '网',
  '⽺' => '羊',
  '⽻' => '羽',
  '⽼' => '老',
  '⽽' => '而',
  '⽾' => '耒',
  '⽿' => '耳',
  '⾀' => '聿',
  '⾁' => '肉',
  '⾂' => '臣',
  '⾃' => '自',
  '⾄' => '至',
  '⾅' => '臼',
  '⾆' => '舌',
  '⾇' => '舛',
  '⾈' => '舟',
  '⾉' => '艮',
  '⾊' => '色',
  '⾋' => '艸',
  '⾌' => '虍',
  '⾍' => '虫',
  '⾎' => '血',
  '⾏' => '行',
  '⾐' => '衣',
  '⾑' => '襾',
  '⾒' => '見',
  '⾓' => '角',
  '⾔' => '言',
  '⾕' => '谷',
  '⾖' => '豆',
  '⾗' => '豕',
  '⾘' => '豸',
  '⾙' => '貝',
  '⾚' => '赤',
  '⾛' => '走',
  '⾜' => '足',
  '⾝' => '身',
  '⾞' => '車',
  '⾟' => '辛',
  '⾠' => '辰',
  '⾡' => '辵',
  '⾢' => '邑',
  '⾣' => '酉',
  '⾤' => '釆',
  '⾥' => '里',
  '⾦' => '金',
  '⾧' => '長',
  '⾨' => '門',
  '⾩' => '阜',
  '⾪' => '隶',
  '⾫' => '隹',
  '⾬' => '雨',
  '⾭' => '靑',
  '⾮' => '非',
  '⾯' => '面',
  '⾰' => '革',
  '⾱' => '韋',
  '⾲' => '韭',
  '⾳' => '音',
  '⾴' => '頁',
  '⾵' => '風',
  '⾶' => '飛',
  '⾷' => '食',
  '⾸' => '首',
  '⾹' => '香',
  '⾺' => '馬',
  '⾻' => '骨',
  '⾼' => '高',
  '⾽' => '髟',
  '⾾' => '鬥',
  '⾿' => '鬯',
  '⿀' => '鬲',
  '⿁' => '鬼',
  '⿂' => '魚',
  '⿃' => '鳥',
  '⿄' => '鹵',
  '⿅' => '鹿',
  '⿆' => '麥',
  '⿇' => '麻',
  '⿈' => '黃',
  '⿉' => '黍',
  '⿊' => '黑',
  '⿋' => '黹',
  '⿌' => '黽',
  '⿍' => '鼎',
  '⿎' => '鼓',
  '⿏' => '鼠',
  '⿐' => '鼻',
  '⿑' => '齊',
  '⿒' => '齒',
  '⿓' => '龍',
  '⿔' => '龜',
  '⿕' => '龠',
  '　' => ' ',
  '〶' => '〒',
  '〸' => '十',
  '〹' => '卄',
  '〺' => '卅',
  '゛' => ' ゙',
  '゜' => ' ゚',
  'ゟ' => 'より',
  'ヿ' => 'コト',
  'ㄱ' => 'ᄀ',
  'ㄲ' => 'ᄁ',
  'ㄳ' => 'ᆪ',
  'ㄴ' => 'ᄂ',
  'ㄵ' => 'ᆬ',
  'ㄶ' => 'ᆭ',
  'ㄷ' => 'ᄃ',
  'ㄸ' => 'ᄄ',
  'ㄹ' => 'ᄅ',
  'ㄺ' => 'ᆰ',
  'ㄻ' => 'ᆱ',
  'ㄼ' => 'ᆲ',
  'ㄽ' => 'ᆳ',
  'ㄾ' => 'ᆴ',
  'ㄿ' => 'ᆵ',
  'ㅀ' => 'ᄚ',
  'ㅁ' => 'ᄆ',
  'ㅂ' => 'ᄇ',
  'ㅃ' => 'ᄈ',
  'ㅄ' => 'ᄡ',
  'ㅅ' => 'ᄉ',
  'ㅆ' => 'ᄊ',
  'ㅇ' => 'ᄋ',
  'ㅈ' => 'ᄌ',
  'ㅉ' => 'ᄍ',
  'ㅊ' => 'ᄎ',
  'ㅋ' => 'ᄏ',
  'ㅌ' => 'ᄐ',
  'ㅍ' => 'ᄑ',
  'ㅎ' => 'ᄒ',
  'ㅏ' => 'ᅡ',
  'ㅐ' => 'ᅢ',
  'ㅑ' => 'ᅣ',
  'ㅒ' => 'ᅤ',
  'ㅓ' => 'ᅥ',
  'ㅔ' => 'ᅦ',
  'ㅕ' => 'ᅧ',
  'ㅖ' => 'ᅨ',
  'ㅗ' => 'ᅩ',
  'ㅘ' => 'ᅪ',
  'ㅙ' => 'ᅫ',
  'ㅚ' => 'ᅬ',
  'ㅛ' => 'ᅭ',
  'ㅜ' => 'ᅮ',
  'ㅝ' => 'ᅯ',
  'ㅞ' => 'ᅰ',
  'ㅟ' => 'ᅱ',
  'ㅠ' => 'ᅲ',
  'ㅡ' => 'ᅳ',
  'ㅢ' => 'ᅴ',
  'ㅣ' => 'ᅵ',
  'ㅤ' => 'ᅠ',
  'ㅥ' => 'ᄔ',
  'ㅦ' => 'ᄕ',
  'ㅧ' => 'ᇇ',
  'ㅨ' => 'ᇈ',
  'ㅩ' => 'ᇌ',
  'ㅪ' => 'ᇎ',
  'ㅫ' => 'ᇓ',
  'ㅬ' => 'ᇗ',
  'ㅭ' => 'ᇙ',
  'ㅮ' => 'ᄜ',
  'ㅯ' => 'ᇝ',
  'ㅰ' => 'ᇟ',
  'ㅱ' => 'ᄝ',
  'ㅲ' => 'ᄞ',
  'ㅳ' => 'ᄠ',
  'ㅴ' => 'ᄢ',
  'ㅵ' => 'ᄣ',
  'ㅶ' => 'ᄧ',
  'ㅷ' => 'ᄩ',
  'ㅸ' => 'ᄫ',
  'ㅹ' => 'ᄬ',
  'ㅺ' => 'ᄭ',
  'ㅻ' => 'ᄮ',
  'ㅼ' => 'ᄯ',
  'ㅽ' => 'ᄲ',
  'ㅾ' => 'ᄶ',
  'ㅿ' => 'ᅀ',
  'ㆀ' => 'ᅇ',
  'ㆁ' => 'ᅌ',
  'ㆂ' => 'ᇱ',
  'ㆃ' => 'ᇲ',
  'ㆄ' => 'ᅗ',
  'ㆅ' => 'ᅘ',
  'ㆆ' => 'ᅙ',
  'ㆇ' => 'ᆄ',
  'ㆈ' => 'ᆅ',
  'ㆉ' => 'ᆈ',
  'ㆊ' => 'ᆑ',
  'ㆋ' => 'ᆒ',
  'ㆌ' => 'ᆔ',
  'ㆍ' => 'ᆞ',
  'ㆎ' => 'ᆡ',
  '㆒' => '一',
  '㆓' => '二',
  '㆔' => '三',
  '㆕' => '四',
  '㆖' => '上',
  '㆗' => '中',
  '㆘' => '下',
  '㆙' => '甲',
  '㆚' => '乙',
  '㆛' => '丙',
  '㆜' => '丁',
  '㆝' => '天',
  '㆞' => '地',
  '㆟' => '人',
  '㈀' => '(ᄀ)',
  '㈁' => '(ᄂ)',
  '㈂' => '(ᄃ)',
  '㈃' => '(ᄅ)',
  '㈄' => '(ᄆ)',
  '㈅' => '(ᄇ)',
  '㈆' => '(ᄉ)',
  '㈇' => '(ᄋ)',
  '㈈' => '(ᄌ)',
  '㈉' => '(ᄎ)',
  '㈊' => '(ᄏ)',
  '㈋' => '(ᄐ)',
  '㈌' => '(ᄑ)',
  '㈍' => '(ᄒ)',
  '㈎' => '(가)',
  '㈏' => '(나)',
  '㈐' => '(다)',
  '㈑' => '(라)',
  '㈒' => '(마)',
  '㈓' => '(바)',
  '㈔' => '(사)',
  '㈕' => '(아)',
  '㈖' => '(자)',
  '㈗' => '(차)',
  '㈘' => '(카)',
  '㈙' => '(타)',
  '㈚' => '(파)',
  '㈛' => '(하)',
  '㈜' => '(주)',
  '㈝' => '(오전)',
  '㈞' => '(오후)',
  '㈠' => '(一)',
  '㈡' => '(二)',
  '㈢' => '(三)',
  '㈣' => '(四)',
  '㈤' => '(五)',
  '㈥' => '(六)',
  '㈦' => '(七)',
  '㈧' => '(八)',
  '㈨' => '(九)',
  '㈩' => '(十)',
  '㈪' => '(月)',
  '㈫' => '(火)',
  '㈬' => '(水)',
  '㈭' => '(木)',
  '㈮' => '(金)',
  '㈯' => '(土)',
  '㈰' => '(日)',
  '㈱' => '(株)',
  '㈲' => '(有)',
  '㈳' => '(社)',
  '㈴' => '(名)',
  '㈵' => '(特)',
  '㈶' => '(財)',
  '㈷' => '(祝)',
  '㈸' => '(労)',
  '㈹' => '(代)',
  '㈺' => '(呼)',
  '㈻' => '(学)',
  '㈼' => '(監)',
  '㈽' => '(企)',
  '㈾' => '(資)',
  '㈿' => '(協)',
  '㉀' => '(祭)',
  '㉁' => '(休)',
  '㉂' => '(自)',
  '㉃' => '(至)',
  '㉄' => '問',
  '㉅' => '幼',
  '㉆' => '文',
  '㉇' => '箏',
  '㉐' => 'PTE',
  '㉑' => '21',
  '㉒' => '22',
  '㉓' => '23',
  '㉔' => '24',
  '㉕' => '25',
  '㉖' => '26',
  '㉗' => '27',
  '㉘' => '28',
  '㉙' => '29',
  '㉚' => '30',
  '㉛' => '31',
  '㉜' => '32',
  '㉝' => '33',
  '㉞' => '34',
  '㉟' => '35',
  '㉠' => 'ᄀ',
  '㉡' => 'ᄂ',
  '㉢' => 'ᄃ',
  '㉣' => 'ᄅ',
  '㉤' => 'ᄆ',
  '㉥' => 'ᄇ',
  '㉦' => 'ᄉ',
  '㉧' => 'ᄋ',
  '㉨' => 'ᄌ',
  '㉩' => 'ᄎ',
  '㉪' => 'ᄏ',
  '㉫' => 'ᄐ',
  '㉬' => 'ᄑ',
  '㉭' => 'ᄒ',
  '㉮' => '가',
  '㉯' => '나',
  '㉰' => '다',
  '㉱' => '라',
  '㉲' => '마',
  '㉳' => '바',
  '㉴' => '사',
  '㉵' => '아',
  '㉶' => '자',
  '㉷' => '차',
  '㉸' => '카',
  '㉹' => '타',
  '㉺' => '파',
  '㉻' => '하',
  '㉼' => '참고',
  '㉽' => '주의',
  '㉾' => '우',
  '㊀' => '一',
  '㊁' => '二',
  '㊂' => '三',
  '㊃' => '四',
  '㊄' => '五',
  '㊅' => '六',
  '㊆' => '七',
  '㊇' => '八',
  '㊈' => '九',
  '㊉' => '十',
  '㊊' => '月',
  '㊋' => '火',
  '㊌' => '水',
  '㊍' => '木',
  '㊎' => '金',
  '㊏' => '土',
  '㊐' => '日',
  '㊑' => '株',
  '㊒' => '有',
  '㊓' => '社',
  '㊔' => '名',
  '㊕' => '特',
  '㊖' => '財',
  '㊗' => '祝',
  '㊘' => '労',
  '㊙' => '秘',
  '㊚' => '男',
  '㊛' => '女',
  '㊜' => '適',
  '㊝' => '優',
  '㊞' => '印',
  '㊟' => '注',
  '㊠' => '項',
  '㊡' => '休',
  '㊢' => '写',
  '㊣' => '正',
  '㊤' => '上',
  '㊥' => '中',
  '㊦' => '下',
  '㊧' => '左',
  '㊨' => '右',
  '㊩' => '医',
  '㊪' => '宗',
  '㊫' => '学',
  '㊬' => '監',
  '㊭' => '企',
  '㊮' => '資',
  '㊯' => '協',
  '㊰' => '夜',
  '㊱' => '36',
  '㊲' => '37',
  '㊳' => '38',
  '㊴' => '39',
  '㊵' => '40',
  '㊶' => '41',
  '㊷' => '42',
  '㊸' => '43',
  '㊹' => '44',
  '㊺' => '45',
  '㊻' => '46',
  '㊼' => '47',
  '㊽' => '48',
  '㊾' => '49',
  '㊿' => '50',
  '㋀' => '1月',
  '㋁' => '2月',
  '㋂' => '3月',
  '㋃' => '4月',
  '㋄' => '5月',
  '㋅' => '6月',
  '㋆' => '7月',
  '㋇' => '8月',
  '㋈' => '9月',
  '㋉' => '10月',
  '㋊' => '11月',
  '㋋' => '12月',
  '㋌' => 'Hg',
  '㋍' => 'erg',
  '㋎' => 'eV',
  '㋏' => 'LTD',
  '㋐' => 'ア',
  '㋑' => 'イ',
  '㋒' => 'ウ',
  '㋓' => 'エ',
  '㋔' => 'オ',
  '㋕' => 'カ',
  '㋖' => 'キ',
  '㋗' => 'ク',
  '㋘' => 'ケ',
  '㋙' => 'コ',
  '㋚' => 'サ',
  '㋛' => 'シ',
  '㋜' => 'ス',
  '㋝' => 'セ',
  '㋞' => 'ソ',
  '㋟' => 'タ',
  '㋠' => 'チ',
  '㋡' => 'ツ',
  '㋢' => 'テ',
  '㋣' => 'ト',
  '㋤' => 'ナ',
  '㋥' => 'ニ',
  '㋦' => 'ヌ',
  '㋧' => 'ネ',
  '㋨' => 'ノ',
  '㋩' => 'ハ',
  '㋪' => 'ヒ',
  '㋫' => 'フ',
  '㋬' => 'ヘ',
  '㋭' => 'ホ',
  '㋮' => 'マ',
  '㋯' => 'ミ',
  '㋰' => 'ム',
  '㋱' => 'メ',
  '㋲' => 'モ',
  '㋳' => 'ヤ',
  '㋴' => 'ユ',
  '㋵' => 'ヨ',
  '㋶' => 'ラ',
  '㋷' => 'リ',
  '㋸' => 'ル',
  '㋹' => 'レ',
  '㋺' => 'ロ',
  '㋻' => 'ワ',
  '㋼' => 'ヰ',
  '㋽' => 'ヱ',
  '㋾' => 'ヲ',
  '㋿' => '令和',
  '㌀' => 'アパート',
  '㌁' => 'アルファ',
  '㌂' => 'アンペア',
  '㌃' => 'アール',
  '㌄' => 'イニング',
  '㌅' => 'インチ',
  '㌆' => 'ウォン',
  '㌇' => 'エスクード',
  '㌈' => 'エーカー',
  '㌉' => 'オンス',
  '㌊' => 'オーム',
  '㌋' => 'カイリ',
  '㌌' => 'カラット',
  '㌍' => 'カロリー',
  '㌎' => 'ガロン',
  '㌏' => 'ガンマ',
  '㌐' => 'ギガ',
  '㌑' => 'ギニー',
  '㌒' => 'キュリー',
  '㌓' => 'ギルダー',
  '㌔' => 'キロ',
  '㌕' => 'キログラム',
  '㌖' => 'キロメートル',
  '㌗' => 'キロワット',
  '㌘' => 'グラム',
  '㌙' => 'グラムトン',
  '㌚' => 'クルゼイロ',
  '㌛' => 'クローネ',
  '㌜' => 'ケース',
  '㌝' => 'コルナ',
  '㌞' => 'コーポ',
  '㌟' => 'サイクル',
  '㌠' => 'サンチーム',
  '㌡' => 'シリング',
  '㌢' => 'センチ',
  '㌣' => 'セント',
  '㌤' => 'ダース',
  '㌥' => 'デシ',
  '㌦' => 'ドル',
  '㌧' => 'トン',
  '㌨' => 'ナノ',
  '㌩' => 'ノット',
  '㌪' => 'ハイツ',
  '㌫' => 'パーセント',
  '㌬' => 'パーツ',
  '㌭' => 'バーレル',
  '㌮' => 'ピアストル',
  '㌯' => 'ピクル',
  '㌰' => 'ピコ',
  '㌱' => 'ビル',
  '㌲' => 'ファラッド',
  '㌳' => 'フィート',
  '㌴' => 'ブッシェル',
  '㌵' => 'フラン',
  '㌶' => 'ヘクタール',
  '㌷' => 'ペソ',
  '㌸' => 'ペニヒ',
  '㌹' => 'ヘルツ',
  '㌺' => 'ペンス',
  '㌻' => 'ページ',
  '㌼' => 'ベータ',
  '㌽' => 'ポイント',
  '㌾' => 'ボルト',
  '㌿' => 'ホン',
  '㍀' => 'ポンド',
  '㍁' => 'ホール',
  '㍂' => 'ホーン',
  '㍃' => 'マイクロ',
  '㍄' => 'マイル',
  '㍅' => 'マッハ',
  '㍆' => 'マルク',
  '㍇' => 'マンション',
  '㍈' => 'ミクロン',
  '㍉' => 'ミリ',
  '㍊' => 'ミリバール',
  '㍋' => 'メガ',
  '㍌' => 'メガトン',
  '㍍' => 'メートル',
  '㍎' => 'ヤード',
  '㍏' => 'ヤール',
  '㍐' => 'ユアン',
  '㍑' => 'リットル',
  '㍒' => 'リラ',
  '㍓' => 'ルピー',
  '㍔' => 'ルーブル',
  '㍕' => 'レム',
  '㍖' => 'レントゲン',
  '㍗' => 'ワット',
  '㍘' => '0点',
  '㍙' => '1点',
  '㍚' => '2点',
  '㍛' => '3点',
  '㍜' => '4点',
  '㍝' => '5点',
  '㍞' => '6点',
  '㍟' => '7点',
  '㍠' => '8点',
  '㍡' => '9点',
  '㍢' => '10点',
  '㍣' => '11点',
  '㍤' => '12点',
  '㍥' => '13点',
  '㍦' => '14点',
  '㍧' => '15点',
  '㍨' => '16点',
  '㍩' => '17点',
  '㍪' => '18点',
  '㍫' => '19点',
  '㍬' => '20点',
  '㍭' => '21点',
  '㍮' => '22点',
  '㍯' => '23点',
  '㍰' => '24点',
  '㍱' => 'hPa',
  '㍲' => 'da',
  '㍳' => 'AU',
  '㍴' => 'bar',
  '㍵' => 'oV',
  '㍶' => 'pc',
  '㍷' => 'dm',
  '㍸' => 'dm2',
  '㍹' => 'dm3',
  '㍺' => 'IU',
  '㍻' => '平成',
  '㍼' => '昭和',
  '㍽' => '大正',
  '㍾' => '明治',
  '㍿' => '株式会社',
  '㎀' => 'pA',
  '㎁' => 'nA',
  '㎂' => 'μA',
  '㎃' => 'mA',
  '㎄' => 'kA',
  '㎅' => 'KB',
  '㎆' => 'MB',
  '㎇' => 'GB',
  '㎈' => 'cal',
  '㎉' => 'kcal',
  '㎊' => 'pF',
  '㎋' => 'nF',
  '㎌' => 'μF',
  '㎍' => 'μg',
  '㎎' => 'mg',
  '㎏' => 'kg',
  '㎐' => 'Hz',
  '㎑' => 'kHz',
  '㎒' => 'MHz',
  '㎓' => 'GHz',
  '㎔' => 'THz',
  '㎕' => 'μl',
  '㎖' => 'ml',
  '㎗' => 'dl',
  '㎘' => 'kl',
  '㎙' => 'fm',
  '㎚' => 'nm',
  '㎛' => 'μm',
  '㎜' => 'mm',
  '㎝' => 'cm',
  '㎞' => 'km',
  '㎟' => 'mm2',
  '㎠' => 'cm2',
  '㎡' => 'm2',
  '㎢' => 'km2',
  '㎣' => 'mm3',
  '㎤' => 'cm3',
  '㎥' => 'm3',
  '㎦' => 'km3',
  '㎧' => 'm∕s',
  '㎨' => 'm∕s2',
  '㎩' => 'Pa',
  '㎪' => 'kPa',
  '㎫' => 'MPa',
  '㎬' => 'GPa',
  '㎭' => 'rad',
  '㎮' => 'rad∕s',
  '㎯' => 'rad∕s2',
  '㎰' => 'ps',
  '㎱' => 'ns',
  '㎲' => 'μs',
  '㎳' => 'ms',
  '㎴' => 'pV',
  '㎵' => 'nV',
  '㎶' => 'μV',
  '㎷' => 'mV',
  '㎸' => 'kV',
  '㎹' => 'MV',
  '㎺' => 'pW',
  '㎻' => 'nW',
  '㎼' => 'μW',
  '㎽' => 'mW',
  '㎾' => 'kW',
  '㎿' => 'MW',
  '㏀' => 'kΩ',
  '㏁' => 'MΩ',
  '㏂' => 'a.m.',
  '㏃' => 'Bq',
  '㏄' => 'cc',
  '㏅' => 'cd',
  '㏆' => 'C∕kg',
  '㏇' => 'Co.',
  '㏈' => 'dB',
  '㏉' => 'Gy',
  '㏊' => 'ha',
  '㏋' => 'HP',
  '㏌' => 'in',
  '㏍' => 'KK',
  '㏎' => 'KM',
  '㏏' => 'kt',
  '㏐' => 'lm',
  '㏑' => 'ln',
  '㏒' => 'log',
  '㏓' => 'lx',
  '㏔' => 'mb',
  '㏕' => 'mil',
  '㏖' => 'mol',
  '㏗' => 'PH',
  '㏘' => 'p.m.',
  '㏙' => 'PPM',
  '㏚' => 'PR',
  '㏛' => 'sr',
  '㏜' => 'Sv',
  '㏝' => 'Wb',
  '㏞' => 'V∕m',
  '㏟' => 'A∕m',
  '㏠' => '1日',
  '㏡' => '2日',
  '㏢' => '3日',
  '㏣' => '4日',
  '㏤' => '5日',
  '㏥' => '6日',
  '㏦' => '7日',
  '㏧' => '8日',
  '㏨' => '9日',
  '㏩' => '10日',
  '㏪' => '11日',
  '㏫' => '12日',
  '㏬' => '13日',
  '㏭' => '14日',
  '㏮' => '15日',
  '㏯' => '16日',
  '㏰' => '17日',
  '㏱' => '18日',
  '㏲' => '19日',
  '㏳' => '20日',
  '㏴' => '21日',
  '㏵' => '22日',
  '㏶' => '23日',
  '㏷' => '24日',
  '㏸' => '25日',
  '㏹' => '26日',
  '㏺' => '27日',
  '㏻' => '28日',
  '㏼' => '29日',
  '㏽' => '30日',
  '㏾' => '31日',
  '㏿' => 'gal',
  'ꚜ' => 'ъ',
  'ꚝ' => 'ь',
  'ꝰ' => 'ꝯ',
  'ꟸ' => 'Ħ',
  'ꟹ' => 'œ',
  'ꭜ' => 'ꜧ',
  'ꭝ' => 'ꬷ',
  'ꭞ' => 'ɫ',
  'ꭟ' => 'ꭒ',
  'ꭩ' => 'ʍ',
  'ﬀ' => 'ff',
  'ﬁ' => 'fi',
  'ﬂ' => 'fl',
  'ﬃ' => 'ffi',
  'ﬄ' => 'ffl',
  'ﬅ' => 'st',
  'ﬆ' => 'st',
  'ﬓ' => 'մն',
  'ﬔ' => 'մե',
  'ﬕ' => 'մի',
  'ﬖ' => 'վն',
  'ﬗ' => 'մխ',
  'ﬠ' => 'ע',
  'ﬡ' => 'א',
  'ﬢ' => 'ד',
  'ﬣ' => 'ה',
  'ﬤ' => 'כ',
  'ﬥ' => 'ל',
  'ﬦ' => 'ם',
  'ﬧ' => 'ר',
  'ﬨ' => 'ת',
  '﬩' => '+',
  'ﭏ' => 'אל',
  'ﭐ' => 'ٱ',
  'ﭑ' => 'ٱ',
  'ﭒ' => 'ٻ',
  'ﭓ' => 'ٻ',
  'ﭔ' => 'ٻ',
  'ﭕ' => 'ٻ',
  'ﭖ' => 'پ',
  'ﭗ' => 'پ',
  'ﭘ' => 'پ',
  'ﭙ' => 'پ',
  'ﭚ' => 'ڀ',
  'ﭛ' => 'ڀ',
  'ﭜ' => 'ڀ',
  'ﭝ' => 'ڀ',
  'ﭞ' => 'ٺ',
  'ﭟ' => 'ٺ',
  'ﭠ' => 'ٺ',
  'ﭡ' => 'ٺ',
  'ﭢ' => 'ٿ',
  'ﭣ' => 'ٿ',
  'ﭤ' => 'ٿ',
  'ﭥ' => 'ٿ',
  'ﭦ' => 'ٹ',
  'ﭧ' => 'ٹ',
  'ﭨ' => 'ٹ',
  'ﭩ' => 'ٹ',
  'ﭪ' => 'ڤ',
  'ﭫ' => 'ڤ',
  'ﭬ' => 'ڤ',
  'ﭭ' => 'ڤ',
  'ﭮ' => 'ڦ',
  'ﭯ' => 'ڦ',
  'ﭰ' => 'ڦ',
  'ﭱ' => 'ڦ',
  'ﭲ' => 'ڄ',
  'ﭳ' => 'ڄ',
  'ﭴ' => 'ڄ',
  'ﭵ' => 'ڄ',
  'ﭶ' => 'ڃ',
  'ﭷ' => 'ڃ',
  'ﭸ' => 'ڃ',
  'ﭹ' => 'ڃ',
  'ﭺ' => 'چ',
  'ﭻ' => 'چ',
  'ﭼ' => 'چ',
  'ﭽ' => 'چ',
  'ﭾ' => 'ڇ',
  'ﭿ' => 'ڇ',
  'ﮀ' => 'ڇ',
  'ﮁ' => 'ڇ',
  'ﮂ' => 'ڍ',
  'ﮃ' => 'ڍ',
  'ﮄ' => 'ڌ',
  'ﮅ' => 'ڌ',
  'ﮆ' => 'ڎ',
  'ﮇ' => 'ڎ',
  'ﮈ' => 'ڈ',
  'ﮉ' => 'ڈ',
  'ﮊ' => 'ژ',
  'ﮋ' => 'ژ',
  'ﮌ' => 'ڑ',
  'ﮍ' => 'ڑ',
  'ﮎ' => 'ک',
  'ﮏ' => 'ک',
  'ﮐ' => 'ک',
  'ﮑ' => 'ک',
  'ﮒ' => 'گ',
  'ﮓ' => 'گ',
  'ﮔ' => 'گ',
  'ﮕ' => 'گ',
  'ﮖ' => 'ڳ',
  'ﮗ' => 'ڳ',
  'ﮘ' => 'ڳ',
  'ﮙ' => 'ڳ',
  'ﮚ' => 'ڱ',
  'ﮛ' => 'ڱ',
  'ﮜ' => 'ڱ',
  'ﮝ' => 'ڱ',
  'ﮞ' => 'ں',
  'ﮟ' => 'ں',
  'ﮠ' => 'ڻ',
  'ﮡ' => 'ڻ',
  'ﮢ' => 'ڻ',
  'ﮣ' => 'ڻ',
  'ﮤ' => 'ۀ',
  'ﮥ' => 'ۀ',
  'ﮦ' => 'ہ',
  'ﮧ' => 'ہ',
  'ﮨ' => 'ہ',
  'ﮩ' => 'ہ',
  'ﮪ' => 'ھ',
  'ﮫ' => 'ھ',
  'ﮬ' => 'ھ',
  'ﮭ' => 'ھ',
  'ﮮ' => 'ے',
  'ﮯ' => 'ے',
  'ﮰ' => 'ۓ',
  'ﮱ' => 'ۓ',
  'ﯓ' => 'ڭ',
  'ﯔ' => 'ڭ',
  'ﯕ' => 'ڭ',
  'ﯖ' => 'ڭ',
  'ﯗ' => 'ۇ',
  'ﯘ' => 'ۇ',
  'ﯙ' => 'ۆ',
  'ﯚ' => 'ۆ',
  'ﯛ' => 'ۈ',
  'ﯜ' => 'ۈ',
  'ﯝ' => 'ۇٴ',
  'ﯞ' => 'ۋ',
  'ﯟ' => 'ۋ',
  'ﯠ' => 'ۅ',
  'ﯡ' => 'ۅ',
  'ﯢ' => 'ۉ',
  'ﯣ' => 'ۉ',
  'ﯤ' => 'ې',
  'ﯥ' => 'ې',
  'ﯦ' => 'ې',
  'ﯧ' => 'ې',
  'ﯨ' => 'ى',
  'ﯩ' => 'ى',
  'ﯪ' => 'ئا',
  'ﯫ' => 'ئا',
  'ﯬ' => 'ئە',
  'ﯭ' => 'ئە',
  'ﯮ' => 'ئو',
  'ﯯ' => 'ئو',
  'ﯰ' => 'ئۇ',
  'ﯱ' => 'ئۇ',
  'ﯲ' => 'ئۆ',
  'ﯳ' => 'ئۆ',
  'ﯴ' => 'ئۈ',
  'ﯵ' => 'ئۈ',
  'ﯶ' => 'ئې',
  'ﯷ' => 'ئې',
  'ﯸ' => 'ئې',
  'ﯹ' => 'ئى',
  'ﯺ' => 'ئى',
  'ﯻ' => 'ئى',
  'ﯼ' => 'ی',
  'ﯽ' => 'ی',
  'ﯾ' => 'ی',
  'ﯿ' => 'ی',
  'ﰀ' => 'ئج',
  'ﰁ' => 'ئح',
  'ﰂ' => 'ئم',
  'ﰃ' => 'ئى',
  'ﰄ' => 'ئي',
  'ﰅ' => 'بج',
  'ﰆ' => 'بح',
  'ﰇ' => 'بخ',
  'ﰈ' => 'بم',
  'ﰉ' => 'بى',
  'ﰊ' => 'بي',
  'ﰋ' => 'تج',
  'ﰌ' => 'تح',
  'ﰍ' => 'تخ',
  'ﰎ' => 'تم',
  'ﰏ' => 'تى',
  'ﰐ' => 'تي',
  'ﰑ' => 'ثج',
  'ﰒ' => 'ثم',
  'ﰓ' => 'ثى',
  'ﰔ' => 'ثي',
  'ﰕ' => 'جح',
  'ﰖ' => 'جم',
  'ﰗ' => 'حج',
  'ﰘ' => 'حم',
  'ﰙ' => 'خج',
  'ﰚ' => 'خح',
  'ﰛ' => 'خم',
  'ﰜ' => 'سج',
  'ﰝ' => 'سح',
  'ﰞ' => 'سخ',
  'ﰟ' => 'سم',
  'ﰠ' => 'صح',
  'ﰡ' => 'صم',
  'ﰢ' => 'ضج',
  'ﰣ' => 'ضح',
  'ﰤ' => 'ضخ',
  'ﰥ' => 'ضم',
  'ﰦ' => 'طح',
  'ﰧ' => 'طم',
  'ﰨ' => 'ظم',
  'ﰩ' => 'عج',
  'ﰪ' => 'عم',
  'ﰫ' => 'غج',
  'ﰬ' => 'غم',
  'ﰭ' => 'فج',
  'ﰮ' => 'فح',
  'ﰯ' => 'فخ',
  'ﰰ' => 'فم',
  'ﰱ' => 'فى',
  'ﰲ' => 'في',
  'ﰳ' => 'قح',
  'ﰴ' => 'قم',
  'ﰵ' => 'قى',
  'ﰶ' => 'قي',
  'ﰷ' => 'كا',
  'ﰸ' => 'كج',
  'ﰹ' => 'كح',
  'ﰺ' => 'كخ',
  'ﰻ' => 'كل',
  'ﰼ' => 'كم',
  'ﰽ' => 'كى',
  'ﰾ' => 'كي',
  'ﰿ' => 'لج',
  'ﱀ' => 'لح',
  'ﱁ' => 'لخ',
  'ﱂ' => 'لم',
  'ﱃ' => 'لى',
  'ﱄ' => 'لي',
  'ﱅ' => 'مج',
  'ﱆ' => 'مح',
  'ﱇ' => 'مخ',
  'ﱈ' => 'مم',
  'ﱉ' => 'مى',
  'ﱊ' => 'مي',
  'ﱋ' => 'نج',
  'ﱌ' => 'نح',
  'ﱍ' => 'نخ',
  'ﱎ' => 'نم',
  'ﱏ' => 'نى',
  'ﱐ' => 'ني',
  'ﱑ' => 'هج',
  'ﱒ' => 'هم',
  'ﱓ' => 'هى',
  'ﱔ' => 'هي',
  'ﱕ' => 'يج',
  'ﱖ' => 'يح',
  'ﱗ' => 'يخ',
  'ﱘ' => 'يم',
  'ﱙ' => 'يى',
  'ﱚ' => 'يي',
  'ﱛ' => 'ذٰ',
  'ﱜ' => 'رٰ',
  'ﱝ' => 'ىٰ',
  'ﱞ' => ' ٌّ',
  'ﱟ' => ' ٍّ',
  'ﱠ' => ' َّ',
  'ﱡ' => ' ُّ',
  'ﱢ' => ' ِّ',
  'ﱣ' => ' ّٰ',
  'ﱤ' => 'ئر',
  'ﱥ' => 'ئز',
  'ﱦ' => 'ئم',
  'ﱧ' => 'ئن',
  'ﱨ' => 'ئى',
  'ﱩ' => 'ئي',
  'ﱪ' => 'بر',
  'ﱫ' => 'بز',
  'ﱬ' => 'بم',
  'ﱭ' => 'بن',
  'ﱮ' => 'بى',
  'ﱯ' => 'بي',
  'ﱰ' => 'تر',
  'ﱱ' => 'تز',
  'ﱲ' => 'تم',
  'ﱳ' => 'تن',
  'ﱴ' => 'تى',
  'ﱵ' => 'تي',
  'ﱶ' => 'ثر',
  'ﱷ' => 'ثز',
  'ﱸ' => 'ثم',
  'ﱹ' => 'ثن',
  'ﱺ' => 'ثى',
  'ﱻ' => 'ثي',
  'ﱼ' => 'فى',
  'ﱽ' => 'في',
  'ﱾ' => 'قى',
  'ﱿ' => 'قي',
  'ﲀ' => 'كا',
  'ﲁ' => 'كل',
  'ﲂ' => 'كم',
  'ﲃ' => 'كى',
  'ﲄ' => 'كي',
  'ﲅ' => 'لم',
  'ﲆ' => 'لى',
  'ﲇ' => 'لي',
  'ﲈ' => 'ما',
  'ﲉ' => 'مم',
  'ﲊ' => 'نر',
  'ﲋ' => 'نز',
  'ﲌ' => 'نم',
  'ﲍ' => 'نن',
  'ﲎ' => 'نى',
  'ﲏ' => 'ني',
  'ﲐ' => 'ىٰ',
  'ﲑ' => 'ير',
  'ﲒ' => 'يز',
  'ﲓ' => 'يم',
  'ﲔ' => 'ين',
  'ﲕ' => 'يى',
  'ﲖ' => 'يي',
  'ﲗ' => 'ئج',
  'ﲘ' => 'ئح',
  'ﲙ' => 'ئخ',
  'ﲚ' => 'ئم',
  'ﲛ' => 'ئه',
  'ﲜ' => 'بج',
  'ﲝ' => 'بح',
  'ﲞ' => 'بخ',
  'ﲟ' => 'بم',
  'ﲠ' => 'به',
  'ﲡ' => 'تج',
  'ﲢ' => 'تح',
  'ﲣ' => 'تخ',
  'ﲤ' => 'تم',
  'ﲥ' => 'ته',
  'ﲦ' => 'ثم',
  'ﲧ' => 'جح',
  'ﲨ' => 'جم',
  'ﲩ' => 'حج',
  'ﲪ' => 'حم',
  'ﲫ' => 'خج',
  'ﲬ' => 'خم',
  'ﲭ' => 'سج',
  'ﲮ' => 'سح',
  'ﲯ' => 'سخ',
  'ﲰ' => 'سم',
  'ﲱ' => 'صح',
  'ﲲ' => 'صخ',
  'ﲳ' => 'صم',
  'ﲴ' => 'ضج',
  'ﲵ' => 'ضح',
  'ﲶ' => 'ضخ',
  'ﲷ' => 'ضم',
  'ﲸ' => 'طح',
  'ﲹ' => 'ظم',
  'ﲺ' => 'عج',
  'ﲻ' => 'عم',
  'ﲼ' => 'غج',
  'ﲽ' => 'غم',
  'ﲾ' => 'فج',
  'ﲿ' => 'فح',
  'ﳀ' => 'فخ',
  'ﳁ' => 'فم',
  'ﳂ' => 'قح',
  'ﳃ' => 'قم',
  'ﳄ' => 'كج',
  'ﳅ' => 'كح',
  'ﳆ' => 'كخ',
  'ﳇ' => 'كل',
  'ﳈ' => 'كم',
  'ﳉ' => 'لج',
  'ﳊ' => 'لح',
  'ﳋ' => 'لخ',
  'ﳌ' => 'لم',
  'ﳍ' => 'له',
  'ﳎ' => 'مج',
  'ﳏ' => 'مح',
  'ﳐ' => 'مخ',
  'ﳑ' => 'مم',
  'ﳒ' => 'نج',
  'ﳓ' => 'نح',
  'ﳔ' => 'نخ',
  'ﳕ' => 'نم',
  'ﳖ' => 'نه',
  'ﳗ' => 'هج',
  'ﳘ' => 'هم',
  'ﳙ' => 'هٰ',
  'ﳚ' => 'يج',
  'ﳛ' => 'يح',
  'ﳜ' => 'يخ',
  'ﳝ' => 'يم',
  'ﳞ' => 'يه',
  'ﳟ' => 'ئم',
  'ﳠ' => 'ئه',
  'ﳡ' => 'بم',
  'ﳢ' => 'به',
  'ﳣ' => 'تم',
  'ﳤ' => 'ته',
  'ﳥ' => 'ثم',
  'ﳦ' => 'ثه',
  'ﳧ' => 'سم',
  'ﳨ' => 'سه',
  'ﳩ' => 'شم',
  'ﳪ' => 'شه',
  'ﳫ' => 'كل',
  'ﳬ' => 'كم',
  'ﳭ' => 'لم',
  'ﳮ' => 'نم',
  'ﳯ' => 'نه',
  'ﳰ' => 'يم',
  'ﳱ' => 'يه',
  'ﳲ' => 'ـَّ',
  'ﳳ' => 'ـُّ',
  'ﳴ' => 'ـِّ',
  'ﳵ' => 'طى',
  'ﳶ' => 'طي',
  'ﳷ' => 'عى',
  'ﳸ' => 'عي',
  'ﳹ' => 'غى',
  'ﳺ' => 'غي',
  'ﳻ' => 'سى',
  'ﳼ' => 'سي',
  'ﳽ' => 'شى',
  'ﳾ' => 'شي',
  'ﳿ' => 'حى',
  'ﴀ' => 'حي',
  'ﴁ' => 'جى',
  'ﴂ' => 'جي',
  'ﴃ' => 'خى',
  'ﴄ' => 'خي',
  'ﴅ' => 'صى',
  'ﴆ' => 'صي',
  'ﴇ' => 'ضى',
  'ﴈ' => 'ضي',
  'ﴉ' => 'شج',
  'ﴊ' => 'شح',
  'ﴋ' => 'شخ',
  'ﴌ' => 'شم',
  'ﴍ' => 'شر',
  'ﴎ' => 'سر',
  'ﴏ' => 'صر',
  'ﴐ' => 'ضر',
  'ﴑ' => 'طى',
  'ﴒ' => 'طي',
  'ﴓ' => 'عى',
  'ﴔ' => 'عي',
  'ﴕ' => 'غى',
  'ﴖ' => 'غي',
  'ﴗ' => 'سى',
  'ﴘ' => 'سي',
  'ﴙ' => 'شى',
  'ﴚ' => 'شي',
  'ﴛ' => 'حى',
  'ﴜ' => 'حي',
  'ﴝ' => 'جى',
  'ﴞ' => 'جي',
  'ﴟ' => 'خى',
  'ﴠ' => 'خي',
  'ﴡ' => 'صى',
  'ﴢ' => 'صي',
  'ﴣ' => 'ضى',
  'ﴤ' => 'ضي',
  'ﴥ' => 'شج',
  'ﴦ' => 'شح',
  'ﴧ' => 'شخ',
  'ﴨ' => 'شم',
  'ﴩ' => 'شر',
  'ﴪ' => 'سر',
  'ﴫ' => 'صر',
  'ﴬ' => 'ضر',
  'ﴭ' => 'شج',
  'ﴮ' => 'شح',
  'ﴯ' => 'شخ',
  'ﴰ' => 'شم',
  'ﴱ' => 'سه',
  'ﴲ' => 'شه',
  'ﴳ' => 'طم',
  'ﴴ' => 'سج',
  'ﴵ' => 'سح',
  'ﴶ' => 'سخ',
  'ﴷ' => 'شج',
  'ﴸ' => 'شح',
  'ﴹ' => 'شخ',
  'ﴺ' => 'طم',
  'ﴻ' => 'ظم',
  'ﴼ' => 'اً',
  'ﴽ' => 'اً',
  'ﵐ' => 'تجم',
  'ﵑ' => 'تحج',
  'ﵒ' => 'تحج',
  'ﵓ' => 'تحم',
  'ﵔ' => 'تخم',
  'ﵕ' => 'تمج',
  'ﵖ' => 'تمح',
  'ﵗ' => 'تمخ',
  'ﵘ' => 'جمح',
  'ﵙ' => 'جمح',
  'ﵚ' => 'حمي',
  'ﵛ' => 'حمى',
  'ﵜ' => 'سحج',
  'ﵝ' => 'سجح',
  'ﵞ' => 'سجى',
  'ﵟ' => 'سمح',
  'ﵠ' => 'سمح',
  'ﵡ' => 'سمج',
  'ﵢ' => 'سمم',
  'ﵣ' => 'سمم',
  'ﵤ' => 'صحح',
  'ﵥ' => 'صحح',
  'ﵦ' => 'صمم',
  'ﵧ' => 'شحم',
  'ﵨ' => 'شحم',
  'ﵩ' => 'شجي',
  'ﵪ' => 'شمخ',
  'ﵫ' => 'شمخ',
  'ﵬ' => 'شمم',
  'ﵭ' => 'شمم',
  'ﵮ' => 'ضحى',
  'ﵯ' => 'ضخم',
  'ﵰ' => 'ضخم',
  'ﵱ' => 'طمح',
  'ﵲ' => 'طمح',
  'ﵳ' => 'طمم',
  'ﵴ' => 'طمي',
  'ﵵ' => 'عجم',
  'ﵶ' => 'عمم',
  'ﵷ' => 'عمم',
  'ﵸ' => 'عمى',
  'ﵹ' => 'غمم',
  'ﵺ' => 'غمي',
  'ﵻ' => 'غمى',
  'ﵼ' => 'فخم',
  'ﵽ' => 'فخم',
  'ﵾ' => 'قمح',
  'ﵿ' => 'قمم',
  'ﶀ' => 'لحم',
  'ﶁ' => 'لحي',
  'ﶂ' => 'لحى',
  'ﶃ' => 'لجج',
  'ﶄ' => 'لجج',
  'ﶅ' => 'لخم',
  'ﶆ' => 'لخم',
  'ﶇ' => 'لمح',
  'ﶈ' => 'لمح',
  'ﶉ' => 'محج',
  'ﶊ' => 'محم',
  'ﶋ' => 'محي',
  'ﶌ' => 'مجح',
  'ﶍ' => 'مجم',
  'ﶎ' => 'مخج',
  'ﶏ' => 'مخم',
  'ﶒ' => 'مجخ',
  'ﶓ' => 'همج',
  'ﶔ' => 'همم',
  'ﶕ' => 'نحم',
  'ﶖ' => 'نحى',
  'ﶗ' => 'نجم',
  'ﶘ' => 'نجم',
  'ﶙ' => 'نجى',
  'ﶚ' => 'نمي',
  'ﶛ' => 'نمى',
  'ﶜ' => 'يمم',
  'ﶝ' => 'يمم',
  'ﶞ' => 'بخي',
  'ﶟ' => 'تجي',
  'ﶠ' => 'تجى',
  'ﶡ' => 'تخي',
  'ﶢ' => 'تخى',
  'ﶣ' => 'تمي',
  'ﶤ' => 'تمى',
  'ﶥ' => 'جمي',
  'ﶦ' => 'جحى',
  'ﶧ' => 'جمى',
  'ﶨ' => 'سخى',
  'ﶩ' => 'صحي',
  'ﶪ' => 'شحي',
  'ﶫ' => 'ضحي',
  'ﶬ' => 'لجي',
  'ﶭ' => 'لمي',
  'ﶮ' => 'يحي',
  'ﶯ' => 'يجي',
  'ﶰ' => 'يمي',
  'ﶱ' => 'ممي',
  'ﶲ' => 'قمي',
  'ﶳ' => 'نحي',
  'ﶴ' => 'قمح',
  'ﶵ' => 'لحم',
  'ﶶ' => 'عمي',
  'ﶷ' => 'كمي',
  'ﶸ' => 'نجح',
  'ﶹ' => 'مخي',
  'ﶺ' => 'لجم',
  'ﶻ' => 'كمم',
  'ﶼ' => 'لجم',
  'ﶽ' => 'نجح',
  'ﶾ' => 'جحي',
  'ﶿ' => 'حجي',
  'ﷀ' => 'مجي',
  'ﷁ' => 'فمي',
  'ﷂ' => 'بحي',
  'ﷃ' => 'كمم',
  'ﷄ' => 'عجم',
  'ﷅ' => 'صمم',
  'ﷆ' => 'سخي',
  'ﷇ' => 'نجي',
  'ﷰ' => 'صلے',
  'ﷱ' => 'قلے',
  'ﷲ' => 'الله',
  'ﷳ' => 'اكبر',
  'ﷴ' => 'محمد',
  'ﷵ' => 'صلعم',
  'ﷶ' => 'رسول',
  'ﷷ' => 'عليه',
  'ﷸ' => 'وسلم',
  'ﷹ' => 'صلى',
  'ﷺ' => 'صلى الله عليه وسلم',
  'ﷻ' => 'جل جلاله',
  '﷼' => 'ریال',
  '︐' => ',',
  '︑' => '、',
  '︒' => '。',
  '︓' => ':',
  '︔' => ';',
  '︕' => '!',
  '︖' => '?',
  '︗' => '〖',
  '︘' => '〗',
  '︙' => '...',
  '︰' => '..',
  '︱' => '—',
  '︲' => '–',
  '︳' => '_',
  '︴' => '_',
  '︵' => '(',
  '︶' => ')',
  '︷' => '{',
  '︸' => '}',
  '︹' => '〔',
  '︺' => '〕',
  '︻' => '【',
  '︼' => '】',
  '︽' => '《',
  '︾' => '》',
  '︿' => '〈',
  '﹀' => '〉',
  '﹁' => '「',
  '﹂' => '」',
  '﹃' => '『',
  '﹄' => '』',
  '﹇' => '[',
  '﹈' => ']',
  '﹉' => ' ̅',
  '﹊' => ' ̅',
  '﹋' => ' ̅',
  '﹌' => ' ̅',
  '﹍' => '_',
  '﹎' => '_',
  '﹏' => '_',
  '﹐' => ',',
  '﹑' => '、',
  '﹒' => '.',
  '﹔' => ';',
  '﹕' => ':',
  '﹖' => '?',
  '﹗' => '!',
  '﹘' => '—',
  '﹙' => '(',
  '﹚' => ')',
  '﹛' => '{',
  '﹜' => '}',
  '﹝' => '〔',
  '﹞' => '〕',
  '﹟' => '#',
  '﹠' => '&',
  '﹡' => '*',
  '﹢' => '+',
  '﹣' => '-',
  '﹤' => '<',
  '﹥' => '>',
  '﹦' => '=',
  '﹨' => '\\',
  '﹩' => '$',
  '﹪' => '%',
  '﹫' => '@',
  'ﹰ' => ' ً',
  'ﹱ' => 'ـً',
  'ﹲ' => ' ٌ',
  'ﹴ' => ' ٍ',
  'ﹶ' => ' َ',
  'ﹷ' => 'ـَ',
  'ﹸ' => ' ُ',
  'ﹹ' => 'ـُ',
  'ﹺ' => ' ِ',
  'ﹻ' => 'ـِ',
  'ﹼ' => ' ّ',
  'ﹽ' => 'ـّ',
  'ﹾ' => ' ْ',
  'ﹿ' => 'ـْ',
  'ﺀ' => 'ء',
  'ﺁ' => 'آ',
  'ﺂ' => 'آ',
  'ﺃ' => 'أ',
  'ﺄ' => 'أ',
  'ﺅ' => 'ؤ',
  'ﺆ' => 'ؤ',
  'ﺇ' => 'إ',
  'ﺈ' => 'إ',
  'ﺉ' => 'ئ',
  'ﺊ' => 'ئ',
  'ﺋ' => 'ئ',
  'ﺌ' => 'ئ',
  'ﺍ' => 'ا',
  'ﺎ' => 'ا',
  'ﺏ' => 'ب',
  'ﺐ' => 'ب',
  'ﺑ' => 'ب',
  'ﺒ' => 'ب',
  'ﺓ' => 'ة',
  'ﺔ' => 'ة',
  'ﺕ' => 'ت',
  'ﺖ' => 'ت',
  'ﺗ' => 'ت',
  'ﺘ' => 'ت',
  'ﺙ' => 'ث',
  'ﺚ' => 'ث',
  'ﺛ' => 'ث',
  'ﺜ' => 'ث',
  'ﺝ' => 'ج',
  'ﺞ' => 'ج',
  'ﺟ' => 'ج',
  'ﺠ' => 'ج',
  'ﺡ' => 'ح',
  'ﺢ' => 'ح',
  'ﺣ' => 'ح',
  'ﺤ' => 'ح',
  'ﺥ' => 'خ',
  'ﺦ' => 'خ',
  'ﺧ' => 'خ',
  'ﺨ' => 'خ',
  'ﺩ' => 'د',
  'ﺪ' => 'د',
  'ﺫ' => 'ذ',
  'ﺬ' => 'ذ',
  'ﺭ' => 'ر',
  'ﺮ' => 'ر',
  'ﺯ' => 'ز',
  'ﺰ' => 'ز',
  'ﺱ' => 'س',
  'ﺲ' => 'س',
  'ﺳ' => 'س',
  'ﺴ' => 'س',
  'ﺵ' => 'ش',
  'ﺶ' => 'ش',
  'ﺷ' => 'ش',
  'ﺸ' => 'ش',
  'ﺹ' => 'ص',
  'ﺺ' => 'ص',
  'ﺻ' => 'ص',
  'ﺼ' => 'ص',
  'ﺽ' => 'ض',
  'ﺾ' => 'ض',
  'ﺿ' => 'ض',
  'ﻀ' => 'ض',
  'ﻁ' => 'ط',
  'ﻂ' => 'ط',
  'ﻃ' => 'ط',
  'ﻄ' => 'ط',
  'ﻅ' => 'ظ',
  'ﻆ' => 'ظ',
  'ﻇ' => 'ظ',
  'ﻈ' => 'ظ',
  'ﻉ' => 'ع',
  'ﻊ' => 'ع',
  'ﻋ' => 'ع',
  'ﻌ' => 'ع',
  'ﻍ' => 'غ',
  'ﻎ' => 'غ',
  'ﻏ' => 'غ',
  'ﻐ' => 'غ',
  'ﻑ' => 'ف',
  'ﻒ' => 'ف',
  'ﻓ' => 'ف',
  'ﻔ' => 'ف',
  'ﻕ' => 'ق',
  'ﻖ' => 'ق',
  'ﻗ' => 'ق',
  'ﻘ' => 'ق',
  'ﻙ' => 'ك',
  'ﻚ' => 'ك',
  'ﻛ' => 'ك',
  'ﻜ' => 'ك',
  'ﻝ' => 'ل',
  'ﻞ' => 'ل',
  'ﻟ' => 'ل',
  'ﻠ' => 'ل',
  'ﻡ' => 'م',
  'ﻢ' => 'م',
  'ﻣ' => 'م',
  'ﻤ' => 'م',
  'ﻥ' => 'ن',
  'ﻦ' => 'ن',
  'ﻧ' => 'ن',
  'ﻨ' => 'ن',
  'ﻩ' => 'ه',
  'ﻪ' => 'ه',
  'ﻫ' => 'ه',
  'ﻬ' => 'ه',
  'ﻭ' => 'و',
  'ﻮ' => 'و',
  'ﻯ' => 'ى',
  'ﻰ' => 'ى',
  'ﻱ' => 'ي',
  'ﻲ' => 'ي',
  'ﻳ' => 'ي',
  'ﻴ' => 'ي',
  'ﻵ' => 'لآ',
  'ﻶ' => 'لآ',
  'ﻷ' => 'لأ',
  'ﻸ' => 'لأ',
  'ﻹ' => 'لإ',
  'ﻺ' => 'لإ',
  'ﻻ' => 'لا',
  'ﻼ' => 'لا',
  '！' => '!',
  '＂' => '"',
  '＃' => '#',
  '＄' => '$',
  '％' => '%',
  '＆' => '&',
  '＇' => '\'',
  '（' => '(',
  '）' => ')',
  '＊' => '*',
  '＋' => '+',
  '，' => ',',
  '－' => '-',
  '．' => '.',
  '／' => '/',
  '０' => '0',
  '１' => '1',
  '２' => '2',
  '３' => '3',
  '４' => '4',
  '５' => '5',
  '６' => '6',
  '７' => '7',
  '８' => '8',
  '９' => '9',
  '：' => ':',
  '；' => ';',
  '＜' => '<',
  '＝' => '=',
  '＞' => '>',
  '？' => '?',
  '＠' => '@',
  'Ａ' => 'A',
  'Ｂ' => 'B',
  'Ｃ' => 'C',
  'Ｄ' => 'D',
  'Ｅ' => 'E',
  'Ｆ' => 'F',
  'Ｇ' => 'G',
  'Ｈ' => 'H',
  'Ｉ' => 'I',
  'Ｊ' => 'J',
  'Ｋ' => 'K',
  'Ｌ' => 'L',
  'Ｍ' => 'M',
  'Ｎ' => 'N',
  'Ｏ' => 'O',
  'Ｐ' => 'P',
  'Ｑ' => 'Q',
  'Ｒ' => 'R',
  'Ｓ' => 'S',
  'Ｔ' => 'T',
  'Ｕ' => 'U',
  'Ｖ' => 'V',
  'Ｗ' => 'W',
  'Ｘ' => 'X',
  'Ｙ' => 'Y',
  'Ｚ' => 'Z',
  '［' => '[',
  '＼' => '\\',
  '］' => ']',
  '＾' => '^',
  '＿' => '_',
  '｀' => '`',
  'ａ' => 'a',
  'ｂ' => 'b',
  'ｃ' => 'c',
  'ｄ' => 'd',
  'ｅ' => 'e',
  'ｆ' => 'f',
  'ｇ' => 'g',
  'ｈ' => 'h',
  'ｉ' => 'i',
  'ｊ' => 'j',
  'ｋ' => 'k',
  'ｌ' => 'l',
  'ｍ' => 'm',
  'ｎ' => 'n',
  'ｏ' => 'o',
  'ｐ' => 'p',
  'ｑ' => 'q',
  'ｒ' => 'r',
  'ｓ' => 's',
  'ｔ' => 't',
  'ｕ' => 'u',
  'ｖ' => 'v',
  'ｗ' => 'w',
  'ｘ' => 'x',
  'ｙ' => 'y',
  'ｚ' => 'z',
  '｛' => '{',
  '｜' => '|',
  '｝' => '}',
  '～' => '~',
  '｟' => '⦅',
  '｠' => '⦆',
  '｡' => '。',
  '｢' => '「',
  '｣' => '」',
  '､' => '、',
  '･' => '・',
  'ｦ' => 'ヲ',
  'ｧ' => 'ァ',
  'ｨ' => 'ィ',
  'ｩ' => 'ゥ',
  'ｪ' => 'ェ',
  'ｫ' => 'ォ',
  'ｬ' => 'ャ',
  'ｭ' => 'ュ',
  'ｮ' => 'ョ',
  'ｯ' => 'ッ',
  'ｰ' => 'ー',
  'ｱ' => 'ア',
  'ｲ' => 'イ',
  'ｳ' => 'ウ',
  'ｴ' => 'エ',
  'ｵ' => 'オ',
  'ｶ' => 'カ',
  'ｷ' => 'キ',
  'ｸ' => 'ク',
  'ｹ' => 'ケ',
  'ｺ' => 'コ',
  'ｻ' => 'サ',
  'ｼ' => 'シ',
  'ｽ' => 'ス',
  'ｾ' => 'セ',
  'ｿ' => 'ソ',
  'ﾀ' => 'タ',
  'ﾁ' => 'チ',
  'ﾂ' => 'ツ',
  'ﾃ' => 'テ',
  'ﾄ' => 'ト',
  'ﾅ' => 'ナ',
  'ﾆ' => 'ニ',
  'ﾇ' => 'ヌ',
  'ﾈ' => 'ネ',
  'ﾉ' => 'ノ',
  'ﾊ' => 'ハ',
  'ﾋ' => 'ヒ',
  'ﾌ' => 'フ',
  'ﾍ' => 'ヘ',
  'ﾎ' => 'ホ',
  'ﾏ' => 'マ',
  'ﾐ' => 'ミ',
  'ﾑ' => 'ム',
  'ﾒ' => 'メ',
  'ﾓ' => 'モ',
  'ﾔ' => 'ヤ',
  'ﾕ' => 'ユ',
  'ﾖ' => 'ヨ',
  'ﾗ' => 'ラ',
  'ﾘ' => 'リ',
  'ﾙ' => 'ル',
  'ﾚ' => 'レ',
  'ﾛ' => 'ロ',
  'ﾜ' => 'ワ',
  'ﾝ' => 'ン',
  'ﾞ' => '゙',
  'ﾟ' => '゚',
  'ﾠ' => 'ᅠ',
  'ﾡ' => 'ᄀ',
  'ﾢ' => 'ᄁ',
  'ﾣ' => 'ᆪ',
  'ﾤ' => 'ᄂ',
  'ﾥ' => 'ᆬ',
  'ﾦ' => 'ᆭ',
  'ﾧ' => 'ᄃ',
  'ﾨ' => 'ᄄ',
  'ﾩ' => 'ᄅ',
  'ﾪ' => 'ᆰ',
  'ﾫ' => 'ᆱ',
  'ﾬ' => 'ᆲ',
  'ﾭ' => 'ᆳ',
  'ﾮ' => 'ᆴ',
  'ﾯ' => 'ᆵ',
  'ﾰ' => 'ᄚ',
  'ﾱ' => 'ᄆ',
  'ﾲ' => 'ᄇ',
  'ﾳ' => 'ᄈ',
  'ﾴ' => 'ᄡ',
  'ﾵ' => 'ᄉ',
  'ﾶ' => 'ᄊ',
  'ﾷ' => 'ᄋ',
  'ﾸ' => 'ᄌ',
  'ﾹ' => 'ᄍ',
  'ﾺ' => 'ᄎ',
  'ﾻ' => 'ᄏ',
  'ﾼ' => 'ᄐ',
  'ﾽ' => 'ᄑ',
  'ﾾ' => 'ᄒ',
  'ￂ' => 'ᅡ',
  'ￃ' => 'ᅢ',
  'ￄ' => 'ᅣ',
  'ￅ' => 'ᅤ',
  'ￆ' => 'ᅥ',
  'ￇ' => 'ᅦ',
  'ￊ' => 'ᅧ',
  'ￋ' => 'ᅨ',
  'ￌ' => 'ᅩ',
  'ￍ' => 'ᅪ',
  'ￎ' => 'ᅫ',
  'ￏ' => 'ᅬ',
  'ￒ' => 'ᅭ',
  'ￓ' => 'ᅮ',
  'ￔ' => 'ᅯ',
  'ￕ' => 'ᅰ',
  'ￖ' => 'ᅱ',
  'ￗ' => 'ᅲ',
  'ￚ' => 'ᅳ',
  'ￛ' => 'ᅴ',
  'ￜ' => 'ᅵ',
  '￠' => '¢',
  '￡' => '£',
  '￢' => '¬',
  '￣' => ' ̄',
  '￤' => '¦',
  '￥' => '¥',
  '￦' => '₩',
  '￨' => '│',
  '￩' => '←',
  '￪' => '↑',
  '￫' => '→',
  '￬' => '↓',
  '￭' => '■',
  '￮' => '○',
  '𝐀' => 'A',
  '𝐁' => 'B',
  '𝐂' => 'C',
  '𝐃' => 'D',
  '𝐄' => 'E',
  '𝐅' => 'F',
  '𝐆' => 'G',
  '𝐇' => 'H',
  '𝐈' => 'I',
  '𝐉' => 'J',
  '𝐊' => 'K',
  '𝐋' => 'L',
  '𝐌' => 'M',
  '𝐍' => 'N',
  '𝐎' => 'O',
  '𝐏' => 'P',
  '𝐐' => 'Q',
  '𝐑' => 'R',
  '𝐒' => 'S',
  '𝐓' => 'T',
  '𝐔' => 'U',
  '𝐕' => 'V',
  '𝐖' => 'W',
  '𝐗' => 'X',
  '𝐘' => 'Y',
  '𝐙' => 'Z',
  '𝐚' => 'a',
  '𝐛' => 'b',
  '𝐜' => 'c',
  '𝐝' => 'd',
  '𝐞' => 'e',
  '𝐟' => 'f',
  '𝐠' => 'g',
  '𝐡' => 'h',
  '𝐢' => 'i',
  '𝐣' => 'j',
  '𝐤' => 'k',
  '𝐥' => 'l',
  '𝐦' => 'm',
  '𝐧' => 'n',
  '𝐨' => 'o',
  '𝐩' => 'p',
  '𝐪' => 'q',
  '𝐫' => 'r',
  '𝐬' => 's',
  '𝐭' => 't',
  '𝐮' => 'u',
  '𝐯' => 'v',
  '𝐰' => 'w',
  '𝐱' => 'x',
  '𝐲' => 'y',
  '𝐳' => 'z',
  '𝐴' => 'A',
  '𝐵' => 'B',
  '𝐶' => 'C',
  '𝐷' => 'D',
  '𝐸' => 'E',
  '𝐹' => 'F',
  '𝐺' => 'G',
  '𝐻' => 'H',
  '𝐼' => 'I',
  '𝐽' => 'J',
  '𝐾' => 'K',
  '𝐿' => 'L',
  '𝑀' => 'M',
  '𝑁' => 'N',
  '𝑂' => 'O',
  '𝑃' => 'P',
  '𝑄' => 'Q',
  '𝑅' => 'R',
  '𝑆' => 'S',
  '𝑇' => 'T',
  '𝑈' => 'U',
  '𝑉' => 'V',
  '𝑊' => 'W',
  '𝑋' => 'X',
  '𝑌' => 'Y',
  '𝑍' => 'Z',
  '𝑎' => 'a',
  '𝑏' => 'b',
  '𝑐' => 'c',
  '𝑑' => 'd',
  '𝑒' => 'e',
  '𝑓' => 'f',
  '𝑔' => 'g',
  '𝑖' => 'i',
  '𝑗' => 'j',
  '𝑘' => 'k',
  '𝑙' => 'l',
  '𝑚' => 'm',
  '𝑛' => 'n',
  '𝑜' => 'o',
  '𝑝' => 'p',
  '𝑞' => 'q',
  '𝑟' => 'r',
  '𝑠' => 's',
  '𝑡' => 't',
  '𝑢' => 'u',
  '𝑣' => 'v',
  '𝑤' => 'w',
  '𝑥' => 'x',
  '𝑦' => 'y',
  '𝑧' => 'z',
  '𝑨' => 'A',
  '𝑩' => 'B',
  '𝑪' => 'C',
  '𝑫' => 'D',
  '𝑬' => 'E',
  '𝑭' => 'F',
  '𝑮' => 'G',
  '𝑯' => 'H',
  '𝑰' => 'I',
  '𝑱' => 'J',
  '𝑲' => 'K',
  '𝑳' => 'L',
  '𝑴' => 'M',
  '𝑵' => 'N',
  '𝑶' => 'O',
  '𝑷' => 'P',
  '𝑸' => 'Q',
  '𝑹' => 'R',
  '𝑺' => 'S',
  '𝑻' => 'T',
  '𝑼' => 'U',
  '𝑽' => 'V',
  '𝑾' => 'W',
  '𝑿' => 'X',
  '𝒀' => 'Y',
  '𝒁' => 'Z',
  '𝒂' => 'a',
  '𝒃' => 'b',
  '𝒄' => 'c',
  '𝒅' => 'd',
  '𝒆' => 'e',
  '𝒇' => 'f',
  '𝒈' => 'g',
  '𝒉' => 'h',
  '𝒊' => 'i',
  '𝒋' => 'j',
  '𝒌' => 'k',
  '𝒍' => 'l',
  '𝒎' => 'm',
  '𝒏' => 'n',
  '𝒐' => 'o',
  '𝒑' => 'p',
  '𝒒' => 'q',
  '𝒓' => 'r',
  '𝒔' => 's',
  '𝒕' => 't',
  '𝒖' => 'u',
  '𝒗' => 'v',
  '𝒘' => 'w',
  '𝒙' => 'x',
  '𝒚' => 'y',
  '𝒛' => 'z',
  '𝒜' => 'A',
  '𝒞' => 'C',
  '𝒟' => 'D',
  '𝒢' => 'G',
  '𝒥' => 'J',
  '𝒦' => 'K',
  '𝒩' => 'N',
  '𝒪' => 'O',
  '𝒫' => 'P',
  '𝒬' => 'Q',
  '𝒮' => 'S',
  '𝒯' => 'T',
  '𝒰' => 'U',
  '𝒱' => 'V',
  '𝒲' => 'W',
  '𝒳' => 'X',
  '𝒴' => 'Y',
  '𝒵' => 'Z',
  '𝒶' => 'a',
  '𝒷' => 'b',
  '𝒸' => 'c',
  '𝒹' => 'd',
  '𝒻' => 'f',
  '𝒽' => 'h',
  '𝒾' => 'i',
  '𝒿' => 'j',
  '𝓀' => 'k',
  '𝓁' => 'l',
  '𝓂' => 'm',
  '𝓃' => 'n',
  '𝓅' => 'p',
  '𝓆' => 'q',
  '𝓇' => 'r',
  '𝓈' => 's',
  '𝓉' => 't',
  '𝓊' => 'u',
  '𝓋' => 'v',
  '𝓌' => 'w',
  '𝓍' => 'x',
  '𝓎' => 'y',
  '𝓏' => 'z',
  '𝓐' => 'A',
  '𝓑' => 'B',
  '𝓒' => 'C',
  '𝓓' => 'D',
  '𝓔' => 'E',
  '𝓕' => 'F',
  '𝓖' => 'G',
  '𝓗' => 'H',
  '𝓘' => 'I',
  '𝓙' => 'J',
  '𝓚' => 'K',
  '𝓛' => 'L',
  '𝓜' => 'M',
  '𝓝' => 'N',
  '𝓞' => 'O',
  '𝓟' => 'P',
  '𝓠' => 'Q',
  '𝓡' => 'R',
  '𝓢' => 'S',
  '𝓣' => 'T',
  '𝓤' => 'U',
  '𝓥' => 'V',
  '𝓦' => 'W',
  '𝓧' => 'X',
  '𝓨' => 'Y',
  '𝓩' => 'Z',
  '𝓪' => 'a',
  '𝓫' => 'b',
  '𝓬' => 'c',
  '𝓭' => 'd',
  '𝓮' => 'e',
  '𝓯' => 'f',
  '𝓰' => 'g',
  '𝓱' => 'h',
  '𝓲' => 'i',
  '𝓳' => 'j',
  '𝓴' => 'k',
  '𝓵' => 'l',
  '𝓶' => 'm',
  '𝓷' => 'n',
  '𝓸' => 'o',
  '𝓹' => 'p',
  '𝓺' => 'q',
  '𝓻' => 'r',
  '𝓼' => 's',
  '𝓽' => 't',
  '𝓾' => 'u',
  '𝓿' => 'v',
  '𝔀' => 'w',
  '𝔁' => 'x',
  '𝔂' => 'y',
  '𝔃' => 'z',
  '𝔄' => 'A',
  '𝔅' => 'B',
  '𝔇' => 'D',
  '𝔈' => 'E',
  '𝔉' => 'F',
  '𝔊' => 'G',
  '𝔍' => 'J',
  '𝔎' => 'K',
  '𝔏' => 'L',
  '𝔐' => 'M',
  '𝔑' => 'N',
  '𝔒' => 'O',
  '𝔓' => 'P',
  '𝔔' => 'Q',
  '𝔖' => 'S',
  '𝔗' => 'T',
  '𝔘' => 'U',
  '𝔙' => 'V',
  '𝔚' => 'W',
  '𝔛' => 'X',
  '𝔜' => 'Y',
  '𝔞' => 'a',
  '𝔟' => 'b',
  '𝔠' => 'c',
  '𝔡' => 'd',
  '𝔢' => 'e',
  '𝔣' => 'f',
  '𝔤' => 'g',
  '𝔥' => 'h',
  '𝔦' => 'i',
  '𝔧' => 'j',
  '𝔨' => 'k',
  '𝔩' => 'l',
  '𝔪' => 'm',
  '𝔫' => 'n',
  '𝔬' => 'o',
  '𝔭' => 'p',
  '𝔮' => 'q',
  '𝔯' => 'r',
  '𝔰' => 's',
  '𝔱' => 't',
  '𝔲' => 'u',
  '𝔳' => 'v',
  '𝔴' => 'w',
  '𝔵' => 'x',
  '𝔶' => 'y',
  '𝔷' => 'z',
  '𝔸' => 'A',
  '𝔹' => 'B',
  '𝔻' => 'D',
  '𝔼' => 'E',
  '𝔽' => 'F',
  '𝔾' => 'G',
  '𝕀' => 'I',
  '𝕁' => 'J',
  '𝕂' => 'K',
  '𝕃' => 'L',
  '𝕄' => 'M',
  '𝕆' => 'O',
  '𝕊' => 'S',
  '𝕋' => 'T',
  '𝕌' => 'U',
  '𝕍' => 'V',
  '𝕎' => 'W',
  '𝕏' => 'X',
  '𝕐' => 'Y',
  '𝕒' => 'a',
  '𝕓' => 'b',
  '𝕔' => 'c',
  '𝕕' => 'd',
  '𝕖' => 'e',
  '𝕗' => 'f',
  '𝕘' => 'g',
  '𝕙' => 'h',
  '𝕚' => 'i',
  '𝕛' => 'j',
  '𝕜' => 'k',
  '𝕝' => 'l',
  '𝕞' => 'm',
  '𝕟' => 'n',
  '𝕠' => 'o',
  '𝕡' => 'p',
  '𝕢' => 'q',
  '𝕣' => 'r',
  '𝕤' => 's',
  '𝕥' => 't',
  '𝕦' => 'u',
  '𝕧' => 'v',
  '𝕨' => 'w',
  '𝕩' => 'x',
  '𝕪' => 'y',
  '𝕫' => 'z',
  '𝕬' => 'A',
  '𝕭' => 'B',
  '𝕮' => 'C',
  '𝕯' => 'D',
  '𝕰' => 'E',
  '𝕱' => 'F',
  '𝕲' => 'G',
  '𝕳' => 'H',
  '𝕴' => 'I',
  '𝕵' => 'J',
  '𝕶' => 'K',
  '𝕷' => 'L',
  '𝕸' => 'M',
  '𝕹' => 'N',
  '𝕺' => 'O',
  '𝕻' => 'P',
  '𝕼' => 'Q',
  '𝕽' => 'R',
  '𝕾' => 'S',
  '𝕿' => 'T',
  '𝖀' => 'U',
  '𝖁' => 'V',
  '𝖂' => 'W',
  '𝖃' => 'X',
  '𝖄' => 'Y',
  '𝖅' => 'Z',
  '𝖆' => 'a',
  '𝖇' => 'b',
  '𝖈' => 'c',
  '𝖉' => 'd',
  '𝖊' => 'e',
  '𝖋' => 'f',
  '𝖌' => 'g',
  '𝖍' => 'h',
  '𝖎' => 'i',
  '𝖏' => 'j',
  '𝖐' => 'k',
  '𝖑' => 'l',
  '𝖒' => 'm',
  '𝖓' => 'n',
  '𝖔' => 'o',
  '𝖕' => 'p',
  '𝖖' => 'q',
  '𝖗' => 'r',
  '𝖘' => 's',
  '𝖙' => 't',
  '𝖚' => 'u',
  '𝖛' => 'v',
  '𝖜' => 'w',
  '𝖝' => 'x',
  '𝖞' => 'y',
  '𝖟' => 'z',
  '𝖠' => 'A',
  '𝖡' => 'B',
  '𝖢' => 'C',
  '𝖣' => 'D',
  '𝖤' => 'E',
  '𝖥' => 'F',
  '𝖦' => 'G',
  '𝖧' => 'H',
  '𝖨' => 'I',
  '𝖩' => 'J',
  '𝖪' => 'K',
  '𝖫' => 'L',
  '𝖬' => 'M',
  '𝖭' => 'N',
  '𝖮' => 'O',
  '𝖯' => 'P',
  '𝖰' => 'Q',
  '𝖱' => 'R',
  '𝖲' => 'S',
  '𝖳' => 'T',
  '𝖴' => 'U',
  '𝖵' => 'V',
  '𝖶' => 'W',
  '𝖷' => 'X',
  '𝖸' => 'Y',
  '𝖹' => 'Z',
  '𝖺' => 'a',
  '𝖻' => 'b',
  '𝖼' => 'c',
  '𝖽' => 'd',
  '𝖾' => 'e',
  '𝖿' => 'f',
  '𝗀' => 'g',
  '𝗁' => 'h',
  '𝗂' => 'i',
  '𝗃' => 'j',
  '𝗄' => 'k',
  '𝗅' => 'l',
  '𝗆' => 'm',
  '𝗇' => 'n',
  '𝗈' => 'o',
  '𝗉' => 'p',
  '𝗊' => 'q',
  '𝗋' => 'r',
  '𝗌' => 's',
  '𝗍' => 't',
  '𝗎' => 'u',
  '𝗏' => 'v',
  '𝗐' => 'w',
  '𝗑' => 'x',
  '𝗒' => 'y',
  '𝗓' => 'z',
  '𝗔' => 'A',
  '𝗕' => 'B',
  '𝗖' => 'C',
  '𝗗' => 'D',
  '𝗘' => 'E',
  '𝗙' => 'F',
  '𝗚' => 'G',
  '𝗛' => 'H',
  '𝗜' => 'I',
  '𝗝' => 'J',
  '𝗞' => 'K',
  '𝗟' => 'L',
  '𝗠' => 'M',
  '𝗡' => 'N',
  '𝗢' => 'O',
  '𝗣' => 'P',
  '𝗤' => 'Q',
  '𝗥' => 'R',
  '𝗦' => 'S',
  '𝗧' => 'T',
  '𝗨' => 'U',
  '𝗩' => 'V',
  '𝗪' => 'W',
  '𝗫' => 'X',
  '𝗬' => 'Y',
  '𝗭' => 'Z',
  '𝗮' => 'a',
  '𝗯' => 'b',
  '𝗰' => 'c',
  '𝗱' => 'd',
  '𝗲' => 'e',
  '𝗳' => 'f',
  '𝗴' => 'g',
  '𝗵' => 'h',
  '𝗶' => 'i',
  '𝗷' => 'j',
  '𝗸' => 'k',
  '𝗹' => 'l',
  '𝗺' => 'm',
  '𝗻' => 'n',
  '𝗼' => 'o',
  '𝗽' => 'p',
  '𝗾' => 'q',
  '𝗿' => 'r',
  '𝘀' => 's',
  '𝘁' => 't',
  '𝘂' => 'u',
  '𝘃' => 'v',
  '𝘄' => 'w',
  '𝘅' => 'x',
  '𝘆' => 'y',
  '𝘇' => 'z',
  '𝘈' => 'A',
  '𝘉' => 'B',
  '𝘊' => 'C',
  '𝘋' => 'D',
  '𝘌' => 'E',
  '𝘍' => 'F',
  '𝘎' => 'G',
  '𝘏' => 'H',
  '𝘐' => 'I',
  '𝘑' => 'J',
  '𝘒' => 'K',
  '𝘓' => 'L',
  '𝘔' => 'M',
  '𝘕' => 'N',
  '𝘖' => 'O',
  '𝘗' => 'P',
  '𝘘' => 'Q',
  '𝘙' => 'R',
  '𝘚' => 'S',
  '𝘛' => 'T',
  '𝘜' => 'U',
  '𝘝' => 'V',
  '𝘞' => 'W',
  '𝘟' => 'X',
  '𝘠' => 'Y',
  '𝘡' => 'Z',
  '𝘢' => 'a',
  '𝘣' => 'b',
  '𝘤' => 'c',
  '𝘥' => 'd',
  '𝘦' => 'e',
  '𝘧' => 'f',
  '𝘨' => 'g',
  '𝘩' => 'h',
  '𝘪' => 'i',
  '𝘫' => 'j',
  '𝘬' => 'k',
  '𝘭' => 'l',
  '𝘮' => 'm',
  '𝘯' => 'n',
  '𝘰' => 'o',
  '𝘱' => 'p',
  '𝘲' => 'q',
  '𝘳' => 'r',
  '𝘴' => 's',
  '𝘵' => 't',
  '𝘶' => 'u',
  '𝘷' => 'v',
  '𝘸' => 'w',
  '𝘹' => 'x',
  '𝘺' => 'y',
  '𝘻' => 'z',
  '𝘼' => 'A',
  '𝘽' => 'B',
  '𝘾' => 'C',
  '𝘿' => 'D',
  '𝙀' => 'E',
  '𝙁' => 'F',
  '𝙂' => 'G',
  '𝙃' => 'H',
  '𝙄' => 'I',
  '𝙅' => 'J',
  '𝙆' => 'K',
  '𝙇' => 'L',
  '𝙈' => 'M',
  '𝙉' => 'N',
  '𝙊' => 'O',
  '𝙋' => 'P',
  '𝙌' => 'Q',
  '𝙍' => 'R',
  '𝙎' => 'S',
  '𝙏' => 'T',
  '𝙐' => 'U',
  '𝙑' => 'V',
  '𝙒' => 'W',
  '𝙓' => 'X',
  '𝙔' => 'Y',
  '𝙕' => 'Z',
  '𝙖' => 'a',
  '𝙗' => 'b',
  '𝙘' => 'c',
  '𝙙' => 'd',
  '𝙚' => 'e',
  '𝙛' => 'f',
  '𝙜' => 'g',
  '𝙝' => 'h',
  '𝙞' => 'i',
  '𝙟' => 'j',
  '𝙠' => 'k',
  '𝙡' => 'l',
  '𝙢' => 'm',
  '𝙣' => 'n',
  '𝙤' => 'o',
  '𝙥' => 'p',
  '𝙦' => 'q',
  '𝙧' => 'r',
  '𝙨' => 's',
  '𝙩' => 't',
  '𝙪' => 'u',
  '𝙫' => 'v',
  '𝙬' => 'w',
  '𝙭' => 'x',
  '𝙮' => 'y',
  '𝙯' => 'z',
  '𝙰' => 'A',
  '𝙱' => 'B',
  '𝙲' => 'C',
  '𝙳' => 'D',
  '𝙴' => 'E',
  '𝙵' => 'F',
  '𝙶' => 'G',
  '𝙷' => 'H',
  '𝙸' => 'I',
  '𝙹' => 'J',
  '𝙺' => 'K',
  '𝙻' => 'L',
  '𝙼' => 'M',
  '𝙽' => 'N',
  '𝙾' => 'O',
  '𝙿' => 'P',
  '𝚀' => 'Q',
  '𝚁' => 'R',
  '𝚂' => 'S',
  '𝚃' => 'T',
  '𝚄' => 'U',
  '𝚅' => 'V',
  '𝚆' => 'W',
  '𝚇' => 'X',
  '𝚈' => 'Y',
  '𝚉' => 'Z',
  '𝚊' => 'a',
  '𝚋' => 'b',
  '𝚌' => 'c',
  '𝚍' => 'd',
  '𝚎' => 'e',
  '𝚏' => 'f',
  '𝚐' => 'g',
  '𝚑' => 'h',
  '𝚒' => 'i',
  '𝚓' => 'j',
  '𝚔' => 'k',
  '𝚕' => 'l',
  '𝚖' => 'm',
  '𝚗' => 'n',
  '𝚘' => 'o',
  '𝚙' => 'p',
  '𝚚' => 'q',
  '𝚛' => 'r',
  '𝚜' => 's',
  '𝚝' => 't',
  '𝚞' => 'u',
  '𝚟' => 'v',
  '𝚠' => 'w',
  '𝚡' => 'x',
  '𝚢' => 'y',
  '𝚣' => 'z',
  '𝚤' => 'ı',
  '𝚥' => 'ȷ',
  '𝚨' => 'Α',
  '𝚩' => 'Β',
  '𝚪' => 'Γ',
  '𝚫' => 'Δ',
  '𝚬' => 'Ε',
  '𝚭' => 'Ζ',
  '𝚮' => 'Η',
  '𝚯' => 'Θ',
  '𝚰' => 'Ι',
  '𝚱' => 'Κ',
  '𝚲' => 'Λ',
  '𝚳' => 'Μ',
  '𝚴' => 'Ν',
  '𝚵' => 'Ξ',
  '𝚶' => 'Ο',
  '𝚷' => 'Π',
  '𝚸' => 'Ρ',
  '𝚹' => 'Θ',
  '𝚺' => 'Σ',
  '𝚻' => 'Τ',
  '𝚼' => 'Υ',
  '𝚽' => 'Φ',
  '𝚾' => 'Χ',
  '𝚿' => 'Ψ',
  '𝛀' => 'Ω',
  '𝛁' => '∇',
  '𝛂' => 'α',
  '𝛃' => 'β',
  '𝛄' => 'γ',
  '𝛅' => 'δ',
  '𝛆' => 'ε',
  '𝛇' => 'ζ',
  '𝛈' => 'η',
  '𝛉' => 'θ',
  '𝛊' => 'ι',
  '𝛋' => 'κ',
  '𝛌' => 'λ',
  '𝛍' => 'μ',
  '𝛎' => 'ν',
  '𝛏' => 'ξ',
  '𝛐' => 'ο',
  '𝛑' => 'π',
  '𝛒' => 'ρ',
  '𝛓' => 'ς',
  '𝛔' => 'σ',
  '𝛕' => 'τ',
  '𝛖' => 'υ',
  '𝛗' => 'φ',
  '𝛘' => 'χ',
  '𝛙' => 'ψ',
  '𝛚' => 'ω',
  '𝛛' => '∂',
  '𝛜' => 'ε',
  '𝛝' => 'θ',
  '𝛞' => 'κ',
  '𝛟' => 'φ',
  '𝛠' => 'ρ',
  '𝛡' => 'π',
  '𝛢' => 'Α',
  '𝛣' => 'Β',
  '𝛤' => 'Γ',
  '𝛥' => 'Δ',
  '𝛦' => 'Ε',
  '𝛧' => 'Ζ',
  '𝛨' => 'Η',
  '𝛩' => 'Θ',
  '𝛪' => 'Ι',
  '𝛫' => 'Κ',
  '𝛬' => 'Λ',
  '𝛭' => 'Μ',
  '𝛮' => 'Ν',
  '𝛯' => 'Ξ',
  '𝛰' => 'Ο',
  '𝛱' => 'Π',
  '𝛲' => 'Ρ',
  '𝛳' => 'Θ',
  '𝛴' => 'Σ',
  '𝛵' => 'Τ',
  '𝛶' => 'Υ',
  '𝛷' => 'Φ',
  '𝛸' => 'Χ',
  '𝛹' => 'Ψ',
  '𝛺' => 'Ω',
  '𝛻' => '∇',
  '𝛼' => 'α',
  '𝛽' => 'β',
  '𝛾' => 'γ',
  '𝛿' => 'δ',
  '𝜀' => 'ε',
  '𝜁' => 'ζ',
  '𝜂' => 'η',
  '𝜃' => 'θ',
  '𝜄' => 'ι',
  '𝜅' => 'κ',
  '𝜆' => 'λ',
  '𝜇' => 'μ',
  '𝜈' => 'ν',
  '𝜉' => 'ξ',
  '𝜊' => 'ο',
  '𝜋' => 'π',
  '𝜌' => 'ρ',
  '𝜍' => 'ς',
  '𝜎' => 'σ',
  '𝜏' => 'τ',
  '𝜐' => 'υ',
  '𝜑' => 'φ',
  '𝜒' => 'χ',
  '𝜓' => 'ψ',
  '𝜔' => 'ω',
  '𝜕' => '∂',
  '𝜖' => 'ε',
  '𝜗' => 'θ',
  '𝜘' => 'κ',
  '𝜙' => 'φ',
  '𝜚' => 'ρ',
  '𝜛' => 'π',
  '𝜜' => 'Α',
  '𝜝' => 'Β',
  '𝜞' => 'Γ',
  '𝜟' => 'Δ',
  '𝜠' => 'Ε',
  '𝜡' => 'Ζ',
  '𝜢' => 'Η',
  '𝜣' => 'Θ',
  '𝜤' => 'Ι',
  '𝜥' => 'Κ',
  '𝜦' => 'Λ',
  '𝜧' => 'Μ',
  '𝜨' => 'Ν',
  '𝜩' => 'Ξ',
  '𝜪' => 'Ο',
  '𝜫' => 'Π',
  '𝜬' => 'Ρ',
  '𝜭' => 'Θ',
  '𝜮' => 'Σ',
  '𝜯' => 'Τ',
  '𝜰' => 'Υ',
  '𝜱' => 'Φ',
  '𝜲' => 'Χ',
  '𝜳' => 'Ψ',
  '𝜴' => 'Ω',
  '𝜵' => '∇',
  '𝜶' => 'α',
  '𝜷' => 'β',
  '𝜸' => 'γ',
  '𝜹' => 'δ',
  '𝜺' => 'ε',
  '𝜻' => 'ζ',
  '𝜼' => 'η',
  '𝜽' => 'θ',
  '𝜾' => 'ι',
  '𝜿' => 'κ',
  '𝝀' => 'λ',
  '𝝁' => 'μ',
  '𝝂' => 'ν',
  '𝝃' => 'ξ',
  '𝝄' => 'ο',
  '𝝅' => 'π',
  '𝝆' => 'ρ',
  '𝝇' => 'ς',
  '𝝈' => 'σ',
  '𝝉' => 'τ',
  '𝝊' => 'υ',
  '𝝋' => 'φ',
  '𝝌' => 'χ',
  '𝝍' => 'ψ',
  '𝝎' => 'ω',
  '𝝏' => '∂',
  '𝝐' => 'ε',
  '𝝑' => 'θ',
  '𝝒' => 'κ',
  '𝝓' => 'φ',
  '𝝔' => 'ρ',
  '𝝕' => 'π',
  '𝝖' => 'Α',
  '𝝗' => 'Β',
  '𝝘' => 'Γ',
  '𝝙' => 'Δ',
  '𝝚' => 'Ε',
  '𝝛' => 'Ζ',
  '𝝜' => 'Η',
  '𝝝' => 'Θ',
  '𝝞' => 'Ι',
  '𝝟' => 'Κ',
  '𝝠' => 'Λ',
  '𝝡' => 'Μ',
  '𝝢' => 'Ν',
  '𝝣' => 'Ξ',
  '𝝤' => 'Ο',
  '𝝥' => 'Π',
  '𝝦' => 'Ρ',
  '𝝧' => 'Θ',
  '𝝨' => 'Σ',
  '𝝩' => 'Τ',
  '𝝪' => 'Υ',
  '𝝫' => 'Φ',
  '𝝬' => 'Χ',
  '𝝭' => 'Ψ',
  '𝝮' => 'Ω',
  '𝝯' => '∇',
  '𝝰' => 'α',
  '𝝱' => 'β',
  '𝝲' => 'γ',
  '𝝳' => 'δ',
  '𝝴' => 'ε',
  '𝝵' => 'ζ',
  '𝝶' => 'η',
  '𝝷' => 'θ',
  '𝝸' => 'ι',
  '𝝹' => 'κ',
  '𝝺' => 'λ',
  '𝝻' => 'μ',
  '𝝼' => 'ν',
  '𝝽' => 'ξ',
  '𝝾' => 'ο',
  '𝝿' => 'π',
  '𝞀' => 'ρ',
  '𝞁' => 'ς',
  '𝞂' => 'σ',
  '𝞃' => 'τ',
  '𝞄' => 'υ',
  '𝞅' => 'φ',
  '𝞆' => 'χ',
  '𝞇' => 'ψ',
  '𝞈' => 'ω',
  '𝞉' => '∂',
  '𝞊' => 'ε',
  '𝞋' => 'θ',
  '𝞌' => 'κ',
  '𝞍' => 'φ',
  '𝞎' => 'ρ',
  '𝞏' => 'π',
  '𝞐' => 'Α',
  '𝞑' => 'Β',
  '𝞒' => 'Γ',
  '𝞓' => 'Δ',
  '𝞔' => 'Ε',
  '𝞕' => 'Ζ',
  '𝞖' => 'Η',
  '𝞗' => 'Θ',
  '𝞘' => 'Ι',
  '𝞙' => 'Κ',
  '𝞚' => 'Λ',
  '𝞛' => 'Μ',
  '𝞜' => 'Ν',
  '𝞝' => 'Ξ',
  '𝞞' => 'Ο',
  '𝞟' => 'Π',
  '𝞠' => 'Ρ',
  '𝞡' => 'Θ',
  '𝞢' => 'Σ',
  '𝞣' => 'Τ',
  '𝞤' => 'Υ',
  '𝞥' => 'Φ',
  '𝞦' => 'Χ',
  '𝞧' => 'Ψ',
  '𝞨' => 'Ω',
  '𝞩' => '∇',
  '𝞪' => 'α',
  '𝞫' => 'β',
  '𝞬' => 'γ',
  '𝞭' => 'δ',
  '𝞮' => 'ε',
  '𝞯' => 'ζ',
  '𝞰' => 'η',
  '𝞱' => 'θ',
  '𝞲' => 'ι',
  '𝞳' => 'κ',
  '𝞴' => 'λ',
  '𝞵' => 'μ',
  '𝞶' => 'ν',
  '𝞷' => 'ξ',
  '𝞸' => 'ο',
  '𝞹' => 'π',
  '𝞺' => 'ρ',
  '𝞻' => 'ς',
  '𝞼' => 'σ',
  '𝞽' => 'τ',
  '𝞾' => 'υ',
  '𝞿' => 'φ',
  '𝟀' => 'χ',
  '𝟁' => 'ψ',
  '𝟂' => 'ω',
  '𝟃' => '∂',
  '𝟄' => 'ε',
  '𝟅' => 'θ',
  '𝟆' => 'κ',
  '𝟇' => 'φ',
  '𝟈' => 'ρ',
  '𝟉' => 'π',
  '𝟊' => 'Ϝ',
  '𝟋' => 'ϝ',
  '𝟎' => '0',
  '𝟏' => '1',
  '𝟐' => '2',
  '𝟑' => '3',
  '𝟒' => '4',
  '𝟓' => '5',
  '𝟔' => '6',
  '𝟕' => '7',
  '𝟖' => '8',
  '𝟗' => '9',
  '𝟘' => '0',
  '𝟙' => '1',
  '𝟚' => '2',
  '𝟛' => '3',
  '𝟜' => '4',
  '𝟝' => '5',
  '𝟞' => '6',
  '𝟟' => '7',
  '𝟠' => '8',
  '𝟡' => '9',
  '𝟢' => '0',
  '𝟣' => '1',
  '𝟤' => '2',
  '𝟥' => '3',
  '𝟦' => '4',
  '𝟧' => '5',
  '𝟨' => '6',
  '𝟩' => '7',
  '𝟪' => '8',
  '𝟫' => '9',
  '𝟬' => '0',
  '𝟭' => '1',
  '𝟮' => '2',
  '𝟯' => '3',
  '𝟰' => '4',
  '𝟱' => '5',
  '𝟲' => '6',
  '𝟳' => '7',
  '𝟴' => '8',
  '𝟵' => '9',
  '𝟶' => '0',
  '𝟷' => '1',
  '𝟸' => '2',
  '𝟹' => '3',
  '𝟺' => '4',
  '𝟻' => '5',
  '𝟼' => '6',
  '𝟽' => '7',
  '𝟾' => '8',
  '𝟿' => '9',
  '𞸀' => 'ا',
  '𞸁' => 'ب',
  '𞸂' => 'ج',
  '𞸃' => 'د',
  '𞸅' => 'و',
  '𞸆' => 'ز',
  '𞸇' => 'ح',
  '𞸈' => 'ط',
  '𞸉' => 'ي',
  '𞸊' => 'ك',
  '𞸋' => 'ل',
  '𞸌' => 'م',
  '𞸍' => 'ن',
  '𞸎' => 'س',
  '𞸏' => 'ع',
  '𞸐' => 'ف',
  '𞸑' => 'ص',
  '𞸒' => 'ق',
  '𞸓' => 'ر',
  '𞸔' => 'ش',
  '𞸕' => 'ت',
  '𞸖' => 'ث',
  '𞸗' => 'خ',
  '𞸘' => 'ذ',
  '𞸙' => 'ض',
  '𞸚' => 'ظ',
  '𞸛' => 'غ',
  '𞸜' => 'ٮ',
  '𞸝' => 'ں',
  '𞸞' => 'ڡ',
  '𞸟' => 'ٯ',
  '𞸡' => 'ب',
  '𞸢' => 'ج',
  '𞸤' => 'ه',
  '𞸧' => 'ح',
  '𞸩' => 'ي',
  '𞸪' => 'ك',
  '𞸫' => 'ل',
  '𞸬' => 'م',
  '𞸭' => 'ن',
  '𞸮' => 'س',
  '𞸯' => 'ع',
  '𞸰' => 'ف',
  '𞸱' => 'ص',
  '𞸲' => 'ق',
  '𞸴' => 'ش',
  '𞸵' => 'ت',
  '𞸶' => 'ث',
  '𞸷' => 'خ',
  '𞸹' => 'ض',
  '𞸻' => 'غ',
  '𞹂' => 'ج',
  '𞹇' => 'ح',
  '𞹉' => 'ي',
  '𞹋' => 'ل',
  '𞹍' => 'ن',
  '𞹎' => 'س',
  '𞹏' => 'ع',
  '𞹑' => 'ص',
  '𞹒' => 'ق',
  '𞹔' => 'ش',
  '𞹗' => 'خ',
  '𞹙' => 'ض',
  '𞹛' => 'غ',
  '𞹝' => 'ں',
  '𞹟' => 'ٯ',
  '𞹡' => 'ب',
  '𞹢' => 'ج',
  '𞹤' => 'ه',
  '𞹧' => 'ح',
  '𞹨' => 'ط',
  '𞹩' => 'ي',
  '𞹪' => 'ك',
  '𞹬' => 'م',
  '𞹭' => 'ن',
  '𞹮' => 'س',
  '𞹯' => 'ع',
  '𞹰' => 'ف',
  '𞹱' => 'ص',
  '𞹲' => 'ق',
  '𞹴' => 'ش',
  '𞹵' => 'ت',
  '𞹶' => 'ث',
  '𞹷' => 'خ',
  '𞹹' => 'ض',
  '𞹺' => 'ظ',
  '𞹻' => 'غ',
  '𞹼' => 'ٮ',
  '𞹾' => 'ڡ',
  '𞺀' => 'ا',
  '𞺁' => 'ب',
  '𞺂' => 'ج',
  '𞺃' => 'د',
  '𞺄' => 'ه',
  '𞺅' => 'و',
  '𞺆' => 'ز',
  '𞺇' => 'ح',
  '𞺈' => 'ط',
  '𞺉' => 'ي',
  '𞺋' => 'ل',
  '𞺌' => 'م',
  '𞺍' => 'ن',
  '𞺎' => 'س',
  '𞺏' => 'ع',
  '𞺐' => 'ف',
  '𞺑' => 'ص',
  '𞺒' => 'ق',
  '𞺓' => 'ر',
  '𞺔' => 'ش',
  '𞺕' => 'ت',
  '𞺖' => 'ث',
  '𞺗' => 'خ',
  '𞺘' => 'ذ',
  '𞺙' => 'ض',
  '𞺚' => 'ظ',
  '𞺛' => 'غ',
  '𞺡' => 'ب',
  '𞺢' => 'ج',
  '𞺣' => 'د',
  '𞺥' => 'و',
  '𞺦' => 'ز',
  '𞺧' => 'ح',
  '𞺨' => 'ط',
  '𞺩' => 'ي',
  '𞺫' => 'ل',
  '𞺬' => 'م',
  '𞺭' => 'ن',
  '𞺮' => 'س',
  '𞺯' => 'ع',
  '𞺰' => 'ف',
  '𞺱' => 'ص',
  '𞺲' => 'ق',
  '𞺳' => 'ر',
  '𞺴' => 'ش',
  '𞺵' => 'ت',
  '𞺶' => 'ث',
  '𞺷' => 'خ',
  '𞺸' => 'ذ',
  '𞺹' => 'ض',
  '𞺺' => 'ظ',
  '𞺻' => 'غ',
  '🄀' => '0.',
  '🄁' => '0,',
  '🄂' => '1,',
  '🄃' => '2,',
  '🄄' => '3,',
  '🄅' => '4,',
  '🄆' => '5,',
  '🄇' => '6,',
  '🄈' => '7,',
  '🄉' => '8,',
  '🄊' => '9,',
  '🄐' => '(A)',
  '🄑' => '(B)',
  '🄒' => '(C)',
  '🄓' => '(D)',
  '🄔' => '(E)',
  '🄕' => '(F)',
  '🄖' => '(G)',
  '🄗' => '(H)',
  '🄘' => '(I)',
  '🄙' => '(J)',
  '🄚' => '(K)',
  '🄛' => '(L)',
  '🄜' => '(M)',
  '🄝' => '(N)',
  '🄞' => '(O)',
  '🄟' => '(P)',
  '🄠' => '(Q)',
  '🄡' => '(R)',
  '🄢' => '(S)',
  '🄣' => '(T)',
  '🄤' => '(U)',
  '🄥' => '(V)',
  '🄦' => '(W)',
  '🄧' => '(X)',
  '🄨' => '(Y)',
  '🄩' => '(Z)',
  '🄪' => '〔S〕',
  '🄫' => 'C',
  '🄬' => 'R',
  '🄭' => 'CD',
  '🄮' => 'WZ',
  '🄰' => 'A',
  '🄱' => 'B',
  '🄲' => 'C',
  '🄳' => 'D',
  '🄴' => 'E',
  '🄵' => 'F',
  '🄶' => 'G',
  '🄷' => 'H',
  '🄸' => 'I',
  '🄹' => 'J',
  '🄺' => 'K',
  '🄻' => 'L',
  '🄼' => 'M',
  '🄽' => 'N',
  '🄾' => 'O',
  '🄿' => 'P',
  '🅀' => 'Q',
  '🅁' => 'R',
  '🅂' => 'S',
  '🅃' => 'T',
  '🅄' => 'U',
  '🅅' => 'V',
  '🅆' => 'W',
  '🅇' => 'X',
  '🅈' => 'Y',
  '🅉' => 'Z',
  '🅊' => 'HV',
  '🅋' => 'MV',
  '🅌' => 'SD',
  '🅍' => 'SS',
  '🅎' => 'PPV',
  '🅏' => 'WC',
  '🅪' => 'MC',
  '🅫' => 'MD',
  '🅬' => 'MR',
  '🆐' => 'DJ',
  '🈀' => 'ほか',
  '🈁' => 'ココ',
  '🈂' => 'サ',
  '🈐' => '手',
  '🈑' => '字',
  '🈒' => '双',
  '🈓' => 'デ',
  '🈔' => '二',
  '🈕' => '多',
  '🈖' => '解',
  '🈗' => '天',
  '🈘' => '交',
  '🈙' => '映',
  '🈚' => '無',
  '🈛' => '料',
  '🈜' => '前',
  '🈝' => '後',
  '🈞' => '再',
  '🈟' => '新',
  '🈠' => '初',
  '🈡' => '終',
  '🈢' => '生',
  '🈣' => '販',
  '🈤' => '声',
  '🈥' => '吹',
  '🈦' => '演',
  '🈧' => '投',
  '🈨' => '捕',
  '🈩' => '一',
  '🈪' => '三',
  '🈫' => '遊',
  '🈬' => '左',
  '🈭' => '中',
  '🈮' => '右',
  '🈯' => '指',
  '🈰' => '走',
  '🈱' => '打',
  '🈲' => '禁',
  '🈳' => '空',
  '🈴' => '合',
  '🈵' => '満',
  '🈶' => '有',
  '🈷' => '月',
  '🈸' => '申',
  '🈹' => '割',
  '🈺' => '営',
  '🈻' => '配',
  '🉀' => '〔本〕',
  '🉁' => '〔三〕',
  '🉂' => '〔二〕',
  '🉃' => '〔安〕',
  '🉄' => '〔点〕',
  '🉅' => '〔打〕',
  '🉆' => '〔盗〕',
  '🉇' => '〔勝〕',
  '🉈' => '〔敗〕',
  '🉐' => '得',
  '🉑' => '可',
  '🯰' => '0',
  '🯱' => '1',
  '🯲' => '2',
  '🯳' => '3',
  '🯴' => '4',
  '🯵' => '5',
  '🯶' => '6',
  '🯷' => '7',
  '🯸' => '8',
  '🯹' => '9',
);
<?php

return array (
  '̀' => 230,
  '́' => 230,
  '̂' => 230,
  '̃' => 230,
  '̄' => 230,
  '̅' => 230,
  '̆' => 230,
  '̇' => 230,
  '̈' => 230,
  '̉' => 230,
  '̊' => 230,
  '̋' => 230,
  '̌' => 230,
  '̍' => 230,
  '̎' => 230,
  '̏' => 230,
  '̐' => 230,
  '̑' => 230,
  '̒' => 230,
  '̓' => 230,
  '̔' => 230,
  '̕' => 232,
  '̖' => 220,
  '̗' => 220,
  '̘' => 220,
  '̙' => 220,
  '̚' => 232,
  '̛' => 216,
  '̜' => 220,
  '̝' => 220,
  '̞' => 220,
  '̟' => 220,
  '̠' => 220,
  '̡' => 202,
  '̢' => 202,
  '̣' => 220,
  '̤' => 220,
  '̥' => 220,
  '̦' => 220,
  '̧' => 202,
  '̨' => 202,
  '̩' => 220,
  '̪' => 220,
  '̫' => 220,
  '̬' => 220,
  '̭' => 220,
  '̮' => 220,
  '̯' => 220,
  '̰' => 220,
  '̱' => 220,
  '̲' => 220,
  '̳' => 220,
  '̴' => 1,
  '̵' => 1,
  '̶' => 1,
  '̷' => 1,
  '̸' => 1,
  '̹' => 220,
  '̺' => 220,
  '̻' => 220,
  '̼' => 220,
  '̽' => 230,
  '̾' => 230,
  '̿' => 230,
  '̀' => 230,
  '́' => 230,
  '͂' => 230,
  '̓' => 230,
  '̈́' => 230,
  'ͅ' => 240,
  '͆' => 230,
  '͇' => 220,
  '͈' => 220,
  '͉' => 220,
  '͊' => 230,
  '͋' => 230,
  '͌' => 230,
  '͍' => 220,
  '͎' => 220,
  '͐' => 230,
  '͑' => 230,
  '͒' => 230,
  '͓' => 220,
  '͔' => 220,
  '͕' => 220,
  '͖' => 220,
  '͗' => 230,
  '͘' => 232,
  '͙' => 220,
  '͚' => 220,
  '͛' => 230,
  '͜' => 233,
  '͝' => 234,
  '͞' => 234,
  '͟' => 233,
  '͠' => 234,
  '͡' => 234,
  '͢' => 233,
  'ͣ' => 230,
  'ͤ' => 230,
  'ͥ' => 230,
  'ͦ' => 230,
  'ͧ' => 230,
  'ͨ' => 230,
  'ͩ' => 230,
  'ͪ' => 230,
  'ͫ' => 230,
  'ͬ' => 230,
  'ͭ' => 230,
  'ͮ' => 230,
  'ͯ' => 230,
  '҃' => 230,
  '҄' => 230,
  '҅' => 230,
  '҆' => 230,
  '҇' => 230,
  '֑' => 220,
  '֒' => 230,
  '֓' => 230,
  '֔' => 230,
  '֕' => 230,
  '֖' => 220,
  '֗' => 230,
  '֘' => 230,
  '֙' => 230,
  '֚' => 222,
  '֛' => 220,
  '֜' => 230,
  '֝' => 230,
  '֞' => 230,
  '֟' => 230,
  '֠' => 230,
  '֡' => 230,
  '֢' => 220,
  '֣' => 220,
  '֤' => 220,
  '֥' => 220,
  '֦' => 220,
  '֧' => 220,
  '֨' => 230,
  '֩' => 230,
  '֪' => 220,
  '֫' => 230,
  '֬' => 230,
  '֭' => 222,
  '֮' => 228,
  '֯' => 230,
  'ְ' => 10,
  'ֱ' => 11,
  'ֲ' => 12,
  'ֳ' => 13,
  'ִ' => 14,
  'ֵ' => 15,
  'ֶ' => 16,
  'ַ' => 17,
  'ָ' => 18,
  'ֹ' => 19,
  'ֺ' => 19,
  'ֻ' => 20,
  'ּ' => 21,
  'ֽ' => 22,
  'ֿ' => 23,
  'ׁ' => 24,
  'ׂ' => 25,
  'ׄ' => 230,
  'ׅ' => 220,
  'ׇ' => 18,
  'ؐ' => 230,
  'ؑ' => 230,
  'ؒ' => 230,
  'ؓ' => 230,
  'ؔ' => 230,
  'ؕ' => 230,
  'ؖ' => 230,
  'ؗ' => 230,
  'ؘ' => 30,
  'ؙ' => 31,
  'ؚ' => 32,
  'ً' => 27,
  'ٌ' => 28,
  'ٍ' => 29,
  'َ' => 30,
  'ُ' => 31,
  'ِ' => 32,
  'ّ' => 33,
  'ْ' => 34,
  'ٓ' => 230,
  'ٔ' => 230,
  'ٕ' => 220,
  'ٖ' => 220,
  'ٗ' => 230,
  '٘' => 230,
  'ٙ' => 230,
  'ٚ' => 230,
  'ٛ' => 230,
  'ٜ' => 220,
  'ٝ' => 230,
  'ٞ' => 230,
  'ٟ' => 220,
  'ٰ' => 35,
  'ۖ' => 230,
  'ۗ' => 230,
  'ۘ' => 230,
  'ۙ' => 230,
  'ۚ' => 230,
  'ۛ' => 230,
  'ۜ' => 230,
  '۟' => 230,
  '۠' => 230,
  'ۡ' => 230,
  'ۢ' => 230,
  'ۣ' => 220,
  'ۤ' => 230,
  'ۧ' => 230,
  'ۨ' => 230,
  '۪' => 220,
  '۫' => 230,
  '۬' => 230,
  'ۭ' => 220,
  'ܑ' => 36,
  'ܰ' => 230,
  'ܱ' => 220,
  'ܲ' => 230,
  'ܳ' => 230,
  'ܴ' => 220,
  'ܵ' => 230,
  'ܶ' => 230,
  'ܷ' => 220,
  'ܸ' => 220,
  'ܹ' => 220,
  'ܺ' => 230,
  'ܻ' => 220,
  'ܼ' => 220,
  'ܽ' => 230,
  'ܾ' => 220,
  'ܿ' => 230,
  '݀' => 230,
  '݁' => 230,
  '݂' => 220,
  '݃' => 230,
  '݄' => 220,
  '݅' => 230,
  '݆' => 220,
  '݇' => 230,
  '݈' => 220,
  '݉' => 230,
  '݊' => 230,
  '߫' => 230,
  '߬' => 230,
  '߭' => 230,
  '߮' => 230,
  '߯' => 230,
  '߰' => 230,
  '߱' => 230,
  '߲' => 220,
  '߳' => 230,
  '߽' => 220,
  'ࠖ' => 230,
  'ࠗ' => 230,
  '࠘' => 230,
  '࠙' => 230,
  'ࠛ' => 230,
  'ࠜ' => 230,
  'ࠝ' => 230,
  'ࠞ' => 230,
  'ࠟ' => 230,
  'ࠠ' => 230,
  'ࠡ' => 230,
  'ࠢ' => 230,
  'ࠣ' => 230,
  'ࠥ' => 230,
  'ࠦ' => 230,
  'ࠧ' => 230,
  'ࠩ' => 230,
  'ࠪ' => 230,
  'ࠫ' => 230,
  'ࠬ' => 230,
  '࠭' => 230,
  '࡙' => 220,
  '࡚' => 220,
  '࡛' => 220,
  '࣓' => 220,
  'ࣔ' => 230,
  'ࣕ' => 230,
  'ࣖ' => 230,
  'ࣗ' => 230,
  'ࣘ' => 230,
  'ࣙ' => 230,
  'ࣚ' => 230,
  'ࣛ' => 230,
  'ࣜ' => 230,
  'ࣝ' => 230,
  'ࣞ' => 230,
  'ࣟ' => 230,
  '࣠' => 230,
  '࣡' => 230,
  'ࣣ' => 220,
  'ࣤ' => 230,
  'ࣥ' => 230,
  'ࣦ' => 220,
  'ࣧ' => 230,
  'ࣨ' => 230,
  'ࣩ' => 220,
  '࣪' => 230,
  '࣫' => 230,
  '࣬' => 230,
  '࣭' => 220,
  '࣮' => 220,
  '࣯' => 220,
  'ࣰ' => 27,
  'ࣱ' => 28,
  'ࣲ' => 29,
  'ࣳ' => 230,
  'ࣴ' => 230,
  'ࣵ' => 230,
  'ࣶ' => 220,
  'ࣷ' => 230,
  'ࣸ' => 230,
  'ࣹ' => 220,
  'ࣺ' => 220,
  'ࣻ' => 230,
  'ࣼ' => 230,
  'ࣽ' => 230,
  'ࣾ' => 230,
  'ࣿ' => 230,
  '़' => 7,
  '्' => 9,
  '॑' => 230,
  '॒' => 220,
  '॓' => 230,
  '॔' => 230,
  '়' => 7,
  '্' => 9,
  '৾' => 230,
  '਼' => 7,
  '੍' => 9,
  '઼' => 7,
  '્' => 9,
  '଼' => 7,
  '୍' => 9,
  '்' => 9,
  '్' => 9,
  'ౕ' => 84,
  'ౖ' => 91,
  '಼' => 7,
  '್' => 9,
  '഻' => 9,
  '഼' => 9,
  '്' => 9,
  '්' => 9,
  'ุ' => 103,
  'ู' => 103,
  'ฺ' => 9,
  '่' => 107,
  '้' => 107,
  '๊' => 107,
  '๋' => 107,
  'ຸ' => 118,
  'ູ' => 118,
  '຺' => 9,
  '່' => 122,
  '້' => 122,
  '໊' => 122,
  '໋' => 122,
  '༘' => 220,
  '༙' => 220,
  '༵' => 220,
  '༷' => 220,
  '༹' => 216,
  'ཱ' => 129,
  'ི' => 130,
  'ུ' => 132,
  'ེ' => 130,
  'ཻ' => 130,
  'ོ' => 130,
  'ཽ' => 130,
  'ྀ' => 130,
  'ྂ' => 230,
  'ྃ' => 230,
  '྄' => 9,
  '྆' => 230,
  '྇' => 230,
  '࿆' => 220,
  '့' => 7,
  '္' => 9,
  '်' => 9,
  'ႍ' => 220,
  '፝' => 230,
  '፞' => 230,
  '፟' => 230,
  '᜔' => 9,
  '᜴' => 9,
  '្' => 9,
  '៝' => 230,
  'ᢩ' => 228,
  '᤹' => 222,
  '᤺' => 230,
  '᤻' => 220,
  'ᨗ' => 230,
  'ᨘ' => 220,
  '᩠' => 9,
  '᩵' => 230,
  '᩶' => 230,
  '᩷' => 230,
  '᩸' => 230,
  '᩹' => 230,
  '᩺' => 230,
  '᩻' => 230,
  '᩼' => 230,
  '᩿' => 220,
  '᪰' => 230,
  '᪱' => 230,
  '᪲' => 230,
  '᪳' => 230,
  '᪴' => 230,
  '᪵' => 220,
  '᪶' => 220,
  '᪷' => 220,
  '᪸' => 220,
  '᪹' => 220,
  '᪺' => 220,
  '᪻' => 230,
  '᪼' => 230,
  '᪽' => 220,
  'ᪿ' => 220,
  'ᫀ' => 220,
  '᬴' => 7,
  '᭄' => 9,
  '᭫' => 230,
  '᭬' => 220,
  '᭭' => 230,
  '᭮' => 230,
  '᭯' => 230,
  '᭰' => 230,
  '᭱' => 230,
  '᭲' => 230,
  '᭳' => 230,
  '᮪' => 9,
  '᮫' => 9,
  '᯦' => 7,
  '᯲' => 9,
  '᯳' => 9,
  '᰷' => 7,
  '᳐' => 230,
  '᳑' => 230,
  '᳒' => 230,
  '᳔' => 1,
  '᳕' => 220,
  '᳖' => 220,
  '᳗' => 220,
  '᳘' => 220,
  '᳙' => 220,
  '᳚' => 230,
  '᳛' => 230,
  '᳜' => 220,
  '᳝' => 220,
  '᳞' => 220,
  '᳟' => 220,
  '᳠' => 230,
  '᳢' => 1,
  '᳣' => 1,
  '᳤' => 1,
  '᳥' => 1,
  '᳦' => 1,
  '᳧' => 1,
  '᳨' => 1,
  '᳭' => 220,
  '᳴' => 230,
  '᳸' => 230,
  '᳹' => 230,
  '᷀' => 230,
  '᷁' => 230,
  '᷂' => 220,
  '᷃' => 230,
  '᷄' => 230,
  '᷅' => 230,
  '᷆' => 230,
  '᷇' => 230,
  '᷈' => 230,
  '᷉' => 230,
  '᷊' => 220,
  '᷋' => 230,
  '᷌' => 230,
  '᷍' => 234,
  '᷎' => 214,
  '᷏' => 220,
  '᷐' => 202,
  '᷑' => 230,
  '᷒' => 230,
  'ᷓ' => 230,
  'ᷔ' => 230,
  'ᷕ' => 230,
  'ᷖ' => 230,
  'ᷗ' => 230,
  'ᷘ' => 230,
  'ᷙ' => 230,
  'ᷚ' => 230,
  'ᷛ' => 230,
  'ᷜ' => 230,
  'ᷝ' => 230,
  'ᷞ' => 230,
  'ᷟ' => 230,
  'ᷠ' => 230,
  'ᷡ' => 230,
  'ᷢ' => 230,
  'ᷣ' => 230,
  'ᷤ' => 230,
  'ᷥ' => 230,
  'ᷦ' => 230,
  'ᷧ' => 230,
  'ᷨ' => 230,
  'ᷩ' => 230,
  'ᷪ' => 230,
  'ᷫ' => 230,
  'ᷬ' => 230,
  'ᷭ' => 230,
  'ᷮ' => 230,
  'ᷯ' => 230,
  'ᷰ' => 230,
  'ᷱ' => 230,
  'ᷲ' => 230,
  'ᷳ' => 230,
  'ᷴ' => 230,
  '᷵' => 230,
  '᷶' => 232,
  '᷷' => 228,
  '᷸' => 228,
  '᷹' => 220,
  '᷻' => 230,
  '᷼' => 233,
  '᷽' => 220,
  '᷾' => 230,
  '᷿' => 220,
  '⃐' => 230,
  '⃑' => 230,
  '⃒' => 1,
  '⃓' => 1,
  '⃔' => 230,
  '⃕' => 230,
  '⃖' => 230,
  '⃗' => 230,
  '⃘' => 1,
  '⃙' => 1,
  '⃚' => 1,
  '⃛' => 230,
  '⃜' => 230,
  '⃡' => 230,
  '⃥' => 1,
  '⃦' => 1,
  '⃧' => 230,
  '⃨' => 220,
  '⃩' => 230,
  '⃪' => 1,
  '⃫' => 1,
  '⃬' => 220,
  '⃭' => 220,
  '⃮' => 220,
  '⃯' => 220,
  '⃰' => 230,
  '⳯' => 230,
  '⳰' => 230,
  '⳱' => 230,
  '⵿' => 9,
  'ⷠ' => 230,
  'ⷡ' => 230,
  'ⷢ' => 230,
  'ⷣ' => 230,
  'ⷤ' => 230,
  'ⷥ' => 230,
  'ⷦ' => 230,
  'ⷧ' => 230,
  'ⷨ' => 230,
  'ⷩ' => 230,
  'ⷪ' => 230,
  'ⷫ' => 230,
  'ⷬ' => 230,
  'ⷭ' => 230,
  'ⷮ' => 230,
  'ⷯ' => 230,
  'ⷰ' => 230,
  'ⷱ' => 230,
  'ⷲ' => 230,
  'ⷳ' => 230,
  'ⷴ' => 230,
  'ⷵ' => 230,
  'ⷶ' => 230,
  'ⷷ' => 230,
  'ⷸ' => 230,
  'ⷹ' => 230,
  'ⷺ' => 230,
  'ⷻ' => 230,
  'ⷼ' => 230,
  'ⷽ' => 230,
  'ⷾ' => 230,
  'ⷿ' => 230,
  '〪' => 218,
  '〫' => 228,
  '〬' => 232,
  '〭' => 222,
  '〮' => 224,
  '〯' => 224,
  '゙' => 8,
  '゚' => 8,
  '꙯' => 230,
  'ꙴ' => 230,
  'ꙵ' => 230,
  'ꙶ' => 230,
  'ꙷ' => 230,
  'ꙸ' => 230,
  'ꙹ' => 230,
  'ꙺ' => 230,
  'ꙻ' => 230,
  '꙼' => 230,
  '꙽' => 230,
  'ꚞ' => 230,
  'ꚟ' => 230,
  '꛰' => 230,
  '꛱' => 230,
  '꠆' => 9,
  '꠬' => 9,
  '꣄' => 9,
  '꣠' => 230,
  '꣡' => 230,
  '꣢' => 230,
  '꣣' => 230,
  '꣤' => 230,
  '꣥' => 230,
  '꣦' => 230,
  '꣧' => 230,
  '꣨' => 230,
  '꣩' => 230,
  '꣪' => 230,
  '꣫' => 230,
  '꣬' => 230,
  '꣭' => 230,
  '꣮' => 230,
  '꣯' => 230,
  '꣰' => 230,
  '꣱' => 230,
  '꤫' => 220,
  '꤬' => 220,
  '꤭' => 220,
  '꥓' => 9,
  '꦳' => 7,
  '꧀' => 9,
  'ꪰ' => 230,
  'ꪲ' => 230,
  'ꪳ' => 230,
  'ꪴ' => 220,
  'ꪷ' => 230,
  'ꪸ' => 230,
  'ꪾ' => 230,
  '꪿' => 230,
  '꫁' => 230,
  '꫶' => 9,
  '꯭' => 9,
  'ﬞ' => 26,
  '︠' => 230,
  '︡' => 230,
  '︢' => 230,
  '︣' => 230,
  '︤' => 230,
  '︥' => 230,
  '︦' => 230,
  '︧' => 220,
  '︨' => 220,
  '︩' => 220,
  '︪' => 220,
  '︫' => 220,
  '︬' => 220,
  '︭' => 220,
  '︮' => 230,
  '︯' => 230,
  '𐇽' => 220,
  '𐋠' => 220,
  '𐍶' => 230,
  '𐍷' => 230,
  '𐍸' => 230,
  '𐍹' => 230,
  '𐍺' => 230,
  '𐨍' => 220,
  '𐨏' => 230,
  '𐨸' => 230,
  '𐨹' => 1,
  '𐨺' => 220,
  '𐨿' => 9,
  '𐫥' => 230,
  '𐫦' => 220,
  '𐴤' => 230,
  '𐴥' => 230,
  '𐴦' => 230,
  '𐴧' => 230,
  '𐺫' => 230,
  '𐺬' => 230,
  '𐽆' => 220,
  '𐽇' => 220,
  '𐽈' => 230,
  '𐽉' => 230,
  '𐽊' => 230,
  '𐽋' => 220,
  '𐽌' => 230,
  '𐽍' => 220,
  '𐽎' => 220,
  '𐽏' => 220,
  '𐽐' => 220,
  '𑁆' => 9,
  '𑁿' => 9,
  '𑂹' => 9,
  '𑂺' => 7,
  '𑄀' => 230,
  '𑄁' => 230,
  '𑄂' => 230,
  '𑄳' => 9,
  '𑄴' => 9,
  '𑅳' => 7,
  '𑇀' => 9,
  '𑇊' => 7,
  '𑈵' => 9,
  '𑈶' => 7,
  '𑋩' => 7,
  '𑋪' => 9,
  '𑌻' => 7,
  '𑌼' => 7,
  '𑍍' => 9,
  '𑍦' => 230,
  '𑍧' => 230,
  '𑍨' => 230,
  '𑍩' => 230,
  '𑍪' => 230,
  '𑍫' => 230,
  '𑍬' => 230,
  '𑍰' => 230,
  '𑍱' => 230,
  '𑍲' => 230,
  '𑍳' => 230,
  '𑍴' => 230,
  '𑑂' => 9,
  '𑑆' => 7,
  '𑑞' => 230,
  '𑓂' => 9,
  '𑓃' => 7,
  '𑖿' => 9,
  '𑗀' => 7,
  '𑘿' => 9,
  '𑚶' => 9,
  '𑚷' => 7,
  '𑜫' => 9,
  '𑠹' => 9,
  '𑠺' => 7,
  '𑤽' => 9,
  '𑤾' => 9,
  '𑥃' => 7,
  '𑧠' => 9,
  '𑨴' => 9,
  '𑩇' => 9,
  '𑪙' => 9,
  '𑰿' => 9,
  '𑵂' => 7,
  '𑵄' => 9,
  '𑵅' => 9,
  '𑶗' => 9,
  '𖫰' => 1,
  '𖫱' => 1,
  '𖫲' => 1,
  '𖫳' => 1,
  '𖫴' => 1,
  '𖬰' => 230,
  '𖬱' => 230,
  '𖬲' => 230,
  '𖬳' => 230,
  '𖬴' => 230,
  '𖬵' => 230,
  '𖬶' => 230,
  '𖿰' => 6,
  '𖿱' => 6,
  '𛲞' => 1,
  '𝅥' => 216,
  '𝅦' => 216,
  '𝅧' => 1,
  '𝅨' => 1,
  '𝅩' => 1,
  '𝅭' => 226,
  '𝅮' => 216,
  '𝅯' => 216,
  '𝅰' => 216,
  '𝅱' => 216,
  '𝅲' => 216,
  '𝅻' => 220,
  '𝅼' => 220,
  '𝅽' => 220,
  '𝅾' => 220,
  '𝅿' => 220,
  '𝆀' => 220,
  '𝆁' => 220,
  '𝆂' => 220,
  '𝆅' => 230,
  '𝆆' => 230,
  '𝆇' => 230,
  '𝆈' => 230,
  '𝆉' => 230,
  '𝆊' => 220,
  '𝆋' => 220,
  '𝆪' => 230,
  '𝆫' => 230,
  '𝆬' => 230,
  '𝆭' => 230,
  '𝉂' => 230,
  '𝉃' => 230,
  '𝉄' => 230,
  '𞀀' => 230,
  '𞀁' => 230,
  '𞀂' => 230,
  '𞀃' => 230,
  '𞀄' => 230,
  '𞀅' => 230,
  '𞀆' => 230,
  '𞀈' => 230,
  '𞀉' => 230,
  '𞀊' => 230,
  '𞀋' => 230,
  '𞀌' => 230,
  '𞀍' => 230,
  '𞀎' => 230,
  '𞀏' => 230,
  '𞀐' => 230,
  '𞀑' => 230,
  '𞀒' => 230,
  '𞀓' => 230,
  '𞀔' => 230,
  '𞀕' => 230,
  '𞀖' => 230,
  '𞀗' => 230,
  '𞀘' => 230,
  '𞀛' => 230,
  '𞀜' => 230,
  '𞀝' => 230,
  '𞀞' => 230,
  '𞀟' => 230,
  '𞀠' => 230,
  '𞀡' => 230,
  '𞀣' => 230,
  '𞀤' => 230,
  '𞀦' => 230,
  '𞀧' => 230,
  '𞀨' => 230,
  '𞀩' => 230,
  '𞀪' => 230,
  '𞄰' => 230,
  '𞄱' => 230,
  '𞄲' => 230,
  '𞄳' => 230,
  '𞄴' => 230,
  '𞄵' => 230,
  '𞄶' => 230,
  '𞋬' => 230,
  '𞋭' => 230,
  '𞋮' => 230,
  '𞋯' => 230,
  '𞣐' => 220,
  '𞣑' => 220,
  '𞣒' => 220,
  '𞣓' => 220,
  '𞣔' => 220,
  '𞣕' => 220,
  '𞣖' => 220,
  '𞥄' => 230,
  '𞥅' => 230,
  '𞥆' => 230,
  '𞥇' => 230,
  '𞥈' => 230,
  '𞥉' => 230,
  '𞥊' => 7,
);
<?php

return array (
  'À' => 'À',
  'Á' => 'Á',
  'Â' => 'Â',
  'Ã' => 'Ã',
  'Ä' => 'Ä',
  'Å' => 'Å',
  'Ç' => 'Ç',
  'È' => 'È',
  'É' => 'É',
  'Ê' => 'Ê',
  'Ë' => 'Ë',
  'Ì' => 'Ì',
  'Í' => 'Í',
  'Î' => 'Î',
  'Ï' => 'Ï',
  'Ñ' => 'Ñ',
  'Ò' => 'Ò',
  'Ó' => 'Ó',
  'Ô' => 'Ô',
  'Õ' => 'Õ',
  'Ö' => 'Ö',
  'Ù' => 'Ù',
  'Ú' => 'Ú',
  'Û' => 'Û',
  'Ü' => 'Ü',
  'Ý' => 'Ý',
  'à' => 'à',
  'á' => 'á',
  'â' => 'â',
  'ã' => 'ã',
  'ä' => 'ä',
  'å' => 'å',
  'ç' => 'ç',
  'è' => 'è',
  'é' => 'é',
  'ê' => 'ê',
  'ë' => 'ë',
  'ì' => 'ì',
  'í' => 'í',
  'î' => 'î',
  'ï' => 'ï',
  'ñ' => 'ñ',
  'ò' => 'ò',
  'ó' => 'ó',
  'ô' => 'ô',
  'õ' => 'õ',
  'ö' => 'ö',
  'ù' => 'ù',
  'ú' => 'ú',
  'û' => 'û',
  'ü' => 'ü',
  'ý' => 'ý',
  'ÿ' => 'ÿ',
  'Ā' => 'Ā',
  'ā' => 'ā',
  'Ă' => 'Ă',
  'ă' => 'ă',
  'Ą' => 'Ą',
  'ą' => 'ą',
  'Ć' => 'Ć',
  'ć' => 'ć',
  'Ĉ' => 'Ĉ',
  'ĉ' => 'ĉ',
  'Ċ' => 'Ċ',
  'ċ' => 'ċ',
  'Č' => 'Č',
  'č' => 'č',
  'Ď' => 'Ď',
  'ď' => 'ď',
  'Ē' => 'Ē',
  'ē' => 'ē',
  'Ĕ' => 'Ĕ',
  'ĕ' => 'ĕ',
  'Ė' => 'Ė',
  'ė' => 'ė',
  'Ę' => 'Ę',
  'ę' => 'ę',
  'Ě' => 'Ě',
  'ě' => 'ě',
  'Ĝ' => 'Ĝ',
  'ĝ' => 'ĝ',
  'Ğ' => 'Ğ',
  'ğ' => 'ğ',
  'Ġ' => 'Ġ',
  'ġ' => 'ġ',
  'Ģ' => 'Ģ',
  'ģ' => 'ģ',
  'Ĥ' => 'Ĥ',
  'ĥ' => 'ĥ',
  'Ĩ' => 'Ĩ',
  'ĩ' => 'ĩ',
  'Ī' => 'Ī',
  'ī' => 'ī',
  'Ĭ' => 'Ĭ',
  'ĭ' => 'ĭ',
  'Į' => 'Į',
  'į' => 'į',
  'İ' => 'İ',
  'Ĵ' => 'Ĵ',
  'ĵ' => 'ĵ',
  'Ķ' => 'Ķ',
  'ķ' => 'ķ',
  'Ĺ' => 'Ĺ',
  'ĺ' => 'ĺ',
  'Ļ' => 'Ļ',
  'ļ' => 'ļ',
  'Ľ' => 'Ľ',
  'ľ' => 'ľ',
  'Ń' => 'Ń',
  'ń' => 'ń',
  'Ņ' => 'Ņ',
  'ņ' => 'ņ',
  'Ň' => 'Ň',
  'ň' => 'ň',
  'Ō' => 'Ō',
  'ō' => 'ō',
  'Ŏ' => 'Ŏ',
  'ŏ' => 'ŏ',
  'Ő' => 'Ő',
  'ő' => 'ő',
  'Ŕ' => 'Ŕ',
  'ŕ' => 'ŕ',
  'Ŗ' => 'Ŗ',
  'ŗ' => 'ŗ',
  'Ř' => 'Ř',
  'ř' => 'ř',
  'Ś' => 'Ś',
  'ś' => 'ś',
  'Ŝ' => 'Ŝ',
  'ŝ' => 'ŝ',
  'Ş' => 'Ş',
  'ş' => 'ş',
  'Š' => 'Š',
  'š' => 'š',
  'Ţ' => 'Ţ',
  'ţ' => 'ţ',
  'Ť' => 'Ť',
  'ť' => 'ť',
  'Ũ' => 'Ũ',
  'ũ' => 'ũ',
  'Ū' => 'Ū',
  'ū' => 'ū',
  'Ŭ' => 'Ŭ',
  'ŭ' => 'ŭ',
  'Ů' => 'Ů',
  'ů' => 'ů',
  'Ű' => 'Ű',
  'ű' => 'ű',
  'Ų' => 'Ų',
  'ų' => 'ų',
  'Ŵ' => 'Ŵ',
  'ŵ' => 'ŵ',
  'Ŷ' => 'Ŷ',
  'ŷ' => 'ŷ',
  'Ÿ' => 'Ÿ',
  'Ź' => 'Ź',
  'ź' => 'ź',
  'Ż' => 'Ż',
  'ż' => 'ż',
  'Ž' => 'Ž',
  'ž' => 'ž',
  'Ơ' => 'Ơ',
  'ơ' => 'ơ',
  'Ư' => 'Ư',
  'ư' => 'ư',
  'Ǎ' => 'Ǎ',
  'ǎ' => 'ǎ',
  'Ǐ' => 'Ǐ',
  'ǐ' => 'ǐ',
  'Ǒ' => 'Ǒ',
  'ǒ' => 'ǒ',
  'Ǔ' => 'Ǔ',
  'ǔ' => 'ǔ',
  'Ǖ' => 'Ǖ',
  'ǖ' => 'ǖ',
  'Ǘ' => 'Ǘ',
  'ǘ' => 'ǘ',
  'Ǚ' => 'Ǚ',
  'ǚ' => 'ǚ',
  'Ǜ' => 'Ǜ',
  'ǜ' => 'ǜ',
  'Ǟ' => 'Ǟ',
  'ǟ' => 'ǟ',
  'Ǡ' => 'Ǡ',
  'ǡ' => 'ǡ',
  'Ǣ' => 'Ǣ',
  'ǣ' => 'ǣ',
  'Ǧ' => 'Ǧ',
  'ǧ' => 'ǧ',
  'Ǩ' => 'Ǩ',
  'ǩ' => 'ǩ',
  'Ǫ' => 'Ǫ',
  'ǫ' => 'ǫ',
  'Ǭ' => 'Ǭ',
  'ǭ' => 'ǭ',
  'Ǯ' => 'Ǯ',
  'ǯ' => 'ǯ',
  'ǰ' => 'ǰ',
  'Ǵ' => 'Ǵ',
  'ǵ' => 'ǵ',
  'Ǹ' => 'Ǹ',
  'ǹ' => 'ǹ',
  'Ǻ' => 'Ǻ',
  'ǻ' => 'ǻ',
  'Ǽ' => 'Ǽ',
  'ǽ' => 'ǽ',
  'Ǿ' => 'Ǿ',
  'ǿ' => 'ǿ',
  'Ȁ' => 'Ȁ',
  'ȁ' => 'ȁ',
  'Ȃ' => 'Ȃ',
  'ȃ' => 'ȃ',
  'Ȅ' => 'Ȅ',
  'ȅ' => 'ȅ',
  'Ȇ' => 'Ȇ',
  'ȇ' => 'ȇ',
  'Ȉ' => 'Ȉ',
  'ȉ' => 'ȉ',
  'Ȋ' => 'Ȋ',
  'ȋ' => 'ȋ',
  'Ȍ' => 'Ȍ',
  'ȍ' => 'ȍ',
  'Ȏ' => 'Ȏ',
  'ȏ' => 'ȏ',
  'Ȑ' => 'Ȑ',
  'ȑ' => 'ȑ',
  'Ȓ' => 'Ȓ',
  'ȓ' => 'ȓ',
  'Ȕ' => 'Ȕ',
  'ȕ' => 'ȕ',
  'Ȗ' => 'Ȗ',
  'ȗ' => 'ȗ',
  'Ș' => 'Ș',
  'ș' => 'ș',
  'Ț' => 'Ț',
  'ț' => 'ț',
  'Ȟ' => 'Ȟ',
  'ȟ' => 'ȟ',
  'Ȧ' => 'Ȧ',
  'ȧ' => 'ȧ',
  'Ȩ' => 'Ȩ',
  'ȩ' => 'ȩ',
  'Ȫ' => 'Ȫ',
  'ȫ' => 'ȫ',
  'Ȭ' => 'Ȭ',
  'ȭ' => 'ȭ',
  'Ȯ' => 'Ȯ',
  'ȯ' => 'ȯ',
  'Ȱ' => 'Ȱ',
  'ȱ' => 'ȱ',
  'Ȳ' => 'Ȳ',
  'ȳ' => 'ȳ',
  '̀' => '̀',
  '́' => '́',
  '̓' => '̓',
  '̈́' => '̈́',
  'ʹ' => 'ʹ',
  ';' => ';',
  '΅' => '΅',
  'Ά' => 'Ά',
  '·' => '·',
  'Έ' => 'Έ',
  'Ή' => 'Ή',
  'Ί' => 'Ί',
  'Ό' => 'Ό',
  'Ύ' => 'Ύ',
  'Ώ' => 'Ώ',
  'ΐ' => 'ΐ',
  'Ϊ' => 'Ϊ',
  'Ϋ' => 'Ϋ',
  'ά' => 'ά',
  'έ' => 'έ',
  'ή' => 'ή',
  'ί' => 'ί',
  'ΰ' => 'ΰ',
  'ϊ' => 'ϊ',
  'ϋ' => 'ϋ',
  'ό' => 'ό',
  'ύ' => 'ύ',
  'ώ' => 'ώ',
  'ϓ' => 'ϓ',
  'ϔ' => 'ϔ',
  'Ѐ' => 'Ѐ',
  'Ё' => 'Ё',
  'Ѓ' => 'Ѓ',
  'Ї' => 'Ї',
  'Ќ' => 'Ќ',
  'Ѝ' => 'Ѝ',
  'Ў' => 'Ў',
  'Й' => 'Й',
  'й' => 'й',
  'ѐ' => 'ѐ',
  'ё' => 'ё',
  'ѓ' => 'ѓ',
  'ї' => 'ї',
  'ќ' => 'ќ',
  'ѝ' => 'ѝ',
  'ў' => 'ў',
  'Ѷ' => 'Ѷ',
  'ѷ' => 'ѷ',
  'Ӂ' => 'Ӂ',
  'ӂ' => 'ӂ',
  'Ӑ' => 'Ӑ',
  'ӑ' => 'ӑ',
  'Ӓ' => 'Ӓ',
  'ӓ' => 'ӓ',
  'Ӗ' => 'Ӗ',
  'ӗ' => 'ӗ',
  'Ӛ' => 'Ӛ',
  'ӛ' => 'ӛ',
  'Ӝ' => 'Ӝ',
  'ӝ' => 'ӝ',
  'Ӟ' => 'Ӟ',
  'ӟ' => 'ӟ',
  'Ӣ' => 'Ӣ',
  'ӣ' => 'ӣ',
  'Ӥ' => 'Ӥ',
  'ӥ' => 'ӥ',
  'Ӧ' => 'Ӧ',
  'ӧ' => 'ӧ',
  'Ӫ' => 'Ӫ',
  'ӫ' => 'ӫ',
  'Ӭ' => 'Ӭ',
  'ӭ' => 'ӭ',
  'Ӯ' => 'Ӯ',
  'ӯ' => 'ӯ',
  'Ӱ' => 'Ӱ',
  'ӱ' => 'ӱ',
  'Ӳ' => 'Ӳ',
  'ӳ' => 'ӳ',
  'Ӵ' => 'Ӵ',
  'ӵ' => 'ӵ',
  'Ӹ' => 'Ӹ',
  'ӹ' => 'ӹ',
  'آ' => 'آ',
  'أ' => 'أ',
  'ؤ' => 'ؤ',
  'إ' => 'إ',
  'ئ' => 'ئ',
  'ۀ' => 'ۀ',
  'ۂ' => 'ۂ',
  'ۓ' => 'ۓ',
  'ऩ' => 'ऩ',
  'ऱ' => 'ऱ',
  'ऴ' => 'ऴ',
  'क़' => 'क़',
  'ख़' => 'ख़',
  'ग़' => 'ग़',
  'ज़' => 'ज़',
  'ड़' => 'ड़',
  'ढ़' => 'ढ़',
  'फ़' => 'फ़',
  'य़' => 'य़',
  'ো' => 'ো',
  'ৌ' => 'ৌ',
  'ড়' => 'ড়',
  'ঢ়' => 'ঢ়',
  'য়' => 'য়',
  'ਲ਼' => 'ਲ਼',
  'ਸ਼' => 'ਸ਼',
  'ਖ਼' => 'ਖ਼',
  'ਗ਼' => 'ਗ਼',
  'ਜ਼' => 'ਜ਼',
  'ਫ਼' => 'ਫ਼',
  'ୈ' => 'ୈ',
  'ୋ' => 'ୋ',
  'ୌ' => 'ୌ',
  'ଡ଼' => 'ଡ଼',
  'ଢ଼' => 'ଢ଼',
  'ஔ' => 'ஔ',
  'ொ' => 'ொ',
  'ோ' => 'ோ',
  'ௌ' => 'ௌ',
  'ై' => 'ై',
  'ೀ' => 'ೀ',
  'ೇ' => 'ೇ',
  'ೈ' => 'ೈ',
  'ೊ' => 'ೊ',
  'ೋ' => 'ೋ',
  'ൊ' => 'ൊ',
  'ോ' => 'ോ',
  'ൌ' => 'ൌ',
  'ේ' => 'ේ',
  'ො' => 'ො',
  'ෝ' => 'ෝ',
  'ෞ' => 'ෞ',
  'གྷ' => 'གྷ',
  'ཌྷ' => 'ཌྷ',
  'དྷ' => 'དྷ',
  'བྷ' => 'བྷ',
  'ཛྷ' => 'ཛྷ',
  'ཀྵ' => 'ཀྵ',
  'ཱི' => 'ཱི',
  'ཱུ' => 'ཱུ',
  'ྲྀ' => 'ྲྀ',
  'ླྀ' => 'ླྀ',
  'ཱྀ' => 'ཱྀ',
  'ྒྷ' => 'ྒྷ',
  'ྜྷ' => 'ྜྷ',
  'ྡྷ' => 'ྡྷ',
  'ྦྷ' => 'ྦྷ',
  'ྫྷ' => 'ྫྷ',
  'ྐྵ' => 'ྐྵ',
  'ဦ' => 'ဦ',
  'ᬆ' => 'ᬆ',
  'ᬈ' => 'ᬈ',
  'ᬊ' => 'ᬊ',
  'ᬌ' => 'ᬌ',
  'ᬎ' => 'ᬎ',
  'ᬒ' => 'ᬒ',
  'ᬻ' => 'ᬻ',
  'ᬽ' => 'ᬽ',
  'ᭀ' => 'ᭀ',
  'ᭁ' => 'ᭁ',
  'ᭃ' => 'ᭃ',
  'Ḁ' => 'Ḁ',
  'ḁ' => 'ḁ',
  'Ḃ' => 'Ḃ',
  'ḃ' => 'ḃ',
  'Ḅ' => 'Ḅ',
  'ḅ' => 'ḅ',
  'Ḇ' => 'Ḇ',
  'ḇ' => 'ḇ',
  'Ḉ' => 'Ḉ',
  'ḉ' => 'ḉ',
  'Ḋ' => 'Ḋ',
  'ḋ' => 'ḋ',
  'Ḍ' => 'Ḍ',
  'ḍ' => 'ḍ',
  'Ḏ' => 'Ḏ',
  'ḏ' => 'ḏ',
  'Ḑ' => 'Ḑ',
  'ḑ' => 'ḑ',
  'Ḓ' => 'Ḓ',
  'ḓ' => 'ḓ',
  'Ḕ' => 'Ḕ',
  'ḕ' => 'ḕ',
  'Ḗ' => 'Ḗ',
  'ḗ' => 'ḗ',
  'Ḙ' => 'Ḙ',
  'ḙ' => 'ḙ',
  'Ḛ' => 'Ḛ',
  'ḛ' => 'ḛ',
  'Ḝ' => 'Ḝ',
  'ḝ' => 'ḝ',
  'Ḟ' => 'Ḟ',
  'ḟ' => 'ḟ',
  'Ḡ' => 'Ḡ',
  'ḡ' => 'ḡ',
  'Ḣ' => 'Ḣ',
  'ḣ' => 'ḣ',
  'Ḥ' => 'Ḥ',
  'ḥ' => 'ḥ',
  'Ḧ' => 'Ḧ',
  'ḧ' => 'ḧ',
  'Ḩ' => 'Ḩ',
  'ḩ' => 'ḩ',
  'Ḫ' => 'Ḫ',
  'ḫ' => 'ḫ',
  'Ḭ' => 'Ḭ',
  'ḭ' => 'ḭ',
  'Ḯ' => 'Ḯ',
  'ḯ' => 'ḯ',
  'Ḱ' => 'Ḱ',
  'ḱ' => 'ḱ',
  'Ḳ' => 'Ḳ',
  'ḳ' => 'ḳ',
  'Ḵ' => 'Ḵ',
  'ḵ' => 'ḵ',
  'Ḷ' => 'Ḷ',
  'ḷ' => 'ḷ',
  'Ḹ' => 'Ḹ',
  'ḹ' => 'ḹ',
  'Ḻ' => 'Ḻ',
  'ḻ' => 'ḻ',
  'Ḽ' => 'Ḽ',
  'ḽ' => 'ḽ',
  'Ḿ' => 'Ḿ',
  'ḿ' => 'ḿ',
  'Ṁ' => 'Ṁ',
  'ṁ' => 'ṁ',
  'Ṃ' => 'Ṃ',
  'ṃ' => 'ṃ',
  'Ṅ' => 'Ṅ',
  'ṅ' => 'ṅ',
  'Ṇ' => 'Ṇ',
  'ṇ' => 'ṇ',
  'Ṉ' => 'Ṉ',
  'ṉ' => 'ṉ',
  'Ṋ' => 'Ṋ',
  'ṋ' => 'ṋ',
  'Ṍ' => 'Ṍ',
  'ṍ' => 'ṍ',
  'Ṏ' => 'Ṏ',
  'ṏ' => 'ṏ',
  'Ṑ' => 'Ṑ',
  'ṑ' => 'ṑ',
  'Ṓ' => 'Ṓ',
  'ṓ' => 'ṓ',
  'Ṕ' => 'Ṕ',
  'ṕ' => 'ṕ',
  'Ṗ' => 'Ṗ',
  'ṗ' => 'ṗ',
  'Ṙ' => 'Ṙ',
  'ṙ' => 'ṙ',
  'Ṛ' => 'Ṛ',
  'ṛ' => 'ṛ',
  'Ṝ' => 'Ṝ',
  'ṝ' => 'ṝ',
  'Ṟ' => 'Ṟ',
  'ṟ' => 'ṟ',
  'Ṡ' => 'Ṡ',
  'ṡ' => 'ṡ',
  'Ṣ' => 'Ṣ',
  'ṣ' => 'ṣ',
  'Ṥ' => 'Ṥ',
  'ṥ' => 'ṥ',
  'Ṧ' => 'Ṧ',
  'ṧ' => 'ṧ',
  'Ṩ' => 'Ṩ',
  'ṩ' => 'ṩ',
  'Ṫ' => 'Ṫ',
  'ṫ' => 'ṫ',
  'Ṭ' => 'Ṭ',
  'ṭ' => 'ṭ',
  'Ṯ' => 'Ṯ',
  'ṯ' => 'ṯ',
  'Ṱ' => 'Ṱ',
  'ṱ' => 'ṱ',
  'Ṳ' => 'Ṳ',
  'ṳ' => 'ṳ',
  'Ṵ' => 'Ṵ',
  'ṵ' => 'ṵ',
  'Ṷ' => 'Ṷ',
  'ṷ' => 'ṷ',
  'Ṹ' => 'Ṹ',
  'ṹ' => 'ṹ',
  'Ṻ' => 'Ṻ',
  'ṻ' => 'ṻ',
  'Ṽ' => 'Ṽ',
  'ṽ' => 'ṽ',
  'Ṿ' => 'Ṿ',
  'ṿ' => 'ṿ',
  'Ẁ' => 'Ẁ',
  'ẁ' => 'ẁ',
  'Ẃ' => 'Ẃ',
  'ẃ' => 'ẃ',
  'Ẅ' => 'Ẅ',
  'ẅ' => 'ẅ',
  'Ẇ' => 'Ẇ',
  'ẇ' => 'ẇ',
  'Ẉ' => 'Ẉ',
  'ẉ' => 'ẉ',
  'Ẋ' => 'Ẋ',
  'ẋ' => 'ẋ',
  'Ẍ' => 'Ẍ',
  'ẍ' => 'ẍ',
  'Ẏ' => 'Ẏ',
  'ẏ' => 'ẏ',
  'Ẑ' => 'Ẑ',
  'ẑ' => 'ẑ',
  'Ẓ' => 'Ẓ',
  'ẓ' => 'ẓ',
  'Ẕ' => 'Ẕ',
  'ẕ' => 'ẕ',
  'ẖ' => 'ẖ',
  'ẗ' => 'ẗ',
  'ẘ' => 'ẘ',
  'ẙ' => 'ẙ',
  'ẛ' => 'ẛ',
  'Ạ' => 'Ạ',
  'ạ' => 'ạ',
  'Ả' => 'Ả',
  'ả' => 'ả',
  'Ấ' => 'Ấ',
  'ấ' => 'ấ',
  'Ầ' => 'Ầ',
  'ầ' => 'ầ',
  'Ẩ' => 'Ẩ',
  'ẩ' => 'ẩ',
  'Ẫ' => 'Ẫ',
  'ẫ' => 'ẫ',
  'Ậ' => 'Ậ',
  'ậ' => 'ậ',
  'Ắ' => 'Ắ',
  'ắ' => 'ắ',
  'Ằ' => 'Ằ',
  'ằ' => 'ằ',
  'Ẳ' => 'Ẳ',
  'ẳ' => 'ẳ',
  'Ẵ' => 'Ẵ',
  'ẵ' => 'ẵ',
  'Ặ' => 'Ặ',
  'ặ' => 'ặ',
  'Ẹ' => 'Ẹ',
  'ẹ' => 'ẹ',
  'Ẻ' => 'Ẻ',
  'ẻ' => 'ẻ',
  'Ẽ' => 'Ẽ',
  'ẽ' => 'ẽ',
  'Ế' => 'Ế',
  'ế' => 'ế',
  'Ề' => 'Ề',
  'ề' => 'ề',
  'Ể' => 'Ể',
  'ể' => 'ể',
  'Ễ' => 'Ễ',
  'ễ' => 'ễ',
  'Ệ' => 'Ệ',
  'ệ' => 'ệ',
  'Ỉ' => 'Ỉ',
  'ỉ' => 'ỉ',
  'Ị' => 'Ị',
  'ị' => 'ị',
  'Ọ' => 'Ọ',
  'ọ' => 'ọ',
  'Ỏ' => 'Ỏ',
  'ỏ' => 'ỏ',
  'Ố' => 'Ố',
  'ố' => 'ố',
  'Ồ' => 'Ồ',
  'ồ' => 'ồ',
  'Ổ' => 'Ổ',
  'ổ' => 'ổ',
  'Ỗ' => 'Ỗ',
  'ỗ' => 'ỗ',
  'Ộ' => 'Ộ',
  'ộ' => 'ộ',
  'Ớ' => 'Ớ',
  'ớ' => 'ớ',
  'Ờ' => 'Ờ',
  'ờ' => 'ờ',
  'Ở' => 'Ở',
  'ở' => 'ở',
  'Ỡ' => 'Ỡ',
  'ỡ' => 'ỡ',
  'Ợ' => 'Ợ',
  'ợ' => 'ợ',
  'Ụ' => 'Ụ',
  'ụ' => 'ụ',
  'Ủ' => 'Ủ',
  'ủ' => 'ủ',
  'Ứ' => 'Ứ',
  'ứ' => 'ứ',
  'Ừ' => 'Ừ',
  'ừ' => 'ừ',
  'Ử' => 'Ử',
  'ử' => 'ử',
  'Ữ' => 'Ữ',
  'ữ' => 'ữ',
  'Ự' => 'Ự',
  'ự' => 'ự',
  'Ỳ' => 'Ỳ',
  'ỳ' => 'ỳ',
  'Ỵ' => 'Ỵ',
  'ỵ' => 'ỵ',
  'Ỷ' => 'Ỷ',
  'ỷ' => 'ỷ',
  'Ỹ' => 'Ỹ',
  'ỹ' => 'ỹ',
  'ἀ' => 'ἀ',
  'ἁ' => 'ἁ',
  'ἂ' => 'ἂ',
  'ἃ' => 'ἃ',
  'ἄ' => 'ἄ',
  'ἅ' => 'ἅ',
  'ἆ' => 'ἆ',
  'ἇ' => 'ἇ',
  'Ἀ' => 'Ἀ',
  'Ἁ' => 'Ἁ',
  'Ἂ' => 'Ἂ',
  'Ἃ' => 'Ἃ',
  'Ἄ' => 'Ἄ',
  'Ἅ' => 'Ἅ',
  'Ἆ' => 'Ἆ',
  'Ἇ' => 'Ἇ',
  'ἐ' => 'ἐ',
  'ἑ' => 'ἑ',
  'ἒ' => 'ἒ',
  'ἓ' => 'ἓ',
  'ἔ' => 'ἔ',
  'ἕ' => 'ἕ',
  'Ἐ' => 'Ἐ',
  'Ἑ' => 'Ἑ',
  'Ἒ' => 'Ἒ',
  'Ἓ' => 'Ἓ',
  'Ἔ' => 'Ἔ',
  'Ἕ' => 'Ἕ',
  'ἠ' => 'ἠ',
  'ἡ' => 'ἡ',
  'ἢ' => 'ἢ',
  'ἣ' => 'ἣ',
  'ἤ' => 'ἤ',
  'ἥ' => 'ἥ',
  'ἦ' => 'ἦ',
  'ἧ' => 'ἧ',
  'Ἠ' => 'Ἠ',
  'Ἡ' => 'Ἡ',
  'Ἢ' => 'Ἢ',
  'Ἣ' => 'Ἣ',
  'Ἤ' => 'Ἤ',
  'Ἥ' => 'Ἥ',
  'Ἦ' => 'Ἦ',
  'Ἧ' => 'Ἧ',
  'ἰ' => 'ἰ',
  'ἱ' => 'ἱ',
  'ἲ' => 'ἲ',
  'ἳ' => 'ἳ',
  'ἴ' => 'ἴ',
  'ἵ' => 'ἵ',
  'ἶ' => 'ἶ',
  'ἷ' => 'ἷ',
  'Ἰ' => 'Ἰ',
  'Ἱ' => 'Ἱ',
  'Ἲ' => 'Ἲ',
  'Ἳ' => 'Ἳ',
  'Ἴ' => 'Ἴ',
  'Ἵ' => 'Ἵ',
  'Ἶ' => 'Ἶ',
  'Ἷ' => 'Ἷ',
  'ὀ' => 'ὀ',
  'ὁ' => 'ὁ',
  'ὂ' => 'ὂ',
  'ὃ' => 'ὃ',
  'ὄ' => 'ὄ',
  'ὅ' => 'ὅ',
  'Ὀ' => 'Ὀ',
  'Ὁ' => 'Ὁ',
  'Ὂ' => 'Ὂ',
  'Ὃ' => 'Ὃ',
  'Ὄ' => 'Ὄ',
  'Ὅ' => 'Ὅ',
  'ὐ' => 'ὐ',
  'ὑ' => 'ὑ',
  'ὒ' => 'ὒ',
  'ὓ' => 'ὓ',
  'ὔ' => 'ὔ',
  'ὕ' => 'ὕ',
  'ὖ' => 'ὖ',
  'ὗ' => 'ὗ',
  'Ὑ' => 'Ὑ',
  'Ὓ' => 'Ὓ',
  'Ὕ' => 'Ὕ',
  'Ὗ' => 'Ὗ',
  'ὠ' => 'ὠ',
  'ὡ' => 'ὡ',
  'ὢ' => 'ὢ',
  'ὣ' => 'ὣ',
  'ὤ' => 'ὤ',
  'ὥ' => 'ὥ',
  'ὦ' => 'ὦ',
  'ὧ' => 'ὧ',
  'Ὠ' => 'Ὠ',
  'Ὡ' => 'Ὡ',
  'Ὢ' => 'Ὢ',
  'Ὣ' => 'Ὣ',
  'Ὤ' => 'Ὤ',
  'Ὥ' => 'Ὥ',
  'Ὦ' => 'Ὦ',
  'Ὧ' => 'Ὧ',
  'ὰ' => 'ὰ',
  'ά' => 'ά',
  'ὲ' => 'ὲ',
  'έ' => 'έ',
  'ὴ' => 'ὴ',
  'ή' => 'ή',
  'ὶ' => 'ὶ',
  'ί' => 'ί',
  'ὸ' => 'ὸ',
  'ό' => 'ό',
  'ὺ' => 'ὺ',
  'ύ' => 'ύ',
  'ὼ' => 'ὼ',
  'ώ' => 'ώ',
  'ᾀ' => 'ᾀ',
  'ᾁ' => 'ᾁ',
  'ᾂ' => 'ᾂ',
  'ᾃ' => 'ᾃ',
  'ᾄ' => 'ᾄ',
  'ᾅ' => 'ᾅ',
  'ᾆ' => 'ᾆ',
  'ᾇ' => 'ᾇ',
  'ᾈ' => 'ᾈ',
  'ᾉ' => 'ᾉ',
  'ᾊ' => 'ᾊ',
  'ᾋ' => 'ᾋ',
  'ᾌ' => 'ᾌ',
  'ᾍ' => 'ᾍ',
  'ᾎ' => 'ᾎ',
  'ᾏ' => 'ᾏ',
  'ᾐ' => 'ᾐ',
  'ᾑ' => 'ᾑ',
  'ᾒ' => 'ᾒ',
  'ᾓ' => 'ᾓ',
  'ᾔ' => 'ᾔ',
  'ᾕ' => 'ᾕ',
  'ᾖ' => 'ᾖ',
  'ᾗ' => 'ᾗ',
  'ᾘ' => 'ᾘ',
  'ᾙ' => 'ᾙ',
  'ᾚ' => 'ᾚ',
  'ᾛ' => 'ᾛ',
  'ᾜ' => 'ᾜ',
  'ᾝ' => 'ᾝ',
  'ᾞ' => 'ᾞ',
  'ᾟ' => 'ᾟ',
  'ᾠ' => 'ᾠ',
  'ᾡ' => 'ᾡ',
  'ᾢ' => 'ᾢ',
  'ᾣ' => 'ᾣ',
  'ᾤ' => 'ᾤ',
  'ᾥ' => 'ᾥ',
  'ᾦ' => 'ᾦ',
  'ᾧ' => 'ᾧ',
  'ᾨ' => 'ᾨ',
  'ᾩ' => 'ᾩ',
  'ᾪ' => 'ᾪ',
  'ᾫ' => 'ᾫ',
  'ᾬ' => 'ᾬ',
  'ᾭ' => 'ᾭ',
  'ᾮ' => 'ᾮ',
  'ᾯ' => 'ᾯ',
  'ᾰ' => 'ᾰ',
  'ᾱ' => 'ᾱ',
  'ᾲ' => 'ᾲ',
  'ᾳ' => 'ᾳ',
  'ᾴ' => 'ᾴ',
  'ᾶ' => 'ᾶ',
  'ᾷ' => 'ᾷ',
  'Ᾰ' => 'Ᾰ',
  'Ᾱ' => 'Ᾱ',
  'Ὰ' => 'Ὰ',
  'Ά' => 'Ά',
  'ᾼ' => 'ᾼ',
  'ι' => 'ι',
  '῁' => '῁',
  'ῂ' => 'ῂ',
  'ῃ' => 'ῃ',
  'ῄ' => 'ῄ',
  'ῆ' => 'ῆ',
  'ῇ' => 'ῇ',
  'Ὲ' => 'Ὲ',
  'Έ' => 'Έ',
  'Ὴ' => 'Ὴ',
  'Ή' => 'Ή',
  'ῌ' => 'ῌ',
  '῍' => '῍',
  '῎' => '῎',
  '῏' => '῏',
  'ῐ' => 'ῐ',
  'ῑ' => 'ῑ',
  'ῒ' => 'ῒ',
  'ΐ' => 'ΐ',
  'ῖ' => 'ῖ',
  'ῗ' => 'ῗ',
  'Ῐ' => 'Ῐ',
  'Ῑ' => 'Ῑ',
  'Ὶ' => 'Ὶ',
  'Ί' => 'Ί',
  '῝' => '῝',
  '῞' => '῞',
  '῟' => '῟',
  'ῠ' => 'ῠ',
  'ῡ' => 'ῡ',
  'ῢ' => 'ῢ',
  'ΰ' => 'ΰ',
  'ῤ' => 'ῤ',
  'ῥ' => 'ῥ',
  'ῦ' => 'ῦ',
  'ῧ' => 'ῧ',
  'Ῠ' => 'Ῠ',
  'Ῡ' => 'Ῡ',
  'Ὺ' => 'Ὺ',
  'Ύ' => 'Ύ',
  'Ῥ' => 'Ῥ',
  '῭' => '῭',
  '΅' => '΅',
  '`' => '`',
  'ῲ' => 'ῲ',
  'ῳ' => 'ῳ',
  'ῴ' => 'ῴ',
  'ῶ' => 'ῶ',
  'ῷ' => 'ῷ',
  'Ὸ' => 'Ὸ',
  'Ό' => 'Ό',
  'Ὼ' => 'Ὼ',
  'Ώ' => 'Ώ',
  'ῼ' => 'ῼ',
  '´' => '´',
  ' ' => ' ',
  ' ' => ' ',
  'Ω' => 'Ω',
  'K' => 'K',
  'Å' => 'Å',
  '↚' => '↚',
  '↛' => '↛',
  '↮' => '↮',
  '⇍' => '⇍',
  '⇎' => '⇎',
  '⇏' => '⇏',
  '∄' => '∄',
  '∉' => '∉',
  '∌' => '∌',
  '∤' => '∤',
  '∦' => '∦',
  '≁' => '≁',
  '≄' => '≄',
  '≇' => '≇',
  '≉' => '≉',
  '≠' => '≠',
  '≢' => '≢',
  '≭' => '≭',
  '≮' => '≮',
  '≯' => '≯',
  '≰' => '≰',
  '≱' => '≱',
  '≴' => '≴',
  '≵' => '≵',
  '≸' => '≸',
  '≹' => '≹',
  '⊀' => '⊀',
  '⊁' => '⊁',
  '⊄' => '⊄',
  '⊅' => '⊅',
  '⊈' => '⊈',
  '⊉' => '⊉',
  '⊬' => '⊬',
  '⊭' => '⊭',
  '⊮' => '⊮',
  '⊯' => '⊯',
  '⋠' => '⋠',
  '⋡' => '⋡',
  '⋢' => '⋢',
  '⋣' => '⋣',
  '⋪' => '⋪',
  '⋫' => '⋫',
  '⋬' => '⋬',
  '⋭' => '⋭',
  '〈' => '〈',
  '〉' => '〉',
  '⫝̸' => '⫝̸',
  'が' => 'が',
  'ぎ' => 'ぎ',
  'ぐ' => 'ぐ',
  'げ' => 'げ',
  'ご' => 'ご',
  'ざ' => 'ざ',
  'じ' => 'じ',
  'ず' => 'ず',
  'ぜ' => 'ぜ',
  'ぞ' => 'ぞ',
  'だ' => 'だ',
  'ぢ' => 'ぢ',
  'づ' => 'づ',
  'で' => 'で',
  'ど' => 'ど',
  'ば' => 'ば',
  'ぱ' => 'ぱ',
  'び' => 'び',
  'ぴ' => 'ぴ',
  'ぶ' => 'ぶ',
  'ぷ' => 'ぷ',
  'べ' => 'べ',
  'ぺ' => 'ぺ',
  'ぼ' => 'ぼ',
  'ぽ' => 'ぽ',
  'ゔ' => 'ゔ',
  'ゞ' => 'ゞ',
  'ガ' => 'ガ',
  'ギ' => 'ギ',
  'グ' => 'グ',
  'ゲ' => 'ゲ',
  'ゴ' => 'ゴ',
  'ザ' => 'ザ',
  'ジ' => 'ジ',
  'ズ' => 'ズ',
  'ゼ' => 'ゼ',
  'ゾ' => 'ゾ',
  'ダ' => 'ダ',
  'ヂ' => 'ヂ',
  'ヅ' => 'ヅ',
  'デ' => 'デ',
  'ド' => 'ド',
  'バ' => 'バ',
  'パ' => 'パ',
  'ビ' => 'ビ',
  'ピ' => 'ピ',
  'ブ' => 'ブ',
  'プ' => 'プ',
  'ベ' => 'ベ',
  'ペ' => 'ペ',
  'ボ' => 'ボ',
  'ポ' => 'ポ',
  'ヴ' => 'ヴ',
  'ヷ' => 'ヷ',
  'ヸ' => 'ヸ',
  'ヹ' => 'ヹ',
  'ヺ' => 'ヺ',
  'ヾ' => 'ヾ',
  '豈' => '豈',
  '更' => '更',
  '車' => '車',
  '賈' => '賈',
  '滑' => '滑',
  '串' => '串',
  '句' => '句',
  '龜' => '龜',
  '龜' => '龜',
  '契' => '契',
  '金' => '金',
  '喇' => '喇',
  '奈' => '奈',
  '懶' => '懶',
  '癩' => '癩',
  '羅' => '羅',
  '蘿' => '蘿',
  '螺' => '螺',
  '裸' => '裸',
  '邏' => '邏',
  '樂' => '樂',
  '洛' => '洛',
  '烙' => '烙',
  '珞' => '珞',
  '落' => '落',
  '酪' => '酪',
  '駱' => '駱',
  '亂' => '亂',
  '卵' => '卵',
  '欄' => '欄',
  '爛' => '爛',
  '蘭' => '蘭',
  '鸞' => '鸞',
  '嵐' => '嵐',
  '濫' => '濫',
  '藍' => '藍',
  '襤' => '襤',
  '拉' => '拉',
  '臘' => '臘',
  '蠟' => '蠟',
  '廊' => '廊',
  '朗' => '朗',
  '浪' => '浪',
  '狼' => '狼',
  '郎' => '郎',
  '來' => '來',
  '冷' => '冷',
  '勞' => '勞',
  '擄' => '擄',
  '櫓' => '櫓',
  '爐' => '爐',
  '盧' => '盧',
  '老' => '老',
  '蘆' => '蘆',
  '虜' => '虜',
  '路' => '路',
  '露' => '露',
  '魯' => '魯',
  '鷺' => '鷺',
  '碌' => '碌',
  '祿' => '祿',
  '綠' => '綠',
  '菉' => '菉',
  '錄' => '錄',
  '鹿' => '鹿',
  '論' => '論',
  '壟' => '壟',
  '弄' => '弄',
  '籠' => '籠',
  '聾' => '聾',
  '牢' => '牢',
  '磊' => '磊',
  '賂' => '賂',
  '雷' => '雷',
  '壘' => '壘',
  '屢' => '屢',
  '樓' => '樓',
  '淚' => '淚',
  '漏' => '漏',
  '累' => '累',
  '縷' => '縷',
  '陋' => '陋',
  '勒' => '勒',
  '肋' => '肋',
  '凜' => '凜',
  '凌' => '凌',
  '稜' => '稜',
  '綾' => '綾',
  '菱' => '菱',
  '陵' => '陵',
  '讀' => '讀',
  '拏' => '拏',
  '樂' => '樂',
  '諾' => '諾',
  '丹' => '丹',
  '寧' => '寧',
  '怒' => '怒',
  '率' => '率',
  '異' => '異',
  '北' => '北',
  '磻' => '磻',
  '便' => '便',
  '復' => '復',
  '不' => '不',
  '泌' => '泌',
  '數' => '數',
  '索' => '索',
  '參' => '參',
  '塞' => '塞',
  '省' => '省',
  '葉' => '葉',
  '說' => '說',
  '殺' => '殺',
  '辰' => '辰',
  '沈' => '沈',
  '拾' => '拾',
  '若' => '若',
  '掠' => '掠',
  '略' => '略',
  '亮' => '亮',
  '兩' => '兩',
  '凉' => '凉',
  '梁' => '梁',
  '糧' => '糧',
  '良' => '良',
  '諒' => '諒',
  '量' => '量',
  '勵' => '勵',
  '呂' => '呂',
  '女' => '女',
  '廬' => '廬',
  '旅' => '旅',
  '濾' => '濾',
  '礪' => '礪',
  '閭' => '閭',
  '驪' => '驪',
  '麗' => '麗',
  '黎' => '黎',
  '力' => '力',
  '曆' => '曆',
  '歷' => '歷',
  '轢' => '轢',
  '年' => '年',
  '憐' => '憐',
  '戀' => '戀',
  '撚' => '撚',
  '漣' => '漣',
  '煉' => '煉',
  '璉' => '璉',
  '秊' => '秊',
  '練' => '練',
  '聯' => '聯',
  '輦' => '輦',
  '蓮' => '蓮',
  '連' => '連',
  '鍊' => '鍊',
  '列' => '列',
  '劣' => '劣',
  '咽' => '咽',
  '烈' => '烈',
  '裂' => '裂',
  '說' => '說',
  '廉' => '廉',
  '念' => '念',
  '捻' => '捻',
  '殮' => '殮',
  '簾' => '簾',
  '獵' => '獵',
  '令' => '令',
  '囹' => '囹',
  '寧' => '寧',
  '嶺' => '嶺',
  '怜' => '怜',
  '玲' => '玲',
  '瑩' => '瑩',
  '羚' => '羚',
  '聆' => '聆',
  '鈴' => '鈴',
  '零' => '零',
  '靈' => '靈',
  '領' => '領',
  '例' => '例',
  '禮' => '禮',
  '醴' => '醴',
  '隸' => '隸',
  '惡' => '惡',
  '了' => '了',
  '僚' => '僚',
  '寮' => '寮',
  '尿' => '尿',
  '料' => '料',
  '樂' => '樂',
  '燎' => '燎',
  '療' => '療',
  '蓼' => '蓼',
  '遼' => '遼',
  '龍' => '龍',
  '暈' => '暈',
  '阮' => '阮',
  '劉' => '劉',
  '杻' => '杻',
  '柳' => '柳',
  '流' => '流',
  '溜' => '溜',
  '琉' => '琉',
  '留' => '留',
  '硫' => '硫',
  '紐' => '紐',
  '類' => '類',
  '六' => '六',
  '戮' => '戮',
  '陸' => '陸',
  '倫' => '倫',
  '崙' => '崙',
  '淪' => '淪',
  '輪' => '輪',
  '律' => '律',
  '慄' => '慄',
  '栗' => '栗',
  '率' => '率',
  '隆' => '隆',
  '利' => '利',
  '吏' => '吏',
  '履' => '履',
  '易' => '易',
  '李' => '李',
  '梨' => '梨',
  '泥' => '泥',
  '理' => '理',
  '痢' => '痢',
  '罹' => '罹',
  '裏' => '裏',
  '裡' => '裡',
  '里' => '里',
  '離' => '離',
  '匿' => '匿',
  '溺' => '溺',
  '吝' => '吝',
  '燐' => '燐',
  '璘' => '璘',
  '藺' => '藺',
  '隣' => '隣',
  '鱗' => '鱗',
  '麟' => '麟',
  '林' => '林',
  '淋' => '淋',
  '臨' => '臨',
  '立' => '立',
  '笠' => '笠',
  '粒' => '粒',
  '狀' => '狀',
  '炙' => '炙',
  '識' => '識',
  '什' => '什',
  '茶' => '茶',
  '刺' => '刺',
  '切' => '切',
  '度' => '度',
  '拓' => '拓',
  '糖' => '糖',
  '宅' => '宅',
  '洞' => '洞',
  '暴' => '暴',
  '輻' => '輻',
  '行' => '行',
  '降' => '降',
  '見' => '見',
  '廓' => '廓',
  '兀' => '兀',
  '嗀' => '嗀',
  '塚' => '塚',
  '晴' => '晴',
  '凞' => '凞',
  '猪' => '猪',
  '益' => '益',
  '礼' => '礼',
  '神' => '神',
  '祥' => '祥',
  '福' => '福',
  '靖' => '靖',
  '精' => '精',
  '羽' => '羽',
  '蘒' => '蘒',
  '諸' => '諸',
  '逸' => '逸',
  '都' => '都',
  '飯' => '飯',
  '飼' => '飼',
  '館' => '館',
  '鶴' => '鶴',
  '郞' => '郞',
  '隷' => '隷',
  '侮' => '侮',
  '僧' => '僧',
  '免' => '免',
  '勉' => '勉',
  '勤' => '勤',
  '卑' => '卑',
  '喝' => '喝',
  '嘆' => '嘆',
  '器' => '器',
  '塀' => '塀',
  '墨' => '墨',
  '層' => '層',
  '屮' => '屮',
  '悔' => '悔',
  '慨' => '慨',
  '憎' => '憎',
  '懲' => '懲',
  '敏' => '敏',
  '既' => '既',
  '暑' => '暑',
  '梅' => '梅',
  '海' => '海',
  '渚' => '渚',
  '漢' => '漢',
  '煮' => '煮',
  '爫' => '爫',
  '琢' => '琢',
  '碑' => '碑',
  '社' => '社',
  '祉' => '祉',
  '祈' => '祈',
  '祐' => '祐',
  '祖' => '祖',
  '祝' => '祝',
  '禍' => '禍',
  '禎' => '禎',
  '穀' => '穀',
  '突' => '突',
  '節' => '節',
  '練' => '練',
  '縉' => '縉',
  '繁' => '繁',
  '署' => '署',
  '者' => '者',
  '臭' => '臭',
  '艹' => '艹',
  '艹' => '艹',
  '著' => '著',
  '褐' => '褐',
  '視' => '視',
  '謁' => '謁',
  '謹' => '謹',
  '賓' => '賓',
  '贈' => '贈',
  '辶' => '辶',
  '逸' => '逸',
  '難' => '難',
  '響' => '響',
  '頻' => '頻',
  '恵' => '恵',
  '𤋮' => '𤋮',
  '舘' => '舘',
  '並' => '並',
  '况' => '况',
  '全' => '全',
  '侀' => '侀',
  '充' => '充',
  '冀' => '冀',
  '勇' => '勇',
  '勺' => '勺',
  '喝' => '喝',
  '啕' => '啕',
  '喙' => '喙',
  '嗢' => '嗢',
  '塚' => '塚',
  '墳' => '墳',
  '奄' => '奄',
  '奔' => '奔',
  '婢' => '婢',
  '嬨' => '嬨',
  '廒' => '廒',
  '廙' => '廙',
  '彩' => '彩',
  '徭' => '徭',
  '惘' => '惘',
  '慎' => '慎',
  '愈' => '愈',
  '憎' => '憎',
  '慠' => '慠',
  '懲' => '懲',
  '戴' => '戴',
  '揄' => '揄',
  '搜' => '搜',
  '摒' => '摒',
  '敖' => '敖',
  '晴' => '晴',
  '朗' => '朗',
  '望' => '望',
  '杖' => '杖',
  '歹' => '歹',
  '殺' => '殺',
  '流' => '流',
  '滛' => '滛',
  '滋' => '滋',
  '漢' => '漢',
  '瀞' => '瀞',
  '煮' => '煮',
  '瞧' => '瞧',
  '爵' => '爵',
  '犯' => '犯',
  '猪' => '猪',
  '瑱' => '瑱',
  '甆' => '甆',
  '画' => '画',
  '瘝' => '瘝',
  '瘟' => '瘟',
  '益' => '益',
  '盛' => '盛',
  '直' => '直',
  '睊' => '睊',
  '着' => '着',
  '磌' => '磌',
  '窱' => '窱',
  '節' => '節',
  '类' => '类',
  '絛' => '絛',
  '練' => '練',
  '缾' => '缾',
  '者' => '者',
  '荒' => '荒',
  '華' => '華',
  '蝹' => '蝹',
  '襁' => '襁',
  '覆' => '覆',
  '視' => '視',
  '調' => '調',
  '諸' => '諸',
  '請' => '請',
  '謁' => '謁',
  '諾' => '諾',
  '諭' => '諭',
  '謹' => '謹',
  '變' => '變',
  '贈' => '贈',
  '輸' => '輸',
  '遲' => '遲',
  '醙' => '醙',
  '鉶' => '鉶',
  '陼' => '陼',
  '難' => '難',
  '靖' => '靖',
  '韛' => '韛',
  '響' => '響',
  '頋' => '頋',
  '頻' => '頻',
  '鬒' => '鬒',
  '龜' => '龜',
  '𢡊' => '𢡊',
  '𢡄' => '𢡄',
  '𣏕' => '𣏕',
  '㮝' => '㮝',
  '䀘' => '䀘',
  '䀹' => '䀹',
  '𥉉' => '𥉉',
  '𥳐' => '𥳐',
  '𧻓' => '𧻓',
  '齃' => '齃',
  '龎' => '龎',
  'יִ' => 'יִ',
  'ײַ' => 'ײַ',
  'שׁ' => 'שׁ',
  'שׂ' => 'שׂ',
  'שּׁ' => 'שּׁ',
  'שּׂ' => 'שּׂ',
  'אַ' => 'אַ',
  'אָ' => 'אָ',
  'אּ' => 'אּ',
  'בּ' => 'בּ',
  'גּ' => 'גּ',
  'דּ' => 'דּ',
  'הּ' => 'הּ',
  'וּ' => 'וּ',
  'זּ' => 'זּ',
  'טּ' => 'טּ',
  'יּ' => 'יּ',
  'ךּ' => 'ךּ',
  'כּ' => 'כּ',
  'לּ' => 'לּ',
  'מּ' => 'מּ',
  'נּ' => 'נּ',
  'סּ' => 'סּ',
  'ףּ' => 'ףּ',
  'פּ' => 'פּ',
  'צּ' => 'צּ',
  'קּ' => 'קּ',
  'רּ' => 'רּ',
  'שּ' => 'שּ',
  'תּ' => 'תּ',
  'וֹ' => 'וֹ',
  'בֿ' => 'בֿ',
  'כֿ' => 'כֿ',
  'פֿ' => 'פֿ',
  '𑂚' => '𑂚',
  '𑂜' => '𑂜',
  '𑂫' => '𑂫',
  '𑄮' => '𑄮',
  '𑄯' => '𑄯',
  '𑍋' => '𑍋',
  '𑍌' => '𑍌',
  '𑒻' => '𑒻',
  '𑒼' => '𑒼',
  '𑒾' => '𑒾',
  '𑖺' => '𑖺',
  '𑖻' => '𑖻',
  '𑤸' => '𑤸',
  '𝅗𝅥' => '𝅗𝅥',
  '𝅘𝅥' => '𝅘𝅥',
  '𝅘𝅥𝅮' => '𝅘𝅥𝅮',
  '𝅘𝅥𝅯' => '𝅘𝅥𝅯',
  '𝅘𝅥𝅰' => '𝅘𝅥𝅰',
  '𝅘𝅥𝅱' => '𝅘𝅥𝅱',
  '𝅘𝅥𝅲' => '𝅘𝅥𝅲',
  '𝆹𝅥' => '𝆹𝅥',
  '𝆺𝅥' => '𝆺𝅥',
  '𝆹𝅥𝅮' => '𝆹𝅥𝅮',
  '𝆺𝅥𝅮' => '𝆺𝅥𝅮',
  '𝆹𝅥𝅯' => '𝆹𝅥𝅯',
  '𝆺𝅥𝅯' => '𝆺𝅥𝅯',
  '丽' => '丽',
  '丸' => '丸',
  '乁' => '乁',
  '𠄢' => '𠄢',
  '你' => '你',
  '侮' => '侮',
  '侻' => '侻',
  '倂' => '倂',
  '偺' => '偺',
  '備' => '備',
  '僧' => '僧',
  '像' => '像',
  '㒞' => '㒞',
  '𠘺' => '𠘺',
  '免' => '免',
  '兔' => '兔',
  '兤' => '兤',
  '具' => '具',
  '𠔜' => '𠔜',
  '㒹' => '㒹',
  '內' => '內',
  '再' => '再',
  '𠕋' => '𠕋',
  '冗' => '冗',
  '冤' => '冤',
  '仌' => '仌',
  '冬' => '冬',
  '况' => '况',
  '𩇟' => '𩇟',
  '凵' => '凵',
  '刃' => '刃',
  '㓟' => '㓟',
  '刻' => '刻',
  '剆' => '剆',
  '割' => '割',
  '剷' => '剷',
  '㔕' => '㔕',
  '勇' => '勇',
  '勉' => '勉',
  '勤' => '勤',
  '勺' => '勺',
  '包' => '包',
  '匆' => '匆',
  '北' => '北',
  '卉' => '卉',
  '卑' => '卑',
  '博' => '博',
  '即' => '即',
  '卽' => '卽',
  '卿' => '卿',
  '卿' => '卿',
  '卿' => '卿',
  '𠨬' => '𠨬',
  '灰' => '灰',
  '及' => '及',
  '叟' => '叟',
  '𠭣' => '𠭣',
  '叫' => '叫',
  '叱' => '叱',
  '吆' => '吆',
  '咞' => '咞',
  '吸' => '吸',
  '呈' => '呈',
  '周' => '周',
  '咢' => '咢',
  '哶' => '哶',
  '唐' => '唐',
  '啓' => '啓',
  '啣' => '啣',
  '善' => '善',
  '善' => '善',
  '喙' => '喙',
  '喫' => '喫',
  '喳' => '喳',
  '嗂' => '嗂',
  '圖' => '圖',
  '嘆' => '嘆',
  '圗' => '圗',
  '噑' => '噑',
  '噴' => '噴',
  '切' => '切',
  '壮' => '壮',
  '城' => '城',
  '埴' => '埴',
  '堍' => '堍',
  '型' => '型',
  '堲' => '堲',
  '報' => '報',
  '墬' => '墬',
  '𡓤' => '𡓤',
  '売' => '売',
  '壷' => '壷',
  '夆' => '夆',
  '多' => '多',
  '夢' => '夢',
  '奢' => '奢',
  '𡚨' => '𡚨',
  '𡛪' => '𡛪',
  '姬' => '姬',
  '娛' => '娛',
  '娧' => '娧',
  '姘' => '姘',
  '婦' => '婦',
  '㛮' => '㛮',
  '㛼' => '㛼',
  '嬈' => '嬈',
  '嬾' => '嬾',
  '嬾' => '嬾',
  '𡧈' => '𡧈',
  '寃' => '寃',
  '寘' => '寘',
  '寧' => '寧',
  '寳' => '寳',
  '𡬘' => '𡬘',
  '寿' => '寿',
  '将' => '将',
  '当' => '当',
  '尢' => '尢',
  '㞁' => '㞁',
  '屠' => '屠',
  '屮' => '屮',
  '峀' => '峀',
  '岍' => '岍',
  '𡷤' => '𡷤',
  '嵃' => '嵃',
  '𡷦' => '𡷦',
  '嵮' => '嵮',
  '嵫' => '嵫',
  '嵼' => '嵼',
  '巡' => '巡',
  '巢' => '巢',
  '㠯' => '㠯',
  '巽' => '巽',
  '帨' => '帨',
  '帽' => '帽',
  '幩' => '幩',
  '㡢' => '㡢',
  '𢆃' => '𢆃',
  '㡼' => '㡼',
  '庰' => '庰',
  '庳' => '庳',
  '庶' => '庶',
  '廊' => '廊',
  '𪎒' => '𪎒',
  '廾' => '廾',
  '𢌱' => '𢌱',
  '𢌱' => '𢌱',
  '舁' => '舁',
  '弢' => '弢',
  '弢' => '弢',
  '㣇' => '㣇',
  '𣊸' => '𣊸',
  '𦇚' => '𦇚',
  '形' => '形',
  '彫' => '彫',
  '㣣' => '㣣',
  '徚' => '徚',
  '忍' => '忍',
  '志' => '志',
  '忹' => '忹',
  '悁' => '悁',
  '㤺' => '㤺',
  '㤜' => '㤜',
  '悔' => '悔',
  '𢛔' => '𢛔',
  '惇' => '惇',
  '慈' => '慈',
  '慌' => '慌',
  '慎' => '慎',
  '慌' => '慌',
  '慺' => '慺',
  '憎' => '憎',
  '憲' => '憲',
  '憤' => '憤',
  '憯' => '憯',
  '懞' => '懞',
  '懲' => '懲',
  '懶' => '懶',
  '成' => '成',
  '戛' => '戛',
  '扝' => '扝',
  '抱' => '抱',
  '拔' => '拔',
  '捐' => '捐',
  '𢬌' => '𢬌',
  '挽' => '挽',
  '拼' => '拼',
  '捨' => '捨',
  '掃' => '掃',
  '揤' => '揤',
  '𢯱' => '𢯱',
  '搢' => '搢',
  '揅' => '揅',
  '掩' => '掩',
  '㨮' => '㨮',
  '摩' => '摩',
  '摾' => '摾',
  '撝' => '撝',
  '摷' => '摷',
  '㩬' => '㩬',
  '敏' => '敏',
  '敬' => '敬',
  '𣀊' => '𣀊',
  '旣' => '旣',
  '書' => '書',
  '晉' => '晉',
  '㬙' => '㬙',
  '暑' => '暑',
  '㬈' => '㬈',
  '㫤' => '㫤',
  '冒' => '冒',
  '冕' => '冕',
  '最' => '最',
  '暜' => '暜',
  '肭' => '肭',
  '䏙' => '䏙',
  '朗' => '朗',
  '望' => '望',
  '朡' => '朡',
  '杞' => '杞',
  '杓' => '杓',
  '𣏃' => '𣏃',
  '㭉' => '㭉',
  '柺' => '柺',
  '枅' => '枅',
  '桒' => '桒',
  '梅' => '梅',
  '𣑭' => '𣑭',
  '梎' => '梎',
  '栟' => '栟',
  '椔' => '椔',
  '㮝' => '㮝',
  '楂' => '楂',
  '榣' => '榣',
  '槪' => '槪',
  '檨' => '檨',
  '𣚣' => '𣚣',
  '櫛' => '櫛',
  '㰘' => '㰘',
  '次' => '次',
  '𣢧' => '𣢧',
  '歔' => '歔',
  '㱎' => '㱎',
  '歲' => '歲',
  '殟' => '殟',
  '殺' => '殺',
  '殻' => '殻',
  '𣪍' => '𣪍',
  '𡴋' => '𡴋',
  '𣫺' => '𣫺',
  '汎' => '汎',
  '𣲼' => '𣲼',
  '沿' => '沿',
  '泍' => '泍',
  '汧' => '汧',
  '洖' => '洖',
  '派' => '派',
  '海' => '海',
  '流' => '流',
  '浩' => '浩',
  '浸' => '浸',
  '涅' => '涅',
  '𣴞' => '𣴞',
  '洴' => '洴',
  '港' => '港',
  '湮' => '湮',
  '㴳' => '㴳',
  '滋' => '滋',
  '滇' => '滇',
  '𣻑' => '𣻑',
  '淹' => '淹',
  '潮' => '潮',
  '𣽞' => '𣽞',
  '𣾎' => '𣾎',
  '濆' => '濆',
  '瀹' => '瀹',
  '瀞' => '瀞',
  '瀛' => '瀛',
  '㶖' => '㶖',
  '灊' => '灊',
  '災' => '災',
  '灷' => '灷',
  '炭' => '炭',
  '𠔥' => '𠔥',
  '煅' => '煅',
  '𤉣' => '𤉣',
  '熜' => '熜',
  '𤎫' => '𤎫',
  '爨' => '爨',
  '爵' => '爵',
  '牐' => '牐',
  '𤘈' => '𤘈',
  '犀' => '犀',
  '犕' => '犕',
  '𤜵' => '𤜵',
  '𤠔' => '𤠔',
  '獺' => '獺',
  '王' => '王',
  '㺬' => '㺬',
  '玥' => '玥',
  '㺸' => '㺸',
  '㺸' => '㺸',
  '瑇' => '瑇',
  '瑜' => '瑜',
  '瑱' => '瑱',
  '璅' => '璅',
  '瓊' => '瓊',
  '㼛' => '㼛',
  '甤' => '甤',
  '𤰶' => '𤰶',
  '甾' => '甾',
  '𤲒' => '𤲒',
  '異' => '異',
  '𢆟' => '𢆟',
  '瘐' => '瘐',
  '𤾡' => '𤾡',
  '𤾸' => '𤾸',
  '𥁄' => '𥁄',
  '㿼' => '㿼',
  '䀈' => '䀈',
  '直' => '直',
  '𥃳' => '𥃳',
  '𥃲' => '𥃲',
  '𥄙' => '𥄙',
  '𥄳' => '𥄳',
  '眞' => '眞',
  '真' => '真',
  '真' => '真',
  '睊' => '睊',
  '䀹' => '䀹',
  '瞋' => '瞋',
  '䁆' => '䁆',
  '䂖' => '䂖',
  '𥐝' => '𥐝',
  '硎' => '硎',
  '碌' => '碌',
  '磌' => '磌',
  '䃣' => '䃣',
  '𥘦' => '𥘦',
  '祖' => '祖',
  '𥚚' => '𥚚',
  '𥛅' => '𥛅',
  '福' => '福',
  '秫' => '秫',
  '䄯' => '䄯',
  '穀' => '穀',
  '穊' => '穊',
  '穏' => '穏',
  '𥥼' => '𥥼',
  '𥪧' => '𥪧',
  '𥪧' => '𥪧',
  '竮' => '竮',
  '䈂' => '䈂',
  '𥮫' => '𥮫',
  '篆' => '篆',
  '築' => '築',
  '䈧' => '䈧',
  '𥲀' => '𥲀',
  '糒' => '糒',
  '䊠' => '䊠',
  '糨' => '糨',
  '糣' => '糣',
  '紀' => '紀',
  '𥾆' => '𥾆',
  '絣' => '絣',
  '䌁' => '䌁',
  '緇' => '緇',
  '縂' => '縂',
  '繅' => '繅',
  '䌴' => '䌴',
  '𦈨' => '𦈨',
  '𦉇' => '𦉇',
  '䍙' => '䍙',
  '𦋙' => '𦋙',
  '罺' => '罺',
  '𦌾' => '𦌾',
  '羕' => '羕',
  '翺' => '翺',
  '者' => '者',
  '𦓚' => '𦓚',
  '𦔣' => '𦔣',
  '聠' => '聠',
  '𦖨' => '𦖨',
  '聰' => '聰',
  '𣍟' => '𣍟',
  '䏕' => '䏕',
  '育' => '育',
  '脃' => '脃',
  '䐋' => '䐋',
  '脾' => '脾',
  '媵' => '媵',
  '𦞧' => '𦞧',
  '𦞵' => '𦞵',
  '𣎓' => '𣎓',
  '𣎜' => '𣎜',
  '舁' => '舁',
  '舄' => '舄',
  '辞' => '辞',
  '䑫' => '䑫',
  '芑' => '芑',
  '芋' => '芋',
  '芝' => '芝',
  '劳' => '劳',
  '花' => '花',
  '芳' => '芳',
  '芽' => '芽',
  '苦' => '苦',
  '𦬼' => '𦬼',
  '若' => '若',
  '茝' => '茝',
  '荣' => '荣',
  '莭' => '莭',
  '茣' => '茣',
  '莽' => '莽',
  '菧' => '菧',
  '著' => '著',
  '荓' => '荓',
  '菊' => '菊',
  '菌' => '菌',
  '菜' => '菜',
  '𦰶' => '𦰶',
  '𦵫' => '𦵫',
  '𦳕' => '𦳕',
  '䔫' => '䔫',
  '蓱' => '蓱',
  '蓳' => '蓳',
  '蔖' => '蔖',
  '𧏊' => '𧏊',
  '蕤' => '蕤',
  '𦼬' => '𦼬',
  '䕝' => '䕝',
  '䕡' => '䕡',
  '𦾱' => '𦾱',
  '𧃒' => '𧃒',
  '䕫' => '䕫',
  '虐' => '虐',
  '虜' => '虜',
  '虧' => '虧',
  '虩' => '虩',
  '蚩' => '蚩',
  '蚈' => '蚈',
  '蜎' => '蜎',
  '蛢' => '蛢',
  '蝹' => '蝹',
  '蜨' => '蜨',
  '蝫' => '蝫',
  '螆' => '螆',
  '䗗' => '䗗',
  '蟡' => '蟡',
  '蠁' => '蠁',
  '䗹' => '䗹',
  '衠' => '衠',
  '衣' => '衣',
  '𧙧' => '𧙧',
  '裗' => '裗',
  '裞' => '裞',
  '䘵' => '䘵',
  '裺' => '裺',
  '㒻' => '㒻',
  '𧢮' => '𧢮',
  '𧥦' => '𧥦',
  '䚾' => '䚾',
  '䛇' => '䛇',
  '誠' => '誠',
  '諭' => '諭',
  '變' => '變',
  '豕' => '豕',
  '𧲨' => '𧲨',
  '貫' => '貫',
  '賁' => '賁',
  '贛' => '贛',
  '起' => '起',
  '𧼯' => '𧼯',
  '𠠄' => '𠠄',
  '跋' => '跋',
  '趼' => '趼',
  '跰' => '跰',
  '𠣞' => '𠣞',
  '軔' => '軔',
  '輸' => '輸',
  '𨗒' => '𨗒',
  '𨗭' => '𨗭',
  '邔' => '邔',
  '郱' => '郱',
  '鄑' => '鄑',
  '𨜮' => '𨜮',
  '鄛' => '鄛',
  '鈸' => '鈸',
  '鋗' => '鋗',
  '鋘' => '鋘',
  '鉼' => '鉼',
  '鏹' => '鏹',
  '鐕' => '鐕',
  '𨯺' => '𨯺',
  '開' => '開',
  '䦕' => '䦕',
  '閷' => '閷',
  '𨵷' => '𨵷',
  '䧦' => '䧦',
  '雃' => '雃',
  '嶲' => '嶲',
  '霣' => '霣',
  '𩅅' => '𩅅',
  '𩈚' => '𩈚',
  '䩮' => '䩮',
  '䩶' => '䩶',
  '韠' => '韠',
  '𩐊' => '𩐊',
  '䪲' => '䪲',
  '𩒖' => '𩒖',
  '頋' => '頋',
  '頋' => '頋',
  '頩' => '頩',
  '𩖶' => '𩖶',
  '飢' => '飢',
  '䬳' => '䬳',
  '餩' => '餩',
  '馧' => '馧',
  '駂' => '駂',
  '駾' => '駾',
  '䯎' => '䯎',
  '𩬰' => '𩬰',
  '鬒' => '鬒',
  '鱀' => '鱀',
  '鳽' => '鳽',
  '䳎' => '䳎',
  '䳭' => '䳭',
  '鵧' => '鵧',
  '𪃎' => '𪃎',
  '䳸' => '䳸',
  '𪄅' => '𪄅',
  '𪈎' => '𪈎',
  '𪊑' => '𪊑',
  '麻' => '麻',
  '䵖' => '䵖',
  '黹' => '黹',
  '黾' => '黾',
  '鼅' => '鼅',
  '鼏' => '鼏',
  '鼖' => '鼖',
  '鼻' => '鼻',
  '𪘀' => '𪘀',
);
<?php

return array (
  'À' => 'À',
  'Á' => 'Á',
  'Â' => 'Â',
  'Ã' => 'Ã',
  'Ä' => 'Ä',
  'Å' => 'Å',
  'Ç' => 'Ç',
  'È' => 'È',
  'É' => 'É',
  'Ê' => 'Ê',
  'Ë' => 'Ë',
  'Ì' => 'Ì',
  'Í' => 'Í',
  'Î' => 'Î',
  'Ï' => 'Ï',
  'Ñ' => 'Ñ',
  'Ò' => 'Ò',
  'Ó' => 'Ó',
  'Ô' => 'Ô',
  'Õ' => 'Õ',
  'Ö' => 'Ö',
  'Ù' => 'Ù',
  'Ú' => 'Ú',
  'Û' => 'Û',
  'Ü' => 'Ü',
  'Ý' => 'Ý',
  'à' => 'à',
  'á' => 'á',
  'â' => 'â',
  'ã' => 'ã',
  'ä' => 'ä',
  'å' => 'å',
  'ç' => 'ç',
  'è' => 'è',
  'é' => 'é',
  'ê' => 'ê',
  'ë' => 'ë',
  'ì' => 'ì',
  'í' => 'í',
  'î' => 'î',
  'ï' => 'ï',
  'ñ' => 'ñ',
  'ò' => 'ò',
  'ó' => 'ó',
  'ô' => 'ô',
  'õ' => 'õ',
  'ö' => 'ö',
  'ù' => 'ù',
  'ú' => 'ú',
  'û' => 'û',
  'ü' => 'ü',
  'ý' => 'ý',
  'ÿ' => 'ÿ',
  'Ā' => 'Ā',
  'ā' => 'ā',
  'Ă' => 'Ă',
  'ă' => 'ă',
  'Ą' => 'Ą',
  'ą' => 'ą',
  'Ć' => 'Ć',
  'ć' => 'ć',
  'Ĉ' => 'Ĉ',
  'ĉ' => 'ĉ',
  'Ċ' => 'Ċ',
  'ċ' => 'ċ',
  'Č' => 'Č',
  'č' => 'č',
  'Ď' => 'Ď',
  'ď' => 'ď',
  'Ē' => 'Ē',
  'ē' => 'ē',
  'Ĕ' => 'Ĕ',
  'ĕ' => 'ĕ',
  'Ė' => 'Ė',
  'ė' => 'ė',
  'Ę' => 'Ę',
  'ę' => 'ę',
  'Ě' => 'Ě',
  'ě' => 'ě',
  'Ĝ' => 'Ĝ',
  'ĝ' => 'ĝ',
  'Ğ' => 'Ğ',
  'ğ' => 'ğ',
  'Ġ' => 'Ġ',
  'ġ' => 'ġ',
  'Ģ' => 'Ģ',
  'ģ' => 'ģ',
  'Ĥ' => 'Ĥ',
  'ĥ' => 'ĥ',
  'Ĩ' => 'Ĩ',
  'ĩ' => 'ĩ',
  'Ī' => 'Ī',
  'ī' => 'ī',
  'Ĭ' => 'Ĭ',
  'ĭ' => 'ĭ',
  'Į' => 'Į',
  'į' => 'į',
  'İ' => 'İ',
  'Ĵ' => 'Ĵ',
  'ĵ' => 'ĵ',
  'Ķ' => 'Ķ',
  'ķ' => 'ķ',
  'Ĺ' => 'Ĺ',
  'ĺ' => 'ĺ',
  'Ļ' => 'Ļ',
  'ļ' => 'ļ',
  'Ľ' => 'Ľ',
  'ľ' => 'ľ',
  'Ń' => 'Ń',
  'ń' => 'ń',
  'Ņ' => 'Ņ',
  'ņ' => 'ņ',
  'Ň' => 'Ň',
  'ň' => 'ň',
  'Ō' => 'Ō',
  'ō' => 'ō',
  'Ŏ' => 'Ŏ',
  'ŏ' => 'ŏ',
  'Ő' => 'Ő',
  'ő' => 'ő',
  'Ŕ' => 'Ŕ',
  'ŕ' => 'ŕ',
  'Ŗ' => 'Ŗ',
  'ŗ' => 'ŗ',
  'Ř' => 'Ř',
  'ř' => 'ř',
  'Ś' => 'Ś',
  'ś' => 'ś',
  'Ŝ' => 'Ŝ',
  'ŝ' => 'ŝ',
  'Ş' => 'Ş',
  'ş' => 'ş',
  'Š' => 'Š',
  'š' => 'š',
  'Ţ' => 'Ţ',
  'ţ' => 'ţ',
  'Ť' => 'Ť',
  'ť' => 'ť',
  'Ũ' => 'Ũ',
  'ũ' => 'ũ',
  'Ū' => 'Ū',
  'ū' => 'ū',
  'Ŭ' => 'Ŭ',
  'ŭ' => 'ŭ',
  'Ů' => 'Ů',
  'ů' => 'ů',
  'Ű' => 'Ű',
  'ű' => 'ű',
  'Ų' => 'Ų',
  'ų' => 'ų',
  'Ŵ' => 'Ŵ',
  'ŵ' => 'ŵ',
  'Ŷ' => 'Ŷ',
  'ŷ' => 'ŷ',
  'Ÿ' => 'Ÿ',
  'Ź' => 'Ź',
  'ź' => 'ź',
  'Ż' => 'Ż',
  'ż' => 'ż',
  'Ž' => 'Ž',
  'ž' => 'ž',
  'Ơ' => 'Ơ',
  'ơ' => 'ơ',
  'Ư' => 'Ư',
  'ư' => 'ư',
  'Ǎ' => 'Ǎ',
  'ǎ' => 'ǎ',
  'Ǐ' => 'Ǐ',
  'ǐ' => 'ǐ',
  'Ǒ' => 'Ǒ',
  'ǒ' => 'ǒ',
  'Ǔ' => 'Ǔ',
  'ǔ' => 'ǔ',
  'Ǖ' => 'Ǖ',
  'ǖ' => 'ǖ',
  'Ǘ' => 'Ǘ',
  'ǘ' => 'ǘ',
  'Ǚ' => 'Ǚ',
  'ǚ' => 'ǚ',
  'Ǜ' => 'Ǜ',
  'ǜ' => 'ǜ',
  'Ǟ' => 'Ǟ',
  'ǟ' => 'ǟ',
  'Ǡ' => 'Ǡ',
  'ǡ' => 'ǡ',
  'Ǣ' => 'Ǣ',
  'ǣ' => 'ǣ',
  'Ǧ' => 'Ǧ',
  'ǧ' => 'ǧ',
  'Ǩ' => 'Ǩ',
  'ǩ' => 'ǩ',
  'Ǫ' => 'Ǫ',
  'ǫ' => 'ǫ',
  'Ǭ' => 'Ǭ',
  'ǭ' => 'ǭ',
  'Ǯ' => 'Ǯ',
  'ǯ' => 'ǯ',
  'ǰ' => 'ǰ',
  'Ǵ' => 'Ǵ',
  'ǵ' => 'ǵ',
  'Ǹ' => 'Ǹ',
  'ǹ' => 'ǹ',
  'Ǻ' => 'Ǻ',
  'ǻ' => 'ǻ',
  'Ǽ' => 'Ǽ',
  'ǽ' => 'ǽ',
  'Ǿ' => 'Ǿ',
  'ǿ' => 'ǿ',
  'Ȁ' => 'Ȁ',
  'ȁ' => 'ȁ',
  'Ȃ' => 'Ȃ',
  'ȃ' => 'ȃ',
  'Ȅ' => 'Ȅ',
  'ȅ' => 'ȅ',
  'Ȇ' => 'Ȇ',
  'ȇ' => 'ȇ',
  'Ȉ' => 'Ȉ',
  'ȉ' => 'ȉ',
  'Ȋ' => 'Ȋ',
  'ȋ' => 'ȋ',
  'Ȍ' => 'Ȍ',
  'ȍ' => 'ȍ',
  'Ȏ' => 'Ȏ',
  'ȏ' => 'ȏ',
  'Ȑ' => 'Ȑ',
  'ȑ' => 'ȑ',
  'Ȓ' => 'Ȓ',
  'ȓ' => 'ȓ',
  'Ȕ' => 'Ȕ',
  'ȕ' => 'ȕ',
  'Ȗ' => 'Ȗ',
  'ȗ' => 'ȗ',
  'Ș' => 'Ș',
  'ș' => 'ș',
  'Ț' => 'Ț',
  'ț' => 'ț',
  'Ȟ' => 'Ȟ',
  'ȟ' => 'ȟ',
  'Ȧ' => 'Ȧ',
  'ȧ' => 'ȧ',
  'Ȩ' => 'Ȩ',
  'ȩ' => 'ȩ',
  'Ȫ' => 'Ȫ',
  'ȫ' => 'ȫ',
  'Ȭ' => 'Ȭ',
  'ȭ' => 'ȭ',
  'Ȯ' => 'Ȯ',
  'ȯ' => 'ȯ',
  'Ȱ' => 'Ȱ',
  'ȱ' => 'ȱ',
  'Ȳ' => 'Ȳ',
  'ȳ' => 'ȳ',
  '΅' => '΅',
  'Ά' => 'Ά',
  'Έ' => 'Έ',
  'Ή' => 'Ή',
  'Ί' => 'Ί',
  'Ό' => 'Ό',
  'Ύ' => 'Ύ',
  'Ώ' => 'Ώ',
  'ΐ' => 'ΐ',
  'Ϊ' => 'Ϊ',
  'Ϋ' => 'Ϋ',
  'ά' => 'ά',
  'έ' => 'έ',
  'ή' => 'ή',
  'ί' => 'ί',
  'ΰ' => 'ΰ',
  'ϊ' => 'ϊ',
  'ϋ' => 'ϋ',
  'ό' => 'ό',
  'ύ' => 'ύ',
  'ώ' => 'ώ',
  'ϓ' => 'ϓ',
  'ϔ' => 'ϔ',
  'Ѐ' => 'Ѐ',
  'Ё' => 'Ё',
  'Ѓ' => 'Ѓ',
  'Ї' => 'Ї',
  'Ќ' => 'Ќ',
  'Ѝ' => 'Ѝ',
  'Ў' => 'Ў',
  'Й' => 'Й',
  'й' => 'й',
  'ѐ' => 'ѐ',
  'ё' => 'ё',
  'ѓ' => 'ѓ',
  'ї' => 'ї',
  'ќ' => 'ќ',
  'ѝ' => 'ѝ',
  'ў' => 'ў',
  'Ѷ' => 'Ѷ',
  'ѷ' => 'ѷ',
  'Ӂ' => 'Ӂ',
  'ӂ' => 'ӂ',
  'Ӑ' => 'Ӑ',
  'ӑ' => 'ӑ',
  'Ӓ' => 'Ӓ',
  'ӓ' => 'ӓ',
  'Ӗ' => 'Ӗ',
  'ӗ' => 'ӗ',
  'Ӛ' => 'Ӛ',
  'ӛ' => 'ӛ',
  'Ӝ' => 'Ӝ',
  'ӝ' => 'ӝ',
  'Ӟ' => 'Ӟ',
  'ӟ' => 'ӟ',
  'Ӣ' => 'Ӣ',
  'ӣ' => 'ӣ',
  'Ӥ' => 'Ӥ',
  'ӥ' => 'ӥ',
  'Ӧ' => 'Ӧ',
  'ӧ' => 'ӧ',
  'Ӫ' => 'Ӫ',
  'ӫ' => 'ӫ',
  'Ӭ' => 'Ӭ',
  'ӭ' => 'ӭ',
  'Ӯ' => 'Ӯ',
  'ӯ' => 'ӯ',
  'Ӱ' => 'Ӱ',
  'ӱ' => 'ӱ',
  'Ӳ' => 'Ӳ',
  'ӳ' => 'ӳ',
  'Ӵ' => 'Ӵ',
  'ӵ' => 'ӵ',
  'Ӹ' => 'Ӹ',
  'ӹ' => 'ӹ',
  'آ' => 'آ',
  'أ' => 'أ',
  'ؤ' => 'ؤ',
  'إ' => 'إ',
  'ئ' => 'ئ',
  'ۀ' => 'ۀ',
  'ۂ' => 'ۂ',
  'ۓ' => 'ۓ',
  'ऩ' => 'ऩ',
  'ऱ' => 'ऱ',
  'ऴ' => 'ऴ',
  'ো' => 'ো',
  'ৌ' => 'ৌ',
  'ୈ' => 'ୈ',
  'ୋ' => 'ୋ',
  'ୌ' => 'ୌ',
  'ஔ' => 'ஔ',
  'ொ' => 'ொ',
  'ோ' => 'ோ',
  'ௌ' => 'ௌ',
  'ై' => 'ై',
  'ೀ' => 'ೀ',
  'ೇ' => 'ೇ',
  'ೈ' => 'ೈ',
  'ೊ' => 'ೊ',
  'ೋ' => 'ೋ',
  'ൊ' => 'ൊ',
  'ോ' => 'ോ',
  'ൌ' => 'ൌ',
  'ේ' => 'ේ',
  'ො' => 'ො',
  'ෝ' => 'ෝ',
  'ෞ' => 'ෞ',
  'ဦ' => 'ဦ',
  'ᬆ' => 'ᬆ',
  'ᬈ' => 'ᬈ',
  'ᬊ' => 'ᬊ',
  'ᬌ' => 'ᬌ',
  'ᬎ' => 'ᬎ',
  'ᬒ' => 'ᬒ',
  'ᬻ' => 'ᬻ',
  'ᬽ' => 'ᬽ',
  'ᭀ' => 'ᭀ',
  'ᭁ' => 'ᭁ',
  'ᭃ' => 'ᭃ',
  'Ḁ' => 'Ḁ',
  'ḁ' => 'ḁ',
  'Ḃ' => 'Ḃ',
  'ḃ' => 'ḃ',
  'Ḅ' => 'Ḅ',
  'ḅ' => 'ḅ',
  'Ḇ' => 'Ḇ',
  'ḇ' => 'ḇ',
  'Ḉ' => 'Ḉ',
  'ḉ' => 'ḉ',
  'Ḋ' => 'Ḋ',
  'ḋ' => 'ḋ',
  'Ḍ' => 'Ḍ',
  'ḍ' => 'ḍ',
  'Ḏ' => 'Ḏ',
  'ḏ' => 'ḏ',
  'Ḑ' => 'Ḑ',
  'ḑ' => 'ḑ',
  'Ḓ' => 'Ḓ',
  'ḓ' => 'ḓ',
  'Ḕ' => 'Ḕ',
  'ḕ' => 'ḕ',
  'Ḗ' => 'Ḗ',
  'ḗ' => 'ḗ',
  'Ḙ' => 'Ḙ',
  'ḙ' => 'ḙ',
  'Ḛ' => 'Ḛ',
  'ḛ' => 'ḛ',
  'Ḝ' => 'Ḝ',
  'ḝ' => 'ḝ',
  'Ḟ' => 'Ḟ',
  'ḟ' => 'ḟ',
  'Ḡ' => 'Ḡ',
  'ḡ' => 'ḡ',
  'Ḣ' => 'Ḣ',
  'ḣ' => 'ḣ',
  'Ḥ' => 'Ḥ',
  'ḥ' => 'ḥ',
  'Ḧ' => 'Ḧ',
  'ḧ' => 'ḧ',
  'Ḩ' => 'Ḩ',
  'ḩ' => 'ḩ',
  'Ḫ' => 'Ḫ',
  'ḫ' => 'ḫ',
  'Ḭ' => 'Ḭ',
  'ḭ' => 'ḭ',
  'Ḯ' => 'Ḯ',
  'ḯ' => 'ḯ',
  'Ḱ' => 'Ḱ',
  'ḱ' => 'ḱ',
  'Ḳ' => 'Ḳ',
  'ḳ' => 'ḳ',
  'Ḵ' => 'Ḵ',
  'ḵ' => 'ḵ',
  'Ḷ' => 'Ḷ',
  'ḷ' => 'ḷ',
  'Ḹ' => 'Ḹ',
  'ḹ' => 'ḹ',
  'Ḻ' => 'Ḻ',
  'ḻ' => 'ḻ',
  'Ḽ' => 'Ḽ',
  'ḽ' => 'ḽ',
  'Ḿ' => 'Ḿ',
  'ḿ' => 'ḿ',
  'Ṁ' => 'Ṁ',
  'ṁ' => 'ṁ',
  'Ṃ' => 'Ṃ',
  'ṃ' => 'ṃ',
  'Ṅ' => 'Ṅ',
  'ṅ' => 'ṅ',
  'Ṇ' => 'Ṇ',
  'ṇ' => 'ṇ',
  'Ṉ' => 'Ṉ',
  'ṉ' => 'ṉ',
  'Ṋ' => 'Ṋ',
  'ṋ' => 'ṋ',
  'Ṍ' => 'Ṍ',
  'ṍ' => 'ṍ',
  'Ṏ' => 'Ṏ',
  'ṏ' => 'ṏ',
  'Ṑ' => 'Ṑ',
  'ṑ' => 'ṑ',
  'Ṓ' => 'Ṓ',
  'ṓ' => 'ṓ',
  'Ṕ' => 'Ṕ',
  'ṕ' => 'ṕ',
  'Ṗ' => 'Ṗ',
  'ṗ' => 'ṗ',
  'Ṙ' => 'Ṙ',
  'ṙ' => 'ṙ',
  'Ṛ' => 'Ṛ',
  'ṛ' => 'ṛ',
  'Ṝ' => 'Ṝ',
  'ṝ' => 'ṝ',
  'Ṟ' => 'Ṟ',
  'ṟ' => 'ṟ',
  'Ṡ' => 'Ṡ',
  'ṡ' => 'ṡ',
  'Ṣ' => 'Ṣ',
  'ṣ' => 'ṣ',
  'Ṥ' => 'Ṥ',
  'ṥ' => 'ṥ',
  'Ṧ' => 'Ṧ',
  'ṧ' => 'ṧ',
  'Ṩ' => 'Ṩ',
  'ṩ' => 'ṩ',
  'Ṫ' => 'Ṫ',
  'ṫ' => 'ṫ',
  'Ṭ' => 'Ṭ',
  'ṭ' => 'ṭ',
  'Ṯ' => 'Ṯ',
  'ṯ' => 'ṯ',
  'Ṱ' => 'Ṱ',
  'ṱ' => 'ṱ',
  'Ṳ' => 'Ṳ',
  'ṳ' => 'ṳ',
  'Ṵ' => 'Ṵ',
  'ṵ' => 'ṵ',
  'Ṷ' => 'Ṷ',
  'ṷ' => 'ṷ',
  'Ṹ' => 'Ṹ',
  'ṹ' => 'ṹ',
  'Ṻ' => 'Ṻ',
  'ṻ' => 'ṻ',
  'Ṽ' => 'Ṽ',
  'ṽ' => 'ṽ',
  'Ṿ' => 'Ṿ',
  'ṿ' => 'ṿ',
  'Ẁ' => 'Ẁ',
  'ẁ' => 'ẁ',
  'Ẃ' => 'Ẃ',
  'ẃ' => 'ẃ',
  'Ẅ' => 'Ẅ',
  'ẅ' => 'ẅ',
  'Ẇ' => 'Ẇ',
  'ẇ' => 'ẇ',
  'Ẉ' => 'Ẉ',
  'ẉ' => 'ẉ',
  'Ẋ' => 'Ẋ',
  'ẋ' => 'ẋ',
  'Ẍ' => 'Ẍ',
  'ẍ' => 'ẍ',
  'Ẏ' => 'Ẏ',
  'ẏ' => 'ẏ',
  'Ẑ' => 'Ẑ',
  'ẑ' => 'ẑ',
  'Ẓ' => 'Ẓ',
  'ẓ' => 'ẓ',
  'Ẕ' => 'Ẕ',
  'ẕ' => 'ẕ',
  'ẖ' => 'ẖ',
  'ẗ' => 'ẗ',
  'ẘ' => 'ẘ',
  'ẙ' => 'ẙ',
  'ẛ' => 'ẛ',
  'Ạ' => 'Ạ',
  'ạ' => 'ạ',
  'Ả' => 'Ả',
  'ả' => 'ả',
  'Ấ' => 'Ấ',
  'ấ' => 'ấ',
  'Ầ' => 'Ầ',
  'ầ' => 'ầ',
  'Ẩ' => 'Ẩ',
  'ẩ' => 'ẩ',
  'Ẫ' => 'Ẫ',
  'ẫ' => 'ẫ',
  'Ậ' => 'Ậ',
  'ậ' => 'ậ',
  'Ắ' => 'Ắ',
  'ắ' => 'ắ',
  'Ằ' => 'Ằ',
  'ằ' => 'ằ',
  'Ẳ' => 'Ẳ',
  'ẳ' => 'ẳ',
  'Ẵ' => 'Ẵ',
  'ẵ' => 'ẵ',
  'Ặ' => 'Ặ',
  'ặ' => 'ặ',
  'Ẹ' => 'Ẹ',
  'ẹ' => 'ẹ',
  'Ẻ' => 'Ẻ',
  'ẻ' => 'ẻ',
  'Ẽ' => 'Ẽ',
  'ẽ' => 'ẽ',
  'Ế' => 'Ế',
  'ế' => 'ế',
  'Ề' => 'Ề',
  'ề' => 'ề',
  'Ể' => 'Ể',
  'ể' => 'ể',
  'Ễ' => 'Ễ',
  'ễ' => 'ễ',
  'Ệ' => 'Ệ',
  'ệ' => 'ệ',
  'Ỉ' => 'Ỉ',
  'ỉ' => 'ỉ',
  'Ị' => 'Ị',
  'ị' => 'ị',
  'Ọ' => 'Ọ',
  'ọ' => 'ọ',
  'Ỏ' => 'Ỏ',
  'ỏ' => 'ỏ',
  'Ố' => 'Ố',
  'ố' => 'ố',
  'Ồ' => 'Ồ',
  'ồ' => 'ồ',
  'Ổ' => 'Ổ',
  'ổ' => 'ổ',
  'Ỗ' => 'Ỗ',
  'ỗ' => 'ỗ',
  'Ộ' => 'Ộ',
  'ộ' => 'ộ',
  'Ớ' => 'Ớ',
  'ớ' => 'ớ',
  'Ờ' => 'Ờ',
  'ờ' => 'ờ',
  'Ở' => 'Ở',
  'ở' => 'ở',
  'Ỡ' => 'Ỡ',
  'ỡ' => 'ỡ',
  'Ợ' => 'Ợ',
  'ợ' => 'ợ',
  'Ụ' => 'Ụ',
  'ụ' => 'ụ',
  'Ủ' => 'Ủ',
  'ủ' => 'ủ',
  'Ứ' => 'Ứ',
  'ứ' => 'ứ',
  'Ừ' => 'Ừ',
  'ừ' => 'ừ',
  'Ử' => 'Ử',
  'ử' => 'ử',
  'Ữ' => 'Ữ',
  'ữ' => 'ữ',
  'Ự' => 'Ự',
  'ự' => 'ự',
  'Ỳ' => 'Ỳ',
  'ỳ' => 'ỳ',
  'Ỵ' => 'Ỵ',
  'ỵ' => 'ỵ',
  'Ỷ' => 'Ỷ',
  'ỷ' => 'ỷ',
  'Ỹ' => 'Ỹ',
  'ỹ' => 'ỹ',
  'ἀ' => 'ἀ',
  'ἁ' => 'ἁ',
  'ἂ' => 'ἂ',
  'ἃ' => 'ἃ',
  'ἄ' => 'ἄ',
  'ἅ' => 'ἅ',
  'ἆ' => 'ἆ',
  'ἇ' => 'ἇ',
  'Ἀ' => 'Ἀ',
  'Ἁ' => 'Ἁ',
  'Ἂ' => 'Ἂ',
  'Ἃ' => 'Ἃ',
  'Ἄ' => 'Ἄ',
  'Ἅ' => 'Ἅ',
  'Ἆ' => 'Ἆ',
  'Ἇ' => 'Ἇ',
  'ἐ' => 'ἐ',
  'ἑ' => 'ἑ',
  'ἒ' => 'ἒ',
  'ἓ' => 'ἓ',
  'ἔ' => 'ἔ',
  'ἕ' => 'ἕ',
  'Ἐ' => 'Ἐ',
  'Ἑ' => 'Ἑ',
  'Ἒ' => 'Ἒ',
  'Ἓ' => 'Ἓ',
  'Ἔ' => 'Ἔ',
  'Ἕ' => 'Ἕ',
  'ἠ' => 'ἠ',
  'ἡ' => 'ἡ',
  'ἢ' => 'ἢ',
  'ἣ' => 'ἣ',
  'ἤ' => 'ἤ',
  'ἥ' => 'ἥ',
  'ἦ' => 'ἦ',
  'ἧ' => 'ἧ',
  'Ἠ' => 'Ἠ',
  'Ἡ' => 'Ἡ',
  'Ἢ' => 'Ἢ',
  'Ἣ' => 'Ἣ',
  'Ἤ' => 'Ἤ',
  'Ἥ' => 'Ἥ',
  'Ἦ' => 'Ἦ',
  'Ἧ' => 'Ἧ',
  'ἰ' => 'ἰ',
  'ἱ' => 'ἱ',
  'ἲ' => 'ἲ',
  'ἳ' => 'ἳ',
  'ἴ' => 'ἴ',
  'ἵ' => 'ἵ',
  'ἶ' => 'ἶ',
  'ἷ' => 'ἷ',
  'Ἰ' => 'Ἰ',
  'Ἱ' => 'Ἱ',
  'Ἲ' => 'Ἲ',
  'Ἳ' => 'Ἳ',
  'Ἴ' => 'Ἴ',
  'Ἵ' => 'Ἵ',
  'Ἶ' => 'Ἶ',
  'Ἷ' => 'Ἷ',
  'ὀ' => 'ὀ',
  'ὁ' => 'ὁ',
  'ὂ' => 'ὂ',
  'ὃ' => 'ὃ',
  'ὄ' => 'ὄ',
  'ὅ' => 'ὅ',
  'Ὀ' => 'Ὀ',
  'Ὁ' => 'Ὁ',
  'Ὂ' => 'Ὂ',
  'Ὃ' => 'Ὃ',
  'Ὄ' => 'Ὄ',
  'Ὅ' => 'Ὅ',
  'ὐ' => 'ὐ',
  'ὑ' => 'ὑ',
  'ὒ' => 'ὒ',
  'ὓ' => 'ὓ',
  'ὔ' => 'ὔ',
  'ὕ' => 'ὕ',
  'ὖ' => 'ὖ',
  'ὗ' => 'ὗ',
  'Ὑ' => 'Ὑ',
  'Ὓ' => 'Ὓ',
  'Ὕ' => 'Ὕ',
  'Ὗ' => 'Ὗ',
  'ὠ' => 'ὠ',
  'ὡ' => 'ὡ',
  'ὢ' => 'ὢ',
  'ὣ' => 'ὣ',
  'ὤ' => 'ὤ',
  'ὥ' => 'ὥ',
  'ὦ' => 'ὦ',
  'ὧ' => 'ὧ',
  'Ὠ' => 'Ὠ',
  'Ὡ' => 'Ὡ',
  'Ὢ' => 'Ὢ',
  'Ὣ' => 'Ὣ',
  'Ὤ' => 'Ὤ',
  'Ὥ' => 'Ὥ',
  'Ὦ' => 'Ὦ',
  'Ὧ' => 'Ὧ',
  'ὰ' => 'ὰ',
  'ὲ' => 'ὲ',
  'ὴ' => 'ὴ',
  'ὶ' => 'ὶ',
  'ὸ' => 'ὸ',
  'ὺ' => 'ὺ',
  'ὼ' => 'ὼ',
  'ᾀ' => 'ᾀ',
  'ᾁ' => 'ᾁ',
  'ᾂ' => 'ᾂ',
  'ᾃ' => 'ᾃ',
  'ᾄ' => 'ᾄ',
  'ᾅ' => 'ᾅ',
  'ᾆ' => 'ᾆ',
  'ᾇ' => 'ᾇ',
  'ᾈ' => 'ᾈ',
  'ᾉ' => 'ᾉ',
  'ᾊ' => 'ᾊ',
  'ᾋ' => 'ᾋ',
  'ᾌ' => 'ᾌ',
  'ᾍ' => 'ᾍ',
  'ᾎ' => 'ᾎ',
  'ᾏ' => 'ᾏ',
  'ᾐ' => 'ᾐ',
  'ᾑ' => 'ᾑ',
  'ᾒ' => 'ᾒ',
  'ᾓ' => 'ᾓ',
  'ᾔ' => 'ᾔ',
  'ᾕ' => 'ᾕ',
  'ᾖ' => 'ᾖ',
  'ᾗ' => 'ᾗ',
  'ᾘ' => 'ᾘ',
  'ᾙ' => 'ᾙ',
  'ᾚ' => 'ᾚ',
  'ᾛ' => 'ᾛ',
  'ᾜ' => 'ᾜ',
  'ᾝ' => 'ᾝ',
  'ᾞ' => 'ᾞ',
  'ᾟ' => 'ᾟ',
  'ᾠ' => 'ᾠ',
  'ᾡ' => 'ᾡ',
  'ᾢ' => 'ᾢ',
  'ᾣ' => 'ᾣ',
  'ᾤ' => 'ᾤ',
  'ᾥ' => 'ᾥ',
  'ᾦ' => 'ᾦ',
  'ᾧ' => 'ᾧ',
  'ᾨ' => 'ᾨ',
  'ᾩ' => 'ᾩ',
  'ᾪ' => 'ᾪ',
  'ᾫ' => 'ᾫ',
  'ᾬ' => 'ᾬ',
  'ᾭ' => 'ᾭ',
  'ᾮ' => 'ᾮ',
  'ᾯ' => 'ᾯ',
  'ᾰ' => 'ᾰ',
  'ᾱ' => 'ᾱ',
  'ᾲ' => 'ᾲ',
  'ᾳ' => 'ᾳ',
  'ᾴ' => 'ᾴ',
  'ᾶ' => 'ᾶ',
  'ᾷ' => 'ᾷ',
  'Ᾰ' => 'Ᾰ',
  'Ᾱ' => 'Ᾱ',
  'Ὰ' => 'Ὰ',
  'ᾼ' => 'ᾼ',
  '῁' => '῁',
  'ῂ' => 'ῂ',
  'ῃ' => 'ῃ',
  'ῄ' => 'ῄ',
  'ῆ' => 'ῆ',
  'ῇ' => 'ῇ',
  'Ὲ' => 'Ὲ',
  'Ὴ' => 'Ὴ',
  'ῌ' => 'ῌ',
  '῍' => '῍',
  '῎' => '῎',
  '῏' => '῏',
  'ῐ' => 'ῐ',
  'ῑ' => 'ῑ',
  'ῒ' => 'ῒ',
  'ῖ' => 'ῖ',
  'ῗ' => 'ῗ',
  'Ῐ' => 'Ῐ',
  'Ῑ' => 'Ῑ',
  'Ὶ' => 'Ὶ',
  '῝' => '῝',
  '῞' => '῞',
  '῟' => '῟',
  'ῠ' => 'ῠ',
  'ῡ' => 'ῡ',
  'ῢ' => 'ῢ',
  'ῤ' => 'ῤ',
  'ῥ' => 'ῥ',
  'ῦ' => 'ῦ',
  'ῧ' => 'ῧ',
  'Ῠ' => 'Ῠ',
  'Ῡ' => 'Ῡ',
  'Ὺ' => 'Ὺ',
  'Ῥ' => 'Ῥ',
  '῭' => '῭',
  'ῲ' => 'ῲ',
  'ῳ' => 'ῳ',
  'ῴ' => 'ῴ',
  'ῶ' => 'ῶ',
  'ῷ' => 'ῷ',
  'Ὸ' => 'Ὸ',
  'Ὼ' => 'Ὼ',
  'ῼ' => 'ῼ',
  '↚' => '↚',
  '↛' => '↛',
  '↮' => '↮',
  '⇍' => '⇍',
  '⇎' => '⇎',
  '⇏' => '⇏',
  '∄' => '∄',
  '∉' => '∉',
  '∌' => '∌',
  '∤' => '∤',
  '∦' => '∦',
  '≁' => '≁',
  '≄' => '≄',
  '≇' => '≇',
  '≉' => '≉',
  '≠' => '≠',
  '≢' => '≢',
  '≭' => '≭',
  '≮' => '≮',
  '≯' => '≯',
  '≰' => '≰',
  '≱' => '≱',
  '≴' => '≴',
  '≵' => '≵',
  '≸' => '≸',
  '≹' => '≹',
  '⊀' => '⊀',
  '⊁' => '⊁',
  '⊄' => '⊄',
  '⊅' => '⊅',
  '⊈' => '⊈',
  '⊉' => '⊉',
  '⊬' => '⊬',
  '⊭' => '⊭',
  '⊮' => '⊮',
  '⊯' => '⊯',
  '⋠' => '⋠',
  '⋡' => '⋡',
  '⋢' => '⋢',
  '⋣' => '⋣',
  '⋪' => '⋪',
  '⋫' => '⋫',
  '⋬' => '⋬',
  '⋭' => '⋭',
  'が' => 'が',
  'ぎ' => 'ぎ',
  'ぐ' => 'ぐ',
  'げ' => 'げ',
  'ご' => 'ご',
  'ざ' => 'ざ',
  'じ' => 'じ',
  'ず' => 'ず',
  'ぜ' => 'ぜ',
  'ぞ' => 'ぞ',
  'だ' => 'だ',
  'ぢ' => 'ぢ',
  'づ' => 'づ',
  'で' => 'で',
  'ど' => 'ど',
  'ば' => 'ば',
  'ぱ' => 'ぱ',
  'び' => 'び',
  'ぴ' => 'ぴ',
  'ぶ' => 'ぶ',
  'ぷ' => 'ぷ',
  'べ' => 'べ',
  'ぺ' => 'ぺ',
  'ぼ' => 'ぼ',
  'ぽ' => 'ぽ',
  'ゔ' => 'ゔ',
  'ゞ' => 'ゞ',
  'ガ' => 'ガ',
  'ギ' => 'ギ',
  'グ' => 'グ',
  'ゲ' => 'ゲ',
  'ゴ' => 'ゴ',
  'ザ' => 'ザ',
  'ジ' => 'ジ',
  'ズ' => 'ズ',
  'ゼ' => 'ゼ',
  'ゾ' => 'ゾ',
  'ダ' => 'ダ',
  'ヂ' => 'ヂ',
  'ヅ' => 'ヅ',
  'デ' => 'デ',
  'ド' => 'ド',
  'バ' => 'バ',
  'パ' => 'パ',
  'ビ' => 'ビ',
  'ピ' => 'ピ',
  'ブ' => 'ブ',
  'プ' => 'プ',
  'ベ' => 'ベ',
  'ペ' => 'ペ',
  'ボ' => 'ボ',
  'ポ' => 'ポ',
  'ヴ' => 'ヴ',
  'ヷ' => 'ヷ',
  'ヸ' => 'ヸ',
  'ヹ' => 'ヹ',
  'ヺ' => 'ヺ',
  'ヾ' => 'ヾ',
  '𑂚' => '𑂚',
  '𑂜' => '𑂜',
  '𑂫' => '𑂫',
  '𑄮' => '𑄮',
  '𑄯' => '𑄯',
  '𑍋' => '𑍋',
  '𑍌' => '𑍌',
  '𑒻' => '𑒻',
  '𑒼' => '𑒼',
  '𑒾' => '𑒾',
  '𑖺' => '𑖺',
  '𑖻' => '𑖻',
  '𑤸' => '𑤸',
);
Copyright (c) 2015-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Intl\Normalizer;

/**
 * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension.
 *
 * It has been validated with Unicode 6.3 Normalization Conformance Test.
 * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Normalizer
{
    public const FORM_D = \Normalizer::FORM_D;
    public const FORM_KD = \Normalizer::FORM_KD;
    public const FORM_C = \Normalizer::FORM_C;
    public const FORM_KC = \Normalizer::FORM_KC;
    public const NFD = \Normalizer::NFD;
    public const NFKD = \Normalizer::NFKD;
    public const NFC = \Normalizer::NFC;
    public const NFKC = \Normalizer::NFKC;

    private static $C;
    private static $D;
    private static $KD;
    private static $cC;
    private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
    private static $ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";

    public static function isNormalized(string $s, int $form = self::FORM_C)
    {
        if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) {
            return false;
        }
        if (!isset($s[strspn($s, self::$ASCII)])) {
            return true;
        }
        if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) {
            return true;
        }

        return self::normalize($s, $form) === $s;
    }

    public static function normalize(string $s, int $form = self::FORM_C)
    {
        if (!preg_match('//u', $s)) {
            return false;
        }

        switch ($form) {
            case self::NFC: $C = true; $K = false; break;
            case self::NFD: $C = false; $K = false; break;
            case self::NFKC: $C = true; $K = true; break;
            case self::NFKD: $C = false; $K = true; break;
            default:
                if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) {
                    return $s;
                }

                if (80000 > \PHP_VERSION_ID) {
                    return false;
                }

                throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form');
        }

        if ('' === $s) {
            return '';
        }

        if ($K && null === self::$KD) {
            self::$KD = self::getData('compatibilityDecomposition');
        }

        if (null === self::$D) {
            self::$D = self::getData('canonicalDecomposition');
            self::$cC = self::getData('combiningClass');
        }

        if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) \ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) {
            mb_internal_encoding('8bit');
        }

        $r = self::decompose($s, $K);

        if ($C) {
            if (null === self::$C) {
                self::$C = self::getData('canonicalComposition');
            }

            $r = self::recompose($r);
        }
        if (null !== $mbEncoding) {
            mb_internal_encoding($mbEncoding);
        }

        return $r;
    }

    private static function recompose($s)
    {
        $ASCII = self::$ASCII;
        $compMap = self::$C;
        $combClass = self::$cC;
        $ulenMask = self::$ulenMask;

        $result = $tail = '';

        $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"];
        $len = \strlen($s);

        $lastUchr = substr($s, 0, $i);
        $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0;

        while ($i < $len) {
            if ($s[$i] < "\x80") {
                // ASCII chars

                if ($tail) {
                    $lastUchr .= $tail;
                    $tail = '';
                }

                if ($j = strspn($s, $ASCII, $i + 1)) {
                    $lastUchr .= substr($s, $i, $j);
                    $i += $j;
                }

                $result .= $lastUchr;
                $lastUchr = $s[$i];
                $lastUcls = 0;
                ++$i;
                continue;
            }

            $ulen = $ulenMask[$s[$i] & "\xF0"];
            $uchr = substr($s, $i, $ulen);

            if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr
                || $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr
                || $lastUcls) {
                // Table lookup and combining chars composition

                $ucls = $combClass[$uchr] ?? 0;

                if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) {
                    $lastUchr = $compMap[$lastUchr.$uchr];
                } elseif ($lastUcls = $ucls) {
                    $tail .= $uchr;
                } else {
                    if ($tail) {
                        $lastUchr .= $tail;
                        $tail = '';
                    }

                    $result .= $lastUchr;
                    $lastUchr = $uchr;
                }
            } else {
                // Hangul chars

                $L = \ord($lastUchr[2]) - 0x80;
                $V = \ord($uchr[2]) - 0xA1;
                $T = 0;

                $uchr = substr($s, $i + $ulen, 3);

                if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") {
                    $T = \ord($uchr[2]) - 0xA7;
                    0 > $T && $T += 0x40;
                    $ulen += 3;
                }

                $L = 0xAC00 + ($L * 21 + $V) * 28 + $T;
                $lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F);
            }

            $i += $ulen;
        }

        return $result.$lastUchr.$tail;
    }

    private static function decompose($s, $c)
    {
        $result = '';

        $ASCII = self::$ASCII;
        $decompMap = self::$D;
        $combClass = self::$cC;
        $ulenMask = self::$ulenMask;
        if ($c) {
            $compatMap = self::$KD;
        }

        $c = [];
        $i = 0;
        $len = \strlen($s);

        while ($i < $len) {
            if ($s[$i] < "\x80") {
                // ASCII chars

                if ($c) {
                    ksort($c);
                    $result .= implode('', $c);
                    $c = [];
                }

                $j = 1 + strspn($s, $ASCII, $i + 1);
                $result .= substr($s, $i, $j);
                $i += $j;
                continue;
            }

            $ulen = $ulenMask[$s[$i] & "\xF0"];
            $uchr = substr($s, $i, $ulen);
            $i += $ulen;

            if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) {
                // Table lookup

                if ($uchr !== $j = $compatMap[$uchr] ?? ($decompMap[$uchr] ?? $uchr)) {
                    $uchr = $j;

                    $j = \strlen($uchr);
                    $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"];

                    if ($ulen != $j) {
                        // Put trailing chars in $s

                        $j -= $ulen;
                        $i -= $j;

                        if (0 > $i) {
                            $s = str_repeat(' ', -$i).$s;
                            $len -= $i;
                            $i = 0;
                        }

                        while ($j--) {
                            $s[$i + $j] = $uchr[$ulen + $j];
                        }

                        $uchr = substr($uchr, 0, $ulen);
                    }
                }
                if (isset($combClass[$uchr])) {
                    // Combining chars, for sorting

                    if (!isset($c[$combClass[$uchr]])) {
                        $c[$combClass[$uchr]] = '';
                    }
                    $c[$combClass[$uchr]] .= $uchr;
                    continue;
                }
            } else {
                // Hangul chars

                $uchr = unpack('C*', $uchr);
                $j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80;

                $uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588))
                       ."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28));

                if ($j %= 28) {
                    $uchr .= $j < 25
                        ? ("\xE1\x86".\chr(0xA7 + $j))
                        : ("\xE1\x87".\chr(0x67 + $j));
                }
            }
            if ($c) {
                ksort($c);
                $result .= implode('', $c);
                $c = [];
            }

            $result .= $uchr;
        }

        if ($c) {
            ksort($c);
            $result .= implode('', $c);
        }

        return $result;
    }

    private static function getData($file)
    {
        if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
            return require $file;
        }

        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Normalizer as p;

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('normalizer_is_normalized')) {
    function normalizer_is_normalized($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::isNormalized($string, $form); }
}
if (!function_exists('normalizer_normalize')) {
    function normalizer_normalize($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::normalize($string, $form); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Intl\Normalizer as p;

if (!function_exists('normalizer_is_normalized')) {
    function normalizer_is_normalized(?string $string, ?int $form = p\Normalizer::FORM_C): bool { return p\Normalizer::isNormalized((string) $string, (int) $form); }
}
if (!function_exists('normalizer_normalize')) {
    function normalizer_normalize(?string $string, ?int $form = p\Normalizer::FORM_C): string|false { return p\Normalizer::normalize((string) $string, (int) $form); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

use Random\Randomizer;
use Symfony\Component\String\Exception\ExceptionInterface;
use Symfony\Component\String\Exception\InvalidArgumentException;
use Symfony\Component\String\Exception\RuntimeException;

/**
 * Represents a binary-safe string of bytes.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class ByteString extends AbstractString
{
    private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';

    public function __construct(string $string = '')
    {
        $this->string = $string;
    }

    /*
     * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03)
     *
     * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16
     *
     * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE).
     *
     * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/)
     */

    public static function fromRandom(int $length = 16, ?string $alphabet = null): self
    {
        if ($length <= 0) {
            throw new InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length));
        }

        $alphabet ??= self::ALPHABET_ALPHANUMERIC;
        $alphabetSize = \strlen($alphabet);
        $bits = (int) ceil(log($alphabetSize, 2.0));
        if ($bits <= 0 || $bits > 56) {
            throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.');
        }

        if (\PHP_VERSION_ID >= 80300) {
            return new static((new Randomizer())->getBytesFromString($alphabet, $length));
        }

        $ret = '';
        while ($length > 0) {
            $urandomLength = (int) ceil(2 * $length * $bits / 8.0);
            $data = random_bytes($urandomLength);
            $unpackedData = 0;
            $unpackedBits = 0;
            for ($i = 0; $i < $urandomLength && $length > 0; ++$i) {
                // Unpack 8 bits
                $unpackedData = ($unpackedData << 8) | \ord($data[$i]);
                $unpackedBits += 8;

                // While we have enough bits to select a character from the alphabet, keep
                // consuming the random data
                for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
                    $index = ($unpackedData & ((1 << $bits) - 1));
                    $unpackedData >>= $bits;
                    // Unfortunately, the alphabet size is not necessarily a power of two.
                    // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
                    // have around a 50% chance of missing as k gets larger
                    if ($index < $alphabetSize) {
                        $ret .= $alphabet[$index];
                        --$length;
                    }
                }
            }
        }

        return new static($ret);
    }

    public function bytesAt(int $offset): array
    {
        $str = $this->string[$offset] ?? '';

        return '' === $str ? [] : [\ord($str)];
    }

    public function append(string ...$suffix): static
    {
        $str = clone $this;
        $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix);

        return $str;
    }

    public function camel(): static
    {
        $str = clone $this;

        $parts = explode(' ', trim(ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string))));
        $parts[0] = 1 !== \strlen($parts[0]) && ctype_upper($parts[0]) ? $parts[0] : lcfirst($parts[0]);
        $str->string = implode('', $parts);

        return $str;
    }

    public function chunk(int $length = 1): array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }

        if ('' === $this->string) {
            return [];
        }

        $str = clone $this;
        $chunks = [];

        foreach (str_split($this->string, $length) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }

        return $chunks;
    }

    public function endsWith(string|iterable|AbstractString $suffix): bool
    {
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }

        return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase);
    }

    public function equalsTo(string|iterable|AbstractString $string): bool
    {
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }

        if ('' !== $string && $this->ignoreCase) {
            return 0 === strcasecmp($string, $this->string);
        }

        return $string === $this->string;
    }

    public function folded(): static
    {
        $str = clone $this;
        $str->string = strtolower($str->string);

        return $str;
    }

    public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }

        if ('' === $needle) {
            return null;
        }

        $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset);

        return false === $i ? null : $i;
    }

    public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }

        if ('' === $needle) {
            return null;
        }

        $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset);

        return false === $i ? null : $i;
    }

    public function isUtf8(): bool
    {
        return '' === $this->string || preg_match('//u', $this->string);
    }

    public function join(array $strings, ?string $lastGlue = null): static
    {
        $str = clone $this;

        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : '';
        $str->string = implode($this->string, $strings).$tail;

        return $str;
    }

    public function length(): int
    {
        return \strlen($this->string);
    }

    public function lower(): static
    {
        $str = clone $this;
        $str->string = strtolower($str->string);

        return $str;
    }

    public function match(string $regexp, int $flags = 0, int $offset = 0): array
    {
        $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match';

        if ($this->ignoreCase) {
            $regexp .= 'i';
        }

        set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m));

        try {
            if (false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
                throw new RuntimeException('Matching failed with error: '.preg_last_error_msg());
            }
        } finally {
            restore_error_handler();
        }

        return $matches;
    }

    public function padBoth(int $length, string $padStr = ' '): static
    {
        $str = clone $this;
        $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH);

        return $str;
    }

    public function padEnd(int $length, string $padStr = ' '): static
    {
        $str = clone $this;
        $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT);

        return $str;
    }

    public function padStart(int $length, string $padStr = ' '): static
    {
        $str = clone $this;
        $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT);

        return $str;
    }

    public function prepend(string ...$prefix): static
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string;

        return $str;
    }

    public function replace(string $from, string $to): static
    {
        $str = clone $this;

        if ('' !== $from) {
            $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string);
        }

        return $str;
    }

    public function replaceMatches(string $fromRegexp, string|callable $to): static
    {
        if ($this->ignoreCase) {
            $fromRegexp .= 'i';
        }

        $replace = \is_array($to) || $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace';

        set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m));

        try {
            if (null === $string = $replace($fromRegexp, $to, $this->string)) {
                $lastError = preg_last_error();

                foreach (get_defined_constants(true)['pcre'] as $k => $v) {
                    if ($lastError === $v && str_ends_with($k, '_ERROR')) {
                        throw new RuntimeException('Matching failed with '.$k.'.');
                    }
                }

                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            restore_error_handler();
        }

        $str = clone $this;
        $str->string = $string;

        return $str;
    }

    public function reverse(): static
    {
        $str = clone $this;
        $str->string = strrev($str->string);

        return $str;
    }

    public function slice(int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = substr($this->string, $start, $length ?? \PHP_INT_MAX);

        return $str;
    }

    public function snake(): static
    {
        $str = $this->camel();
        $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string));

        return $str;
    }

    public function splice(string $replacement, int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);

        return $str;
    }

    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (1 > $limit ??= \PHP_INT_MAX) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }

        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }

        if (null !== $flags) {
            return parent::split($delimiter, $limit, $flags);
        }

        $str = clone $this;
        $chunks = $this->ignoreCase
            ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit)
            : explode($delimiter, $this->string, $limit);

        foreach ($chunks as &$chunk) {
            $str->string = $chunk;
            $chunk = clone $str;
        }

        return $chunks;
    }

    public function startsWith(string|iterable|AbstractString $prefix): bool
    {
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }

        return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix)));
    }

    public function title(bool $allWords = false): static
    {
        $str = clone $this;
        $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string);

        return $str;
    }

    public function toUnicodeString(?string $fromEncoding = null): UnicodeString
    {
        return new UnicodeString($this->toCodePointString($fromEncoding)->string);
    }

    public function toCodePointString(?string $fromEncoding = null): CodePointString
    {
        $u = new CodePointString();

        if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) {
            $u->string = $this->string;

            return $u;
        }

        set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m));

        try {
            try {
                $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true);
            } catch (InvalidArgumentException $e) {
                if (!\function_exists('iconv')) {
                    throw $e;
                }

                $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string);

                return $u;
            }
        } finally {
            restore_error_handler();
        }

        if (!$validEncoding) {
            throw new InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
        }

        $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');

        return $u;
    }

    public function trim(string $chars = " \t\n\r\0\x0B\x0C"): static
    {
        $str = clone $this;
        $str->string = trim($str->string, $chars);

        return $str;
    }

    public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): static
    {
        $str = clone $this;
        $str->string = rtrim($str->string, $chars);

        return $str;
    }

    public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): static
    {
        $str = clone $this;
        $str->string = ltrim($str->string, $chars);

        return $str;
    }

    public function upper(): static
    {
        $str = clone $this;
        $str->string = strtoupper($str->string);

        return $str;
    }

    public function width(bool $ignoreAnsiDecoration = true): int
    {
        $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string);

        return (new CodePointString($string))->width($ignoreAnsiDecoration);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Slugger;

use Symfony\Component\String\AbstractUnicodeString;

/**
 * Creates a URL-friendly slug from a given string.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
interface SluggerInterface
{
    /**
     * Creates a slug for the given string and locale, using appropriate transliteration when needed.
     */
    public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Slugger;

use Symfony\Component\Emoji\EmojiTransliterator;
use Symfony\Component\String\AbstractUnicodeString;
use Symfony\Component\String\UnicodeString;
use Symfony\Contracts\Translation\LocaleAwareInterface;

if (!interface_exists(LocaleAwareInterface::class)) {
    throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".');
}

/**
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
{
    private const LOCALE_TO_TRANSLITERATOR_ID = [
        'am' => 'Amharic-Latin',
        'ar' => 'Arabic-Latin',
        'az' => 'Azerbaijani-Latin',
        'be' => 'Belarusian-Latin',
        'bg' => 'Bulgarian-Latin',
        'bn' => 'Bengali-Latin',
        'de' => 'de-ASCII',
        'el' => 'Greek-Latin',
        'fa' => 'Persian-Latin',
        'he' => 'Hebrew-Latin',
        'hy' => 'Armenian-Latin',
        'ka' => 'Georgian-Latin',
        'kk' => 'Kazakh-Latin',
        'ky' => 'Kirghiz-Latin',
        'ko' => 'Korean-Latin',
        'mk' => 'Macedonian-Latin',
        'mn' => 'Mongolian-Latin',
        'or' => 'Oriya-Latin',
        'ps' => 'Pashto-Latin',
        'ru' => 'Russian-Latin',
        'sr' => 'Serbian-Latin',
        'sr_Cyrl' => 'Serbian-Latin',
        'th' => 'Thai-Latin',
        'tk' => 'Turkmen-Latin',
        'uk' => 'Ukrainian-Latin',
        'uz' => 'Uzbek-Latin',
        'zh' => 'Han-Latin',
    ];

    private \Closure|array $symbolsMap = [
        'en' => ['@' => 'at', '&' => 'and'],
    ];
    private bool|string $emoji = false;

    /**
     * Cache of transliterators per locale.
     *
     * @var \Transliterator[]
     */
    private array $transliterators = [];

    public function __construct(
        private ?string $defaultLocale = null,
        array|\Closure|null $symbolsMap = null,
    ) {
        $this->symbolsMap = $symbolsMap ?? $this->symbolsMap;
    }

    public function setLocale(string $locale): void
    {
        $this->defaultLocale = $locale;
    }

    public function getLocale(): string
    {
        return $this->defaultLocale;
    }

    /**
     * @param bool|string $emoji true will use the same locale,
     *                           false will disable emoji,
     *                           and a string to use a specific locale
     */
    public function withEmoji(bool|string $emoji = true): static
    {
        if (false !== $emoji && !class_exists(EmojiTransliterator::class)) {
            throw new \LogicException(\sprintf('You cannot use the "%s()" method as the "symfony/emoji" package is not installed. Try running "composer require symfony/emoji".', __METHOD__));
        }

        $new = clone $this;
        $new->emoji = $emoji;

        return $new;
    }

    public function slug(string $string, string $separator = '-', ?string $locale = null): AbstractUnicodeString
    {
        $locale ??= $this->defaultLocale;

        $transliterator = [];
        if ($locale && ('de' === $locale || str_starts_with($locale, 'de_'))) {
            // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl)
            $transliterator = ['de-ASCII'];
        } elseif (\function_exists('transliterator_transliterate') && $locale) {
            $transliterator = (array) $this->createTransliterator($locale);
        }

        if ($emojiTransliterator = $this->createEmojiTransliterator($locale)) {
            $transliterator[] = $emojiTransliterator;
        }

        if ($this->symbolsMap instanceof \Closure) {
            // If the symbols map is passed as a closure, there is no need to fallback to the parent locale
            // as the closure can just provide substitutions for all locales of interest.
            $symbolsMap = $this->symbolsMap;
            array_unshift($transliterator, static fn ($s) => $symbolsMap($s, $locale));
        }

        $unicodeString = (new UnicodeString($string))->ascii($transliterator);

        if (\is_array($this->symbolsMap)) {
            $map = null;
            if (isset($this->symbolsMap[$locale ?? ''])) {
                $map = $this->symbolsMap[$locale ?? ''];
            } else {
                $parent = self::getParentLocale($locale);
                if ($parent && isset($this->symbolsMap[$parent])) {
                    $map = $this->symbolsMap[$parent];
                }
            }
            if ($map) {
                foreach ($map as $char => $replace) {
                    $unicodeString = $unicodeString->replace($char, ' '.$replace.' ');
                }
            }
        }

        return $unicodeString
            ->replaceMatches('/[^A-Za-z0-9]++/', $separator)
            ->trim($separator)
        ;
    }

    private function createTransliterator(string $locale): ?\Transliterator
    {
        if (\array_key_exists($locale, $this->transliterators)) {
            return $this->transliterators[$locale];
        }

        // Exact locale supported, cache and return
        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) {
            return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
        }

        // Locale not supported and no parent, fallback to any-latin
        if (!$parent = self::getParentLocale($locale)) {
            return $this->transliterators[$locale] = null;
        }

        // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
            $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id);
        }

        return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
    }

    private function createEmojiTransliterator(?string $locale): ?EmojiTransliterator
    {
        if (\is_string($this->emoji)) {
            $locale = $this->emoji;
        } elseif (!$this->emoji) {
            return null;
        }

        while (null !== $locale) {
            try {
                return EmojiTransliterator::create("emoji-$locale");
            } catch (\IntlException) {
                $locale = self::getParentLocale($locale);
            }
        }

        return null;
    }

    private static function getParentLocale(?string $locale): ?string
    {
        if (!$locale) {
            return null;
        }
        if (false === $str = strrchr($locale, '_')) {
            // no parent locale
            return null;
        }

        return substr($locale, 0, -\strlen($str));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

use Symfony\Component\String\Exception\ExceptionInterface;
use Symfony\Component\String\Exception\InvalidArgumentException;
use Symfony\Component\String\Exception\RuntimeException;

/**
 * Represents a string of abstract characters.
 *
 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
 * This class is the abstract type to use as a type-hint when the logic you want to
 * implement doesn't care about the exact variant it deals with.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
abstract class AbstractString implements \Stringable, \JsonSerializable
{
    public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER;
    public const PREG_SET_ORDER = \PREG_SET_ORDER;
    public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE;
    public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL;

    public const PREG_SPLIT = 0;
    public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY;
    public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE;
    public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE;

    protected string $string = '';
    protected ?bool $ignoreCase = false;

    abstract public function __construct(string $string = '');

    /**
     * Unwraps instances of AbstractString back to strings.
     *
     * @return string[]|array
     */
    public static function unwrap(array $values): array
    {
        foreach ($values as $k => $v) {
            if ($v instanceof self) {
                $values[$k] = $v->__toString();
            } elseif (\is_array($v) && $values[$k] !== $v = static::unwrap($v)) {
                $values[$k] = $v;
            }
        }

        return $values;
    }

    /**
     * Wraps (and normalizes) strings in instances of AbstractString.
     *
     * @return static[]|array
     */
    public static function wrap(array $values): array
    {
        $i = 0;
        $keys = null;

        foreach ($values as $k => $v) {
            if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) {
                $keys ??= array_keys($values);
                $keys[$i] = $j;
            }

            if (\is_string($v)) {
                $values[$k] = new static($v);
            } elseif (\is_array($v) && $values[$k] !== $v = static::wrap($v)) {
                $values[$k] = $v;
            }

            ++$i;
        }

        return null !== $keys ? array_combine($keys, $values) : $values;
    }

    /**
     * @param string|string[] $needle
     */
    public function after(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static
    {
        $str = clone $this;
        $i = \PHP_INT_MAX;

        if (\is_string($needle)) {
            $needle = [$needle];
        }

        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOf($n, $offset);

            if (null !== $j && $j < $i) {
                $i = $j;
                $str->string = $n;
            }
        }

        if (\PHP_INT_MAX === $i) {
            return $str;
        }

        if (!$includeNeedle) {
            $i += $str->length();
        }

        return $this->slice($i);
    }

    /**
     * @param string|string[] $needle
     */
    public function afterLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static
    {
        $str = clone $this;
        $i = null;

        if (\is_string($needle)) {
            $needle = [$needle];
        }

        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOfLast($n, $offset);

            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
                $str->string = $n;
            }
        }

        if (null === $i) {
            return $str;
        }

        if (!$includeNeedle) {
            $i += $str->length();
        }

        return $this->slice($i);
    }

    abstract public function append(string ...$suffix): static;

    /**
     * @param string|string[] $needle
     */
    public function before(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static
    {
        $str = clone $this;
        $i = \PHP_INT_MAX;

        if (\is_string($needle)) {
            $needle = [$needle];
        }

        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOf($n, $offset);

            if (null !== $j && $j < $i) {
                $i = $j;
                $str->string = $n;
            }
        }

        if (\PHP_INT_MAX === $i) {
            return $str;
        }

        if ($includeNeedle) {
            $i += $str->length();
        }

        return $this->slice(0, $i);
    }

    /**
     * @param string|string[] $needle
     */
    public function beforeLast(string|iterable $needle, bool $includeNeedle = false, int $offset = 0): static
    {
        $str = clone $this;
        $i = null;

        if (\is_string($needle)) {
            $needle = [$needle];
        }

        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOfLast($n, $offset);

            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
                $str->string = $n;
            }
        }

        if (null === $i) {
            return $str;
        }

        if ($includeNeedle) {
            $i += $str->length();
        }

        return $this->slice(0, $i);
    }

    /**
     * @return int[]
     */
    public function bytesAt(int $offset): array
    {
        $str = $this->slice($offset, 1);

        return '' === $str->string ? [] : array_values(unpack('C*', $str->string));
    }

    abstract public function camel(): static;

    /**
     * @return static[]
     */
    abstract public function chunk(int $length = 1): array;

    public function collapseWhitespace(): static
    {
        $str = clone $this;
        $str->string = trim(preg_replace("/(?:[ \n\r\t\x0C]{2,}+|[\n\r\t\x0C])/", ' ', $str->string), " \n\r\t\x0C");

        return $str;
    }

    /**
     * @param string|string[] $needle
     */
    public function containsAny(string|iterable $needle): bool
    {
        return null !== $this->indexOf($needle);
    }

    /**
     * @param string|string[] $suffix
     */
    public function endsWith(string|iterable $suffix): bool
    {
        if (\is_string($suffix)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }

        foreach ($suffix as $s) {
            if ($this->endsWith((string) $s)) {
                return true;
            }
        }

        return false;
    }

    public function ensureEnd(string $suffix): static
    {
        if (!$this->endsWith($suffix)) {
            return $this->append($suffix);
        }

        $suffix = preg_quote($suffix);
        $regex = '{('.$suffix.')(?:'.$suffix.')++$}D';

        return $this->replaceMatches($regex.($this->ignoreCase ? 'i' : ''), '$1');
    }

    public function ensureStart(string $prefix): static
    {
        $prefix = new static($prefix);

        if (!$this->startsWith($prefix)) {
            return $this->prepend($prefix);
        }

        $str = clone $this;
        $i = $prefixLen = $prefix->length();

        while ($this->indexOf($prefix, $i) === $i) {
            $str = $str->slice($prefixLen);
            $i += $prefixLen;
        }

        return $str;
    }

    /**
     * @param string|string[] $string
     */
    public function equalsTo(string|iterable $string): bool
    {
        if (\is_string($string)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }

        foreach ($string as $s) {
            if ($this->equalsTo((string) $s)) {
                return true;
            }
        }

        return false;
    }

    abstract public function folded(): static;

    public function ignoreCase(): static
    {
        $str = clone $this;
        $str->ignoreCase = true;

        return $str;
    }

    /**
     * @param string|string[] $needle
     */
    public function indexOf(string|iterable $needle, int $offset = 0): ?int
    {
        if (\is_string($needle)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }

        $i = \PHP_INT_MAX;

        foreach ($needle as $n) {
            $j = $this->indexOf((string) $n, $offset);

            if (null !== $j && $j < $i) {
                $i = $j;
            }
        }

        return \PHP_INT_MAX === $i ? null : $i;
    }

    /**
     * @param string|string[] $needle
     */
    public function indexOfLast(string|iterable $needle, int $offset = 0): ?int
    {
        if (\is_string($needle)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }

        $i = null;

        foreach ($needle as $n) {
            $j = $this->indexOfLast((string) $n, $offset);

            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
            }
        }

        return $i;
    }

    public function isEmpty(): bool
    {
        return '' === $this->string;
    }

    abstract public function join(array $strings, ?string $lastGlue = null): static;

    public function jsonSerialize(): string
    {
        return $this->string;
    }

    abstract public function length(): int;

    abstract public function lower(): static;

    /**
     * Matches the string using a regular expression.
     *
     * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression.
     *
     * @return array All matches in a multi-dimensional array ordered according to flags
     */
    abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array;

    abstract public function padBoth(int $length, string $padStr = ' '): static;

    abstract public function padEnd(int $length, string $padStr = ' '): static;

    abstract public function padStart(int $length, string $padStr = ' '): static;

    abstract public function prepend(string ...$prefix): static;

    public function repeat(int $multiplier): static
    {
        if (0 > $multiplier) {
            throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
        }

        $str = clone $this;
        $str->string = str_repeat($str->string, $multiplier);

        return $str;
    }

    abstract public function replace(string $from, string $to): static;

    abstract public function replaceMatches(string $fromRegexp, string|callable $to): static;

    abstract public function reverse(): static;

    abstract public function slice(int $start = 0, ?int $length = null): static;

    abstract public function snake(): static;

    public function kebab(): static
    {
        return $this->snake()->replace('_', '-');
    }

    public function pascal(): static
    {
        return $this->camel()->title();
    }

    abstract public function splice(string $replacement, int $start = 0, ?int $length = null): static;

    /**
     * @return static[]
     */
    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (null === $flags) {
            throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.');
        }

        if ($this->ignoreCase) {
            $delimiter .= 'i';
        }

        set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m));

        try {
            if (false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) {
                throw new RuntimeException('Splitting failed with error: '.preg_last_error_msg());
            }
        } finally {
            restore_error_handler();
        }

        $str = clone $this;

        if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) {
            foreach ($chunks as &$chunk) {
                $str->string = $chunk[0];
                $chunk[0] = clone $str;
            }
        } else {
            foreach ($chunks as &$chunk) {
                $str->string = $chunk;
                $chunk = clone $str;
            }
        }

        return $chunks;
    }

    /**
     * @param string|string[] $prefix
     */
    public function startsWith(string|iterable $prefix): bool
    {
        if (\is_string($prefix)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }

        foreach ($prefix as $prefix) {
            if ($this->startsWith((string) $prefix)) {
                return true;
            }
        }

        return false;
    }

    abstract public function title(bool $allWords = false): static;

    public function toByteString(?string $toEncoding = null): ByteString
    {
        $b = new ByteString();

        $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], true) ? 'UTF-8' : $toEncoding;

        if (null === $toEncoding || $toEncoding === $fromEncoding = $this instanceof AbstractUnicodeString || preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252') {
            $b->string = $this->string;

            return $b;
        }

        try {
            $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8');
        } catch (\ValueError $e) {
            if (!\function_exists('iconv')) {
                throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
            }

            $b->string = iconv('UTF-8', $toEncoding, $this->string);
        }

        return $b;
    }

    public function toCodePointString(): CodePointString
    {
        return new CodePointString($this->string);
    }

    public function toString(): string
    {
        return $this->string;
    }

    public function toUnicodeString(): UnicodeString
    {
        return new UnicodeString($this->string);
    }

    abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static;

    abstract public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static;

    /**
     * @param string|string[] $prefix
     */
    public function trimPrefix($prefix): static
    {
        if (\is_array($prefix) || $prefix instanceof \Traversable) { // don't use is_iterable(), it's slow
            foreach ($prefix as $s) {
                $t = $this->trimPrefix($s);

                if ($t->string !== $this->string) {
                    return $t;
                }
            }

            return clone $this;
        }

        $str = clone $this;

        if ($prefix instanceof self) {
            $prefix = $prefix->string;
        } else {
            $prefix = (string) $prefix;
        }

        if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) {
            $str->string = substr($this->string, \strlen($prefix));
        }

        return $str;
    }

    abstract public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static;

    /**
     * @param string|string[] $suffix
     */
    public function trimSuffix($suffix): static
    {
        if (\is_array($suffix) || $suffix instanceof \Traversable) { // don't use is_iterable(), it's slow
            foreach ($suffix as $s) {
                $t = $this->trimSuffix($s);

                if ($t->string !== $this->string) {
                    return $t;
                }
            }

            return clone $this;
        }

        $str = clone $this;

        if ($suffix instanceof self) {
            $suffix = $suffix->string;
        } else {
            $suffix = (string) $suffix;
        }

        if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) {
            $str->string = substr($this->string, 0, -\strlen($suffix));
        }

        return $str;
    }

    public function truncate(int $length, string $ellipsis = '', bool|TruncateMode $cut = TruncateMode::Char): static
    {
        $stringLength = $this->length();

        if ($stringLength <= $length) {
            return clone $this;
        }

        $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0;

        if ($length < $ellipsisLength) {
            $ellipsisLength = 0;
        }

        $desiredLength = $length;
        if (TruncateMode::WordAfter === $cut || !$cut) {
            if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) {
                return clone $this;
            }

            $length += $ellipsisLength;
        } elseif (TruncateMode::WordBefore === $cut && null !== $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) {
            $length += $ellipsisLength;
        }

        $str = $this->slice(0, $length - $ellipsisLength);

        if (TruncateMode::WordBefore === $cut) {
            if (0 === $ellipsisLength && $desiredLength === $this->indexOf([' ', "\r", "\n", "\t"], $length)) {
                return $str;
            }

            $str = $str->beforeLast([' ', "\r", "\n", "\t"]);
        }

        return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
    }

    abstract public function upper(): static;

    /**
     * Returns the printable length on a terminal.
     */
    abstract public function width(bool $ignoreAnsiDecoration = true): int;

    public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): static
    {
        $lines = '' !== $break ? $this->split($break) : [clone $this];
        $chars = [];
        $mask = '';

        if (1 === \count($lines) && '' === $lines[0]->string) {
            return $lines[0];
        }

        foreach ($lines as $i => $line) {
            if ($i) {
                $chars[] = $break;
                $mask .= '#';
            }

            foreach ($line->chunk() as $char) {
                $chars[] = $char->string;
                $mask .= ' ' === $char->string ? ' ' : '?';
            }
        }

        $string = '';
        $j = 0;
        $b = $i = -1;
        $mask = wordwrap($mask, $width, '#', $cut);

        while (false !== $b = strpos($mask, '#', $b + 1)) {
            for (++$i; $i < $b; ++$i) {
                $string .= $chars[$j];
                unset($chars[$j++]);
            }

            if ($break === $chars[$j] || ' ' === $chars[$j]) {
                unset($chars[$j++]);
            }

            $string .= $break;
        }

        $str = clone $this;
        $str->string = $string.implode('', $chars);

        return $str;
    }

    public function __serialize(): array
    {
        if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) {
            return ['string' => $this->string];
        }

        trigger_deprecation('symfony/string', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));

        $data = [];
        foreach ($this->__sleep() as $key) {
            try {
                if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
                    $data[$key] = $r->getValue($this);
                }
            } catch (\ReflectionException) {
                $data[$key] = $this->$key;
            }
        }

        return $data;
    }

    /**
     * @deprecated since Symfony 7.4, will be replaced by `__unserialize()` in 8.0
     */
    public function __sleep(): array
    {
        trigger_deprecation('symfony/string', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));

        return ['string'];
    }

    public function __clone()
    {
        $this->ignoreCase = false;
    }

    public function __toString(): string
    {
        return $this->string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

if (!\function_exists(u::class)) {
    function u(?string $string = ''): UnicodeString
    {
        return new UnicodeString($string ?? '');
    }
}

if (!\function_exists(b::class)) {
    function b(?string $string = ''): ByteString
    {
        return new ByteString($string ?? '');
    }
}

if (!\function_exists(s::class)) {
    /**
     * @return UnicodeString|ByteString
     */
    function s(?string $string = ''): AbstractString
    {
        $string ??= '';

        return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string);
    }
}
<?php

/*
 * This file has been auto-generated by the Symfony String Component for internal use.
 *
 * Unicode version: 16.0.0
 * Date: 2024-09-11T08:21:22+00:00
 */

return [
    [
        768,
        879,
    ],
    [
        1155,
        1159,
    ],
    [
        1160,
        1161,
    ],
    [
        1425,
        1469,
    ],
    [
        1471,
        1471,
    ],
    [
        1473,
        1474,
    ],
    [
        1476,
        1477,
    ],
    [
        1479,
        1479,
    ],
    [
        1552,
        1562,
    ],
    [
        1611,
        1631,
    ],
    [
        1648,
        1648,
    ],
    [
        1750,
        1756,
    ],
    [
        1759,
        1764,
    ],
    [
        1767,
        1768,
    ],
    [
        1770,
        1773,
    ],
    [
        1809,
        1809,
    ],
    [
        1840,
        1866,
    ],
    [
        1958,
        1968,
    ],
    [
        2027,
        2035,
    ],
    [
        2045,
        2045,
    ],
    [
        2070,
        2073,
    ],
    [
        2075,
        2083,
    ],
    [
        2085,
        2087,
    ],
    [
        2089,
        2093,
    ],
    [
        2137,
        2139,
    ],
    [
        2199,
        2207,
    ],
    [
        2250,
        2273,
    ],
    [
        2275,
        2306,
    ],
    [
        2362,
        2362,
    ],
    [
        2364,
        2364,
    ],
    [
        2369,
        2376,
    ],
    [
        2381,
        2381,
    ],
    [
        2385,
        2391,
    ],
    [
        2402,
        2403,
    ],
    [
        2433,
        2433,
    ],
    [
        2492,
        2492,
    ],
    [
        2497,
        2500,
    ],
    [
        2509,
        2509,
    ],
    [
        2530,
        2531,
    ],
    [
        2558,
        2558,
    ],
    [
        2561,
        2562,
    ],
    [
        2620,
        2620,
    ],
    [
        2625,
        2626,
    ],
    [
        2631,
        2632,
    ],
    [
        2635,
        2637,
    ],
    [
        2641,
        2641,
    ],
    [
        2672,
        2673,
    ],
    [
        2677,
        2677,
    ],
    [
        2689,
        2690,
    ],
    [
        2748,
        2748,
    ],
    [
        2753,
        2757,
    ],
    [
        2759,
        2760,
    ],
    [
        2765,
        2765,
    ],
    [
        2786,
        2787,
    ],
    [
        2810,
        2815,
    ],
    [
        2817,
        2817,
    ],
    [
        2876,
        2876,
    ],
    [
        2879,
        2879,
    ],
    [
        2881,
        2884,
    ],
    [
        2893,
        2893,
    ],
    [
        2901,
        2902,
    ],
    [
        2914,
        2915,
    ],
    [
        2946,
        2946,
    ],
    [
        3008,
        3008,
    ],
    [
        3021,
        3021,
    ],
    [
        3072,
        3072,
    ],
    [
        3076,
        3076,
    ],
    [
        3132,
        3132,
    ],
    [
        3134,
        3136,
    ],
    [
        3142,
        3144,
    ],
    [
        3146,
        3149,
    ],
    [
        3157,
        3158,
    ],
    [
        3170,
        3171,
    ],
    [
        3201,
        3201,
    ],
    [
        3260,
        3260,
    ],
    [
        3263,
        3263,
    ],
    [
        3270,
        3270,
    ],
    [
        3276,
        3277,
    ],
    [
        3298,
        3299,
    ],
    [
        3328,
        3329,
    ],
    [
        3387,
        3388,
    ],
    [
        3393,
        3396,
    ],
    [
        3405,
        3405,
    ],
    [
        3426,
        3427,
    ],
    [
        3457,
        3457,
    ],
    [
        3530,
        3530,
    ],
    [
        3538,
        3540,
    ],
    [
        3542,
        3542,
    ],
    [
        3633,
        3633,
    ],
    [
        3636,
        3642,
    ],
    [
        3655,
        3662,
    ],
    [
        3761,
        3761,
    ],
    [
        3764,
        3772,
    ],
    [
        3784,
        3790,
    ],
    [
        3864,
        3865,
    ],
    [
        3893,
        3893,
    ],
    [
        3895,
        3895,
    ],
    [
        3897,
        3897,
    ],
    [
        3953,
        3966,
    ],
    [
        3968,
        3972,
    ],
    [
        3974,
        3975,
    ],
    [
        3981,
        3991,
    ],
    [
        3993,
        4028,
    ],
    [
        4038,
        4038,
    ],
    [
        4141,
        4144,
    ],
    [
        4146,
        4151,
    ],
    [
        4153,
        4154,
    ],
    [
        4157,
        4158,
    ],
    [
        4184,
        4185,
    ],
    [
        4190,
        4192,
    ],
    [
        4209,
        4212,
    ],
    [
        4226,
        4226,
    ],
    [
        4229,
        4230,
    ],
    [
        4237,
        4237,
    ],
    [
        4253,
        4253,
    ],
    [
        4957,
        4959,
    ],
    [
        5906,
        5908,
    ],
    [
        5938,
        5939,
    ],
    [
        5970,
        5971,
    ],
    [
        6002,
        6003,
    ],
    [
        6068,
        6069,
    ],
    [
        6071,
        6077,
    ],
    [
        6086,
        6086,
    ],
    [
        6089,
        6099,
    ],
    [
        6109,
        6109,
    ],
    [
        6155,
        6157,
    ],
    [
        6159,
        6159,
    ],
    [
        6277,
        6278,
    ],
    [
        6313,
        6313,
    ],
    [
        6432,
        6434,
    ],
    [
        6439,
        6440,
    ],
    [
        6450,
        6450,
    ],
    [
        6457,
        6459,
    ],
    [
        6679,
        6680,
    ],
    [
        6683,
        6683,
    ],
    [
        6742,
        6742,
    ],
    [
        6744,
        6750,
    ],
    [
        6752,
        6752,
    ],
    [
        6754,
        6754,
    ],
    [
        6757,
        6764,
    ],
    [
        6771,
        6780,
    ],
    [
        6783,
        6783,
    ],
    [
        6832,
        6845,
    ],
    [
        6846,
        6846,
    ],
    [
        6847,
        6862,
    ],
    [
        6912,
        6915,
    ],
    [
        6964,
        6964,
    ],
    [
        6966,
        6970,
    ],
    [
        6972,
        6972,
    ],
    [
        6978,
        6978,
    ],
    [
        7019,
        7027,
    ],
    [
        7040,
        7041,
    ],
    [
        7074,
        7077,
    ],
    [
        7080,
        7081,
    ],
    [
        7083,
        7085,
    ],
    [
        7142,
        7142,
    ],
    [
        7144,
        7145,
    ],
    [
        7149,
        7149,
    ],
    [
        7151,
        7153,
    ],
    [
        7212,
        7219,
    ],
    [
        7222,
        7223,
    ],
    [
        7376,
        7378,
    ],
    [
        7380,
        7392,
    ],
    [
        7394,
        7400,
    ],
    [
        7405,
        7405,
    ],
    [
        7412,
        7412,
    ],
    [
        7416,
        7417,
    ],
    [
        7616,
        7679,
    ],
    [
        8400,
        8412,
    ],
    [
        8413,
        8416,
    ],
    [
        8417,
        8417,
    ],
    [
        8418,
        8420,
    ],
    [
        8421,
        8432,
    ],
    [
        11503,
        11505,
    ],
    [
        11647,
        11647,
    ],
    [
        11744,
        11775,
    ],
    [
        12330,
        12333,
    ],
    [
        12441,
        12442,
    ],
    [
        42607,
        42607,
    ],
    [
        42608,
        42610,
    ],
    [
        42612,
        42621,
    ],
    [
        42654,
        42655,
    ],
    [
        42736,
        42737,
    ],
    [
        43010,
        43010,
    ],
    [
        43014,
        43014,
    ],
    [
        43019,
        43019,
    ],
    [
        43045,
        43046,
    ],
    [
        43052,
        43052,
    ],
    [
        43204,
        43205,
    ],
    [
        43232,
        43249,
    ],
    [
        43263,
        43263,
    ],
    [
        43302,
        43309,
    ],
    [
        43335,
        43345,
    ],
    [
        43392,
        43394,
    ],
    [
        43443,
        43443,
    ],
    [
        43446,
        43449,
    ],
    [
        43452,
        43453,
    ],
    [
        43493,
        43493,
    ],
    [
        43561,
        43566,
    ],
    [
        43569,
        43570,
    ],
    [
        43573,
        43574,
    ],
    [
        43587,
        43587,
    ],
    [
        43596,
        43596,
    ],
    [
        43644,
        43644,
    ],
    [
        43696,
        43696,
    ],
    [
        43698,
        43700,
    ],
    [
        43703,
        43704,
    ],
    [
        43710,
        43711,
    ],
    [
        43713,
        43713,
    ],
    [
        43756,
        43757,
    ],
    [
        43766,
        43766,
    ],
    [
        44005,
        44005,
    ],
    [
        44008,
        44008,
    ],
    [
        44013,
        44013,
    ],
    [
        64286,
        64286,
    ],
    [
        65024,
        65039,
    ],
    [
        65056,
        65071,
    ],
    [
        66045,
        66045,
    ],
    [
        66272,
        66272,
    ],
    [
        66422,
        66426,
    ],
    [
        68097,
        68099,
    ],
    [
        68101,
        68102,
    ],
    [
        68108,
        68111,
    ],
    [
        68152,
        68154,
    ],
    [
        68159,
        68159,
    ],
    [
        68325,
        68326,
    ],
    [
        68900,
        68903,
    ],
    [
        68969,
        68973,
    ],
    [
        69291,
        69292,
    ],
    [
        69372,
        69375,
    ],
    [
        69446,
        69456,
    ],
    [
        69506,
        69509,
    ],
    [
        69633,
        69633,
    ],
    [
        69688,
        69702,
    ],
    [
        69744,
        69744,
    ],
    [
        69747,
        69748,
    ],
    [
        69759,
        69761,
    ],
    [
        69811,
        69814,
    ],
    [
        69817,
        69818,
    ],
    [
        69826,
        69826,
    ],
    [
        69888,
        69890,
    ],
    [
        69927,
        69931,
    ],
    [
        69933,
        69940,
    ],
    [
        70003,
        70003,
    ],
    [
        70016,
        70017,
    ],
    [
        70070,
        70078,
    ],
    [
        70089,
        70092,
    ],
    [
        70095,
        70095,
    ],
    [
        70191,
        70193,
    ],
    [
        70196,
        70196,
    ],
    [
        70198,
        70199,
    ],
    [
        70206,
        70206,
    ],
    [
        70209,
        70209,
    ],
    [
        70367,
        70367,
    ],
    [
        70371,
        70378,
    ],
    [
        70400,
        70401,
    ],
    [
        70459,
        70460,
    ],
    [
        70464,
        70464,
    ],
    [
        70502,
        70508,
    ],
    [
        70512,
        70516,
    ],
    [
        70587,
        70592,
    ],
    [
        70606,
        70606,
    ],
    [
        70608,
        70608,
    ],
    [
        70610,
        70610,
    ],
    [
        70625,
        70626,
    ],
    [
        70712,
        70719,
    ],
    [
        70722,
        70724,
    ],
    [
        70726,
        70726,
    ],
    [
        70750,
        70750,
    ],
    [
        70835,
        70840,
    ],
    [
        70842,
        70842,
    ],
    [
        70847,
        70848,
    ],
    [
        70850,
        70851,
    ],
    [
        71090,
        71093,
    ],
    [
        71100,
        71101,
    ],
    [
        71103,
        71104,
    ],
    [
        71132,
        71133,
    ],
    [
        71219,
        71226,
    ],
    [
        71229,
        71229,
    ],
    [
        71231,
        71232,
    ],
    [
        71339,
        71339,
    ],
    [
        71341,
        71341,
    ],
    [
        71344,
        71349,
    ],
    [
        71351,
        71351,
    ],
    [
        71453,
        71453,
    ],
    [
        71455,
        71455,
    ],
    [
        71458,
        71461,
    ],
    [
        71463,
        71467,
    ],
    [
        71727,
        71735,
    ],
    [
        71737,
        71738,
    ],
    [
        71995,
        71996,
    ],
    [
        71998,
        71998,
    ],
    [
        72003,
        72003,
    ],
    [
        72148,
        72151,
    ],
    [
        72154,
        72155,
    ],
    [
        72160,
        72160,
    ],
    [
        72193,
        72202,
    ],
    [
        72243,
        72248,
    ],
    [
        72251,
        72254,
    ],
    [
        72263,
        72263,
    ],
    [
        72273,
        72278,
    ],
    [
        72281,
        72283,
    ],
    [
        72330,
        72342,
    ],
    [
        72344,
        72345,
    ],
    [
        72752,
        72758,
    ],
    [
        72760,
        72765,
    ],
    [
        72767,
        72767,
    ],
    [
        72850,
        72871,
    ],
    [
        72874,
        72880,
    ],
    [
        72882,
        72883,
    ],
    [
        72885,
        72886,
    ],
    [
        73009,
        73014,
    ],
    [
        73018,
        73018,
    ],
    [
        73020,
        73021,
    ],
    [
        73023,
        73029,
    ],
    [
        73031,
        73031,
    ],
    [
        73104,
        73105,
    ],
    [
        73109,
        73109,
    ],
    [
        73111,
        73111,
    ],
    [
        73459,
        73460,
    ],
    [
        73472,
        73473,
    ],
    [
        73526,
        73530,
    ],
    [
        73536,
        73536,
    ],
    [
        73538,
        73538,
    ],
    [
        73562,
        73562,
    ],
    [
        78912,
        78912,
    ],
    [
        78919,
        78933,
    ],
    [
        90398,
        90409,
    ],
    [
        90413,
        90415,
    ],
    [
        92912,
        92916,
    ],
    [
        92976,
        92982,
    ],
    [
        94031,
        94031,
    ],
    [
        94095,
        94098,
    ],
    [
        94180,
        94180,
    ],
    [
        113821,
        113822,
    ],
    [
        118528,
        118573,
    ],
    [
        118576,
        118598,
    ],
    [
        119143,
        119145,
    ],
    [
        119163,
        119170,
    ],
    [
        119173,
        119179,
    ],
    [
        119210,
        119213,
    ],
    [
        119362,
        119364,
    ],
    [
        121344,
        121398,
    ],
    [
        121403,
        121452,
    ],
    [
        121461,
        121461,
    ],
    [
        121476,
        121476,
    ],
    [
        121499,
        121503,
    ],
    [
        121505,
        121519,
    ],
    [
        122880,
        122886,
    ],
    [
        122888,
        122904,
    ],
    [
        122907,
        122913,
    ],
    [
        122915,
        122916,
    ],
    [
        122918,
        122922,
    ],
    [
        123023,
        123023,
    ],
    [
        123184,
        123190,
    ],
    [
        123566,
        123566,
    ],
    [
        123628,
        123631,
    ],
    [
        124140,
        124143,
    ],
    [
        124398,
        124399,
    ],
    [
        125136,
        125142,
    ],
    [
        125252,
        125258,
    ],
    [
        917760,
        917999,
    ],
];
<?php

/*
 * This file has been auto-generated by the Symfony String Component for internal use.
 *
 * Unicode version: 16.0.0
 * Date: 2024-09-11T08:21:22+00:00
 */

return [
    [
        4352,
        4447,
    ],
    [
        8986,
        8987,
    ],
    [
        9001,
        9001,
    ],
    [
        9002,
        9002,
    ],
    [
        9193,
        9196,
    ],
    [
        9200,
        9200,
    ],
    [
        9203,
        9203,
    ],
    [
        9725,
        9726,
    ],
    [
        9748,
        9749,
    ],
    [
        9776,
        9783,
    ],
    [
        9800,
        9811,
    ],
    [
        9855,
        9855,
    ],
    [
        9866,
        9871,
    ],
    [
        9875,
        9875,
    ],
    [
        9889,
        9889,
    ],
    [
        9898,
        9899,
    ],
    [
        9917,
        9918,
    ],
    [
        9924,
        9925,
    ],
    [
        9934,
        9934,
    ],
    [
        9940,
        9940,
    ],
    [
        9962,
        9962,
    ],
    [
        9970,
        9971,
    ],
    [
        9973,
        9973,
    ],
    [
        9978,
        9978,
    ],
    [
        9981,
        9981,
    ],
    [
        9989,
        9989,
    ],
    [
        9994,
        9995,
    ],
    [
        10024,
        10024,
    ],
    [
        10060,
        10060,
    ],
    [
        10062,
        10062,
    ],
    [
        10067,
        10069,
    ],
    [
        10071,
        10071,
    ],
    [
        10133,
        10135,
    ],
    [
        10160,
        10160,
    ],
    [
        10175,
        10175,
    ],
    [
        11035,
        11036,
    ],
    [
        11088,
        11088,
    ],
    [
        11093,
        11093,
    ],
    [
        11904,
        11929,
    ],
    [
        11931,
        12019,
    ],
    [
        12032,
        12245,
    ],
    [
        12272,
        12287,
    ],
    [
        12288,
        12288,
    ],
    [
        12289,
        12291,
    ],
    [
        12292,
        12292,
    ],
    [
        12293,
        12293,
    ],
    [
        12294,
        12294,
    ],
    [
        12295,
        12295,
    ],
    [
        12296,
        12296,
    ],
    [
        12297,
        12297,
    ],
    [
        12298,
        12298,
    ],
    [
        12299,
        12299,
    ],
    [
        12300,
        12300,
    ],
    [
        12301,
        12301,
    ],
    [
        12302,
        12302,
    ],
    [
        12303,
        12303,
    ],
    [
        12304,
        12304,
    ],
    [
        12305,
        12305,
    ],
    [
        12306,
        12307,
    ],
    [
        12308,
        12308,
    ],
    [
        12309,
        12309,
    ],
    [
        12310,
        12310,
    ],
    [
        12311,
        12311,
    ],
    [
        12312,
        12312,
    ],
    [
        12313,
        12313,
    ],
    [
        12314,
        12314,
    ],
    [
        12315,
        12315,
    ],
    [
        12316,
        12316,
    ],
    [
        12317,
        12317,
    ],
    [
        12318,
        12319,
    ],
    [
        12320,
        12320,
    ],
    [
        12321,
        12329,
    ],
    [
        12330,
        12333,
    ],
    [
        12334,
        12335,
    ],
    [
        12336,
        12336,
    ],
    [
        12337,
        12341,
    ],
    [
        12342,
        12343,
    ],
    [
        12344,
        12346,
    ],
    [
        12347,
        12347,
    ],
    [
        12348,
        12348,
    ],
    [
        12349,
        12349,
    ],
    [
        12350,
        12350,
    ],
    [
        12353,
        12438,
    ],
    [
        12441,
        12442,
    ],
    [
        12443,
        12444,
    ],
    [
        12445,
        12446,
    ],
    [
        12447,
        12447,
    ],
    [
        12448,
        12448,
    ],
    [
        12449,
        12538,
    ],
    [
        12539,
        12539,
    ],
    [
        12540,
        12542,
    ],
    [
        12543,
        12543,
    ],
    [
        12549,
        12591,
    ],
    [
        12593,
        12686,
    ],
    [
        12688,
        12689,
    ],
    [
        12690,
        12693,
    ],
    [
        12694,
        12703,
    ],
    [
        12704,
        12735,
    ],
    [
        12736,
        12773,
    ],
    [
        12783,
        12783,
    ],
    [
        12784,
        12799,
    ],
    [
        12800,
        12830,
    ],
    [
        12832,
        12841,
    ],
    [
        12842,
        12871,
    ],
    [
        12880,
        12880,
    ],
    [
        12881,
        12895,
    ],
    [
        12896,
        12927,
    ],
    [
        12928,
        12937,
    ],
    [
        12938,
        12976,
    ],
    [
        12977,
        12991,
    ],
    [
        12992,
        13055,
    ],
    [
        13056,
        13311,
    ],
    [
        13312,
        19903,
    ],
    [
        19904,
        19967,
    ],
    [
        19968,
        40959,
    ],
    [
        40960,
        40980,
    ],
    [
        40981,
        40981,
    ],
    [
        40982,
        42124,
    ],
    [
        42128,
        42182,
    ],
    [
        43360,
        43388,
    ],
    [
        44032,
        55203,
    ],
    [
        63744,
        64109,
    ],
    [
        64110,
        64111,
    ],
    [
        64112,
        64217,
    ],
    [
        64218,
        64255,
    ],
    [
        65040,
        65046,
    ],
    [
        65047,
        65047,
    ],
    [
        65048,
        65048,
    ],
    [
        65049,
        65049,
    ],
    [
        65072,
        65072,
    ],
    [
        65073,
        65074,
    ],
    [
        65075,
        65076,
    ],
    [
        65077,
        65077,
    ],
    [
        65078,
        65078,
    ],
    [
        65079,
        65079,
    ],
    [
        65080,
        65080,
    ],
    [
        65081,
        65081,
    ],
    [
        65082,
        65082,
    ],
    [
        65083,
        65083,
    ],
    [
        65084,
        65084,
    ],
    [
        65085,
        65085,
    ],
    [
        65086,
        65086,
    ],
    [
        65087,
        65087,
    ],
    [
        65088,
        65088,
    ],
    [
        65089,
        65089,
    ],
    [
        65090,
        65090,
    ],
    [
        65091,
        65091,
    ],
    [
        65092,
        65092,
    ],
    [
        65093,
        65094,
    ],
    [
        65095,
        65095,
    ],
    [
        65096,
        65096,
    ],
    [
        65097,
        65100,
    ],
    [
        65101,
        65103,
    ],
    [
        65104,
        65106,
    ],
    [
        65108,
        65111,
    ],
    [
        65112,
        65112,
    ],
    [
        65113,
        65113,
    ],
    [
        65114,
        65114,
    ],
    [
        65115,
        65115,
    ],
    [
        65116,
        65116,
    ],
    [
        65117,
        65117,
    ],
    [
        65118,
        65118,
    ],
    [
        65119,
        65121,
    ],
    [
        65122,
        65122,
    ],
    [
        65123,
        65123,
    ],
    [
        65124,
        65126,
    ],
    [
        65128,
        65128,
    ],
    [
        65129,
        65129,
    ],
    [
        65130,
        65131,
    ],
    [
        65281,
        65283,
    ],
    [
        65284,
        65284,
    ],
    [
        65285,
        65287,
    ],
    [
        65288,
        65288,
    ],
    [
        65289,
        65289,
    ],
    [
        65290,
        65290,
    ],
    [
        65291,
        65291,
    ],
    [
        65292,
        65292,
    ],
    [
        65293,
        65293,
    ],
    [
        65294,
        65295,
    ],
    [
        65296,
        65305,
    ],
    [
        65306,
        65307,
    ],
    [
        65308,
        65310,
    ],
    [
        65311,
        65312,
    ],
    [
        65313,
        65338,
    ],
    [
        65339,
        65339,
    ],
    [
        65340,
        65340,
    ],
    [
        65341,
        65341,
    ],
    [
        65342,
        65342,
    ],
    [
        65343,
        65343,
    ],
    [
        65344,
        65344,
    ],
    [
        65345,
        65370,
    ],
    [
        65371,
        65371,
    ],
    [
        65372,
        65372,
    ],
    [
        65373,
        65373,
    ],
    [
        65374,
        65374,
    ],
    [
        65375,
        65375,
    ],
    [
        65376,
        65376,
    ],
    [
        65504,
        65505,
    ],
    [
        65506,
        65506,
    ],
    [
        65507,
        65507,
    ],
    [
        65508,
        65508,
    ],
    [
        65509,
        65510,
    ],
    [
        94176,
        94177,
    ],
    [
        94178,
        94178,
    ],
    [
        94179,
        94179,
    ],
    [
        94180,
        94180,
    ],
    [
        94192,
        94193,
    ],
    [
        94208,
        100343,
    ],
    [
        100352,
        101119,
    ],
    [
        101120,
        101589,
    ],
    [
        101631,
        101631,
    ],
    [
        101632,
        101640,
    ],
    [
        110576,
        110579,
    ],
    [
        110581,
        110587,
    ],
    [
        110589,
        110590,
    ],
    [
        110592,
        110847,
    ],
    [
        110848,
        110882,
    ],
    [
        110898,
        110898,
    ],
    [
        110928,
        110930,
    ],
    [
        110933,
        110933,
    ],
    [
        110948,
        110951,
    ],
    [
        110960,
        111355,
    ],
    [
        119552,
        119638,
    ],
    [
        119648,
        119670,
    ],
    [
        126980,
        126980,
    ],
    [
        127183,
        127183,
    ],
    [
        127374,
        127374,
    ],
    [
        127377,
        127386,
    ],
    [
        127488,
        127490,
    ],
    [
        127504,
        127547,
    ],
    [
        127552,
        127560,
    ],
    [
        127568,
        127569,
    ],
    [
        127584,
        127589,
    ],
    [
        127744,
        127776,
    ],
    [
        127789,
        127797,
    ],
    [
        127799,
        127868,
    ],
    [
        127870,
        127891,
    ],
    [
        127904,
        127946,
    ],
    [
        127951,
        127955,
    ],
    [
        127968,
        127984,
    ],
    [
        127988,
        127988,
    ],
    [
        127992,
        127994,
    ],
    [
        127995,
        127999,
    ],
    [
        128000,
        128062,
    ],
    [
        128064,
        128064,
    ],
    [
        128066,
        128252,
    ],
    [
        128255,
        128317,
    ],
    [
        128331,
        128334,
    ],
    [
        128336,
        128359,
    ],
    [
        128378,
        128378,
    ],
    [
        128405,
        128406,
    ],
    [
        128420,
        128420,
    ],
    [
        128507,
        128511,
    ],
    [
        128512,
        128591,
    ],
    [
        128640,
        128709,
    ],
    [
        128716,
        128716,
    ],
    [
        128720,
        128722,
    ],
    [
        128725,
        128727,
    ],
    [
        128732,
        128735,
    ],
    [
        128747,
        128748,
    ],
    [
        128756,
        128764,
    ],
    [
        128992,
        129003,
    ],
    [
        129008,
        129008,
    ],
    [
        129292,
        129338,
    ],
    [
        129340,
        129349,
    ],
    [
        129351,
        129535,
    ],
    [
        129648,
        129660,
    ],
    [
        129664,
        129673,
    ],
    [
        129679,
        129734,
    ],
    [
        129742,
        129756,
    ],
    [
        129759,
        129769,
    ],
    [
        129776,
        129784,
    ],
    [
        131072,
        173791,
    ],
    [
        173792,
        173823,
    ],
    [
        173824,
        177977,
    ],
    [
        177978,
        177983,
    ],
    [
        177984,
        178205,
    ],
    [
        178206,
        178207,
    ],
    [
        178208,
        183969,
    ],
    [
        183970,
        183983,
    ],
    [
        183984,
        191456,
    ],
    [
        191457,
        191471,
    ],
    [
        191472,
        192093,
    ],
    [
        192094,
        194559,
    ],
    [
        194560,
        195101,
    ],
    [
        195102,
        195103,
    ],
    [
        195104,
        196605,
    ],
    [
        196608,
        201546,
    ],
    [
        201547,
        201551,
    ],
    [
        201552,
        205743,
    ],
    [
        205744,
        262141,
    ],
];
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

enum TruncateMode
{
    /**
     * Will cut exactly at given length.
     *
     * Length: 14
     * Source: Lorem ipsum dolor sit amet
     * Output: Lorem ipsum do
     */
    case Char;

    /**
     * Returns the string up to the last complete word containing the specified length.
     *
     * Length: 14
     * Source: Lorem ipsum dolor sit amet
     * Output: Lorem ipsum
     */
    case WordBefore;

    /**
     * Returns the string up to the complete word after or at the given length.
     *
     * Length: 14
     * Source: Lorem ipsum dolor sit amet
     * Output: Lorem ipsum dolor
     */
    case WordAfter;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Exception;

interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
Copyright (c) 2019-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

use Symfony\Component\String\Exception\ExceptionInterface;
use Symfony\Component\String\Exception\InvalidArgumentException;

/**
 * Represents a string of Unicode grapheme clusters encoded as UTF-8.
 *
 * A letter followed by combining characters (accents typically) form what Unicode defines
 * as a grapheme cluster: a character as humans mean it in written texts. This class knows
 * about the concept and won't split a letter apart from its combining accents. It also
 * ensures all string comparisons happen on their canonically-composed representation,
 * ignoring e.g. the order in which accents are listed when a letter has many of them.
 *
 * @see https://unicode.org/reports/tr15/
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class UnicodeString extends AbstractUnicodeString
{
    public function __construct(string $string = '')
    {
        if ('' === $string || normalizer_is_normalized($this->string = $string)) {
            return;
        }

        if (false === $string = normalizer_normalize($string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $this->string = $string;
    }

    public function append(string ...$suffix): static
    {
        $str = clone $this;
        $str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix));

        if (normalizer_is_normalized($str->string)) {
            return $str;
        }

        if (false === $string = normalizer_normalize($str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $str->string = $string;

        return $str;
    }

    public function chunk(int $length = 1): array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }

        if ('' === $this->string) {
            return [];
        }

        $rx = '/(';
        while (65535 < $length) {
            $rx .= '\X{65535}';
            $length -= 65535;
        }
        $rx .= '\X{'.$length.'})/u';

        $str = clone $this;
        $chunks = [];

        foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }

        return $chunks;
    }

    public function endsWith(string|iterable|AbstractString $suffix): bool
    {
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }

        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form);

        if ('' === $suffix || false === $suffix) {
            return false;
        }

        if (false === $grapheme = grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix))) {
            $grapheme = '';
        }

        if ($this->ignoreCase) {
            return 0 === mb_stripos($grapheme, $suffix, 0, 'UTF-8');
        }

        return $suffix === $grapheme;
    }

    public function equalsTo(string|iterable|AbstractString $string): bool
    {
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }

        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form);

        if ('' !== $string && false !== $string && $this->ignoreCase) {
            return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
        }

        return $string === $this->string;
    }

    public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }

        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);

        if ('' === $needle || false === $needle) {
            return null;
        }

        try {
            $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset);
        } catch (\ValueError) {
            return null;
        }

        return false === $i ? null : $i;
    }

    public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }

        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form);

        if ('' === $needle || false === $needle) {
            return null;
        }

        $string = $this->string;

        if (0 > $offset) {
            // workaround https://bugs.php.net/74264
            if (0 > $offset += grapheme_strlen($needle)) {
                $string = grapheme_substr($string, 0, $offset);
            }
            $offset = 0;
        }

        $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset);

        return false === $i ? null : $i;
    }

    public function join(array $strings, ?string $lastGlue = null): static
    {
        $str = parent::join($strings, $lastGlue);
        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);

        return $str;
    }

    public function length(): int
    {
        return grapheme_strlen($this->string);
    }

    public function normalize(int $form = self::NFC): static
    {
        $str = clone $this;

        if (\in_array($form, [self::NFC, self::NFKC], true)) {
            normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form);
        } elseif (!\in_array($form, [self::NFD, self::NFKD], true)) {
            throw new InvalidArgumentException('Unsupported normalization form.');
        } elseif (!normalizer_is_normalized($str->string, $form)) {
            $str->string = normalizer_normalize($str->string, $form);
            $str->ignoreCase = null;
        }

        return $str;
    }

    public function prepend(string ...$prefix): static
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string;

        if (normalizer_is_normalized($str->string)) {
            return $str;
        }

        if (false === $string = normalizer_normalize($str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $str->string = $string;

        return $str;
    }

    public function replace(string $from, string $to): static
    {
        $str = clone $this;
        normalizer_is_normalized($from) ?: $from = normalizer_normalize($from);

        if ('' !== $from && false !== $from) {
            $tail = $str->string;
            $result = '';
            $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';

            while ('' !== $tail && false !== $i = $indexOf($tail, $from)) {
                $slice = grapheme_substr($tail, 0, $i);
                $result .= $slice.$to;
                $tail = substr($tail, \strlen($slice) + \strlen($from));
            }

            $str->string = $result.$tail;

            if (normalizer_is_normalized($str->string)) {
                return $str;
            }

            if (false === $string = normalizer_normalize($str->string)) {
                throw new InvalidArgumentException('Invalid UTF-8 string.');
            }

            $str->string = $string;
        }

        return $str;
    }

    public function replaceMatches(string $fromRegexp, string|callable $to): static
    {
        $str = parent::replaceMatches($fromRegexp, $to);
        normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string);

        return $str;
    }

    public function slice(int $start = 0, ?int $length = null): static
    {
        $str = clone $this;

        $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647);

        return $str;
    }

    public function splice(string $replacement, int $start = 0, ?int $length = null): static
    {
        $str = clone $this;

        $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0;
        $length = $length ? \strlen(grapheme_substr($this->string, $start, $length)) : $length;
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647);

        if (normalizer_is_normalized($str->string)) {
            return $str;
        }

        if (false === $string = normalizer_normalize($str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $str->string = $string;

        return $str;
    }

    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (1 > $limit ??= 2147483647) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }

        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }

        if (null !== $flags) {
            return parent::split($delimiter.'u', $limit, $flags);
        }

        normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter);

        if (false === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
        }

        $str = clone $this;
        $tail = $this->string;
        $chunks = [];
        $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';

        while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) {
            $str->string = grapheme_substr($tail, 0, $i);
            $chunks[] = clone $str;
            $tail = substr($tail, \strlen($str->string) + \strlen($delimiter));
            --$limit;
        }

        $str->string = $tail;
        $chunks[] = clone $str;

        return $chunks;
    }

    public function startsWith(string|iterable|AbstractString $prefix): bool
    {
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }

        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form);

        if ('' === $prefix || false === $prefix) {
            return false;
        }

        if (false === $grapheme = grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES)) {
            $grapheme = '';
        }

        if ($this->ignoreCase) {
            return 0 === mb_stripos($grapheme, $prefix, 0, 'UTF-8');
        }

        return $prefix === $grapheme;
    }

    public function trimPrefix($prefix): static
    {
        if (\is_array($prefix) || $prefix instanceof \Traversable) {
            return parent::trimPrefix($prefix);
        }

        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } else {
            $prefix = (string) $prefix;
        }

        if (!normalizer_is_normalized($prefix, \Normalizer::NFC)) {
            $prefix = normalizer_normalize($prefix, \Normalizer::NFC);
        }

        return parent::trimPrefix($prefix);
    }

    public function trimSuffix($suffix): static
    {
        if (\is_array($suffix) || $suffix instanceof \Traversable) {
            return parent::trimSuffix($suffix);
        }

        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } else {
            $suffix = (string) $suffix;
        }

        if (!normalizer_is_normalized($suffix, \Normalizer::NFC)) {
            $suffix = normalizer_normalize($suffix, \Normalizer::NFC);
        }

        return parent::trimSuffix($suffix);
    }

    public function __unserialize(array $data): void
    {
        if ($wakeup = self::class !== (new \ReflectionMethod($this, '__wakeup'))->class && self::class === (new \ReflectionMethod($this, '__unserialize'))->class) {
            trigger_deprecation('symfony/string', '7.4', 'Implementing "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));
        }

        try {
            if (\in_array(array_keys($data), [['string'], ["\0*\0string"]], true)) {
                $this->string = $data['string'] ?? $data["\0*\0string"];

                if ($wakeup) {
                    $this->__wakeup();
                }

                return;
            }

            trigger_deprecation('symfony/string', '7.4', 'Passing more than just key "string" to "%s::__unserialize()" is deprecated, populate properties in "%s::__unserialize()" instead.', self::class, get_debug_type($this));

            \Closure::bind(function ($data) use ($wakeup) {
                foreach ($data as $key => $value) {
                    $this->{("\0" === $key[0] ?? '') ? substr($key, 1 + strrpos($key, "\0")) : $key} = $value;
                }

                if ($wakeup) {
                    $this->__wakeup();
                }
            }, $this, static::class)($data);
        } finally {
            if (!$wakeup) {
                if (!\is_string($this->string)) {
                    throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
                }

                normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
            }
        }
    }

    /**
     * @deprecated since Symfony 7.4, will be replaced by `__unserialize()` in 8.0
     */
    public function __wakeup(): void
    {
        trigger_deprecation('symfony/string', '7.4', 'Calling "%s::__wakeup()" is deprecated, use "__unserialize()" instead.', get_debug_type($this));

        if (!\is_string($this->string)) {
            throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
        }

        normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
    }

    public function __clone()
    {
        if (null === $this->ignoreCase) {
            normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string);
        }

        $this->ignoreCase = false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

use Symfony\Component\String\Exception\ExceptionInterface;
use Symfony\Component\String\Exception\InvalidArgumentException;

/**
 * Represents a string of Unicode code points encoded as UTF-8.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class CodePointString extends AbstractUnicodeString
{
    public function __construct(string $string = '')
    {
        if ('' !== $string && !preg_match('//u', $string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $this->string = $string;
    }

    public function append(string ...$suffix): static
    {
        $str = clone $this;
        $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix);

        if (!preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        return $str;
    }

    public function chunk(int $length = 1): array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }

        if ('' === $this->string) {
            return [];
        }

        $rx = '/(';
        while (65535 < $length) {
            $rx .= '.{65535}';
            $length -= 65535;
        }
        $rx .= '.{'.$length.'})/us';

        $str = clone $this;
        $chunks = [];

        foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }

        return $chunks;
    }

    public function codePointsAt(int $offset): array
    {
        $str = $offset ? $this->slice($offset, 1) : $this;

        return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')];
    }

    public function endsWith(string|iterable|AbstractString $suffix): bool
    {
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }

        if ('' === $suffix || !preg_match('//u', $suffix)) {
            return false;
        }

        if ($this->ignoreCase) {
            return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string);
        }

        return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix));
    }

    public function equalsTo(string|iterable|AbstractString $string): bool
    {
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }

        if ('' !== $string && $this->ignoreCase) {
            return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8');
        }

        return $string === $this->string;
    }

    public function indexOf(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }

        if ('' === $needle) {
            return null;
        }

        $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8');

        return false === $i ? null : $i;
    }

    public function indexOfLast(string|iterable|AbstractString $needle, int $offset = 0): ?int
    {
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }

        if ('' === $needle) {
            return null;
        }

        $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8');

        return false === $i ? null : $i;
    }

    public function length(): int
    {
        return mb_strlen($this->string, 'UTF-8');
    }

    public function prepend(string ...$prefix): static
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string;

        if (!preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        return $str;
    }

    public function replace(string $from, string $to): static
    {
        $str = clone $this;

        if ('' === $from || !preg_match('//u', $from)) {
            return $str;
        }

        if ('' !== $to && !preg_match('//u', $to)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        if ($this->ignoreCase) {
            $str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string));
        } else {
            $str->string = str_replace($from, $to, $this->string);
        }

        return $str;
    }

    public function slice(int $start = 0, ?int $length = null): static
    {
        $str = clone $this;
        $str->string = mb_substr($this->string, $start, $length, 'UTF-8');

        return $str;
    }

    public function splice(string $replacement, int $start = 0, ?int $length = null): static
    {
        if (!preg_match('//u', $replacement)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $str = clone $this;
        $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0;
        $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length;
        $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);

        return $str;
    }

    public function split(string $delimiter, ?int $limit = null, ?int $flags = null): array
    {
        if (1 > $limit ??= \PHP_INT_MAX) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }

        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }

        if (null !== $flags) {
            return parent::split($delimiter.'u', $limit, $flags);
        }

        if (!preg_match('//u', $delimiter)) {
            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
        }

        $str = clone $this;
        $chunks = $this->ignoreCase
            ? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit)
            : explode($delimiter, $this->string, $limit);

        foreach ($chunks as &$chunk) {
            $str->string = $chunk;
            $chunk = clone $str;
        }

        return $chunks;
    }

    public function startsWith(string|iterable|AbstractString $prefix): bool
    {
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }

        if ('' === $prefix || !preg_match('//u', $prefix)) {
            return false;
        }

        if ($this->ignoreCase) {
            return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8');
        }

        return 0 === strncmp($this->string, $prefix, \strlen($prefix));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Inflector;

interface InflectorInterface
{
    /**
     * Returns the singular forms of a string.
     *
     * If the method can't determine the form with certainty, several possible singulars are returned.
     *
     * @return string[]
     */
    public function singularize(string $plural): array;

    /**
     * Returns the plural forms of a string.
     *
     * If the method can't determine the form with certainty, several possible plurals are returned.
     *
     * @return string[]
     */
    public function pluralize(string $singular): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Inflector;

final class SpanishInflector implements InflectorInterface
{
    /**
     * A list of all rules for pluralise.
     *
     * @see https://www.spanishdict.com/guide/spanish-plural-noun-forms
     * @see https://www.rae.es/gram%C3%A1tica/morfolog%C3%ADa/la-formaci%C3%B3n-del-plural-plurales-en-s-y-plurales-en-es-reglas-generales
     */
    // First entry: regex
    // Second entry: replacement
    private const PLURALIZE_REGEXP = [
        // Specials sí, no
        ['/(sí|no)$/i', '\1es'],

        // Words ending with vowel must use -s (RAE 3.2a, 3.2c)
        ['/(a|e|i|o|u|á|é|í|ó|ú)$/i', '\1s'],

        // Word ending in s or x and the previous letter is accented (RAE 3.2n)
        ['/ás$/i', 'ases'],
        ['/és$/i', 'eses'],
        ['/ís$/i', 'ises'],
        ['/ós$/i', 'oses'],
        ['/ús$/i', 'uses'],

        // Words ending in -ión must changed to -iones
        ['/ión$/i', '\1iones'],

        // Words ending in some consonants must use -es (RAE 3.2k)
        ['/(l|r|n|d|j|s|x|ch|y)$/i', '\1es'],

        // Word ending in z, must changed to ces
        ['/(z)$/i', 'ces'],
    ];

    /**
     * A list of all rules for singularize.
     */
    private const SINGULARIZE_REGEXP = [
        // Specials sí, no
        ['/(sí|no)es$/i', '\1'],

        // Words ending in -ión must changed to -iones
        ['/iones$/i', '\1ión'],

        // Word ending in z, must changed to ces
        ['/ces$/i', 'z'],

        // Word ending in s or x and the previous letter is accented (RAE 3.2n)
        ['/(\w)ases$/i', '\1ás'],
        ['/eses$/i', 'és'],
        ['/ises$/i', 'ís'],
        ['/(\w{2,})oses$/i', '\1ós'],
        ['/(\w)uses$/i', '\1ús'],

        // Words ending in some consonants and -es, must be the consonants
        ['/(l|r|n|d|j|s|x|ch|y)e?s$/i', '\1'],

        // Words ended with vowel and s, must be vowel
        ['/(a|e|i|o|u|á|é|ó|í|ú)s$/i', '\1'],
    ];

    private const UNINFLECTED_RULES = [
        // Words ending with pies (RAE 3.2n)
        '/.*(piés)$/i',
    ];

    private const UNINFLECTED = '/^(lunes|martes|miércoles|jueves|viernes|análisis|torax|yo|pies)$/i';

    public function singularize(string $plural): array
    {
        if ($this->isInflectedWord($plural)) {
            return [$plural];
        }

        foreach (self::SINGULARIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;

            if (1 === preg_match($regexp, $plural)) {
                return [preg_replace($regexp, $replace, $plural)];
            }
        }

        return [$plural];
    }

    public function pluralize(string $singular): array
    {
        if ($this->isInflectedWord($singular)) {
            return [$singular];
        }

        foreach (self::PLURALIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;

            if (1 === preg_match($regexp, $singular)) {
                return [preg_replace($regexp, $replace, $singular)];
            }
        }

        return [$singular.'s'];
    }

    private function isInflectedWord(string $word): bool
    {
        foreach (self::UNINFLECTED_RULES as $rule) {
            if (1 === preg_match($rule, $word)) {
                return true;
            }
        }

        return 1 === preg_match(self::UNINFLECTED, $word);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Inflector;

/**
 * French inflector.
 *
 * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix".
 */
final class FrenchInflector implements InflectorInterface
{
    /**
     * A list of all rules for pluralise.
     *
     * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php
     */
    private const PLURALIZE_REGEXP = [
        // First entry: regexp
        // Second entry: replacement

        // Words finishing with "s", "x" or "z" are invariables
        // Les mots finissant par "s", "x" ou "z" sont invariables
        ['/(s|x|z)$/i', '\1'],

        // Words finishing with "eau" are pluralized with a "x"
        // Les mots finissant par "eau" prennent tous un "x" au pluriel
        ['/(eau)$/i', '\1x'],

        // Words finishing with "au" are pluralized with a "x" excepted "landau"
        // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
        ['/^(landau)$/i', '\1s'],
        ['/(au)$/i', '\1x'],

        // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu"
        // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu"
        ['/^(pneu|bleu|émeu)$/i', '\1s'],
        ['/(eu)$/i', '\1x'],

        // Words finishing with "al" are pluralized with a "aux" excepted
        // Les mots finissant en "al" se terminent en "aux" sauf
        ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'],
        ['/al$/i', '\1aux'],

        // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
        ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'],

        // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel
        ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'],

        // Invariable words
        ['/^(cinquante|soixante|mille)$/i', '\1'],

        // French titles
        ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'],
        ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'],
    ];

    /**
     * A list of all rules for singularize.
     */
    private const SINGULARIZE_REGEXP = [
        // First entry: regexp
        // Second entry: replacement

        // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
        ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'],

        // Words finishing with "eau" are pluralized with a "x"
        // Les mots finissant par "eau" prennent tous un "x" au pluriel
        ['/(eau)x$/i', '\1'],

        // Words finishing with "al" are pluralized with a "aux" expected
        // Les mots finissant en "al" se terminent en "aux" sauf
        ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'],

        // Words finishing with "au" are pluralized with a "x" excepted "landau"
        // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
        ['/(au)x$/i', '\1'],

        // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu"
        // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu"
        ['/(eu)x$/i', '\1'],

        //  Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou
        // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou
        ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'],

        // French titles
        ['/^mes(dame|demoiselle)s$/', 'ma\1'],
        ['/^Mes(dame|demoiselle)s$/', 'Ma\1'],
        ['/^mes(sieur|seigneur)s$/', 'mon\1'],
        ['/^Mes(sieur|seigneur)s$/', 'Mon\1'],

        // Default rule
        ['/s$/i', ''],
    ];

    /**
     * A list of words which should not be inflected.
     * This list is only used by singularize.
     */
    private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sans|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i';

    public function singularize(string $plural): array
    {
        if ($this->isInflectedWord($plural)) {
            return [$plural];
        }

        foreach (self::SINGULARIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;

            if (1 === preg_match($regexp, $plural)) {
                return [preg_replace($regexp, $replace, $plural)];
            }
        }

        return [$plural];
    }

    public function pluralize(string $singular): array
    {
        if ($this->isInflectedWord($singular)) {
            return [$singular];
        }

        foreach (self::PLURALIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;

            if (1 === preg_match($regexp, $singular)) {
                return [preg_replace($regexp, $replace, $singular)];
            }
        }

        return [$singular.'s'];
    }

    private function isInflectedWord(string $word): bool
    {
        return 1 === preg_match(self::UNINFLECTED, $word);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String\Inflector;

final class EnglishInflector implements InflectorInterface
{
    /**
     * Map English plural to singular suffixes.
     *
     * @see http://english-zone.com/spelling/plurals.html
     */
    private const PLURAL_MAP = [
        // First entry: plural suffix, reversed
        // Second entry: length of plural suffix
        // Third entry: Whether the suffix may succeed a vowel
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: singular suffix, normal

        // insignias (insigne), insignia (insigne)
        ['saingisni', 9, true, true, 'insigne'],
        ['aingisni', 8, true, true, 'insigne'],

        // passersby (passerby)
        ['ybsressap', 9, true, true, 'passerby'],

        // nodes (node)
        ['sedon', 5, true, true, 'node'],

        // bacteria (bacterium)
        ['airetcab', 8, true, true, 'bacterium'],

        // issues (issue)
        ['seussi', 6, true, true, 'issue'],

        // corpora (corpus)
        ['aroproc', 7, true, true, 'corpus'],

        // criteria (criterion)
        ['airetirc', 8, true, true, 'criterion'],

        // curricula (curriculum)
        ['alucirruc', 9, true, true, 'curriculum'],

        // quora (quorum)
        ['arouq', 5, true, true, 'quorum'],

        // genera (genus)
        ['areneg', 6, true, true, 'genus'],

        // media (medium)
        ['aidem', 5, true, true, 'medium'],

        // memoranda (memorandum)
        ['adnaromem', 9, true, true, 'memorandum'],

        // phenomena (phenomenon)
        ['anemonehp', 9, true, true, 'phenomenon'],

        // strata (stratum)
        ['atarts', 6, true, true, 'stratum'],

        // nebulae (nebula)
        ['ea', 2, true, true, 'a'],

        // services (service)
        ['secivres', 8, true, true, 'service'],

        // mice (mouse), lice (louse)
        ['eci', 3, false, true, 'ouse'],

        // geese (goose)
        ['esee', 4, false, true, 'oose'],

        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        ['i', 1, true, true, 'us'],

        // men (man), women (woman)
        ['nem', 3, true, true, 'man'],

        // children (child)
        ['nerdlihc', 8, true, true, 'child'],

        // oxen (ox)
        ['nexo', 4, false, false, 'ox'],

        // indices (index), appendices (appendix), prices (price)
        ['seci', 4, false, true, ['ex', 'ix', 'ice']],

        // codes (code)
        ['sedoc', 5, false, true, 'code'],

        // selfies (selfie)
        ['seifles', 7, true, true, 'selfie'],

        // zombies (zombie)
        ['seibmoz', 7, true, true, 'zombie'],

        // movies (movie)
        ['seivom', 6, true, true, 'movie'],

        // names (name)
        ['seman', 5, true, false, 'name'],

        // conspectuses (conspectus), prospectuses (prospectus)
        ['sesutcep', 8, true, true, 'pectus'],

        // feet (foot)
        ['teef', 4, true, true, 'foot'],

        // geese (goose)
        ['eseeg', 5, true, true, 'goose'],

        // teeth (tooth)
        ['hteet', 5, true, true, 'tooth'],

        // news (news)
        ['swen', 4, true, true, 'news'],

        // series (series)
        ['seires', 6, true, true, 'series'],

        // babies (baby)
        ['sei', 3, false, true, 'y'],

        // accesses (access), addresses (address), kisses (kiss)
        ['sess', 4, true, false, 'ss'],

        // statuses (status)
        ['sesutats', 8, true, true, 'status'],

        // article (articles), ancle (ancles)
        ['sel', 3, true, true, 'le'],

        // analyses (analysis), ellipses (ellipsis), fungi (fungus),
        // neuroses (neurosis), theses (thesis), emphases (emphasis),
        // oases (oasis), crises (crisis), houses (house), bases (base),
        // atlases (atlas)
        ['ses', 3, true, true, ['s', 'se', 'sis']],

        // objectives (objective), alternative (alternatives)
        ['sevit', 5, true, true, 'tive'],

        // drives (drive)
        ['sevird', 6, false, true, 'drive'],

        // lives (life), wives (wife)
        ['sevi', 4, false, true, 'ife'],

        // moves (move)
        ['sevom', 5, true, true, 'move'],

        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff)
        ['sev', 3, true, true, ['f', 've', 'ff']],

        // axes (axis), axes (ax), axes (axe)
        ['sexa', 4, false, false, ['ax', 'axe', 'axis']],

        // indexes (index), matrixes (matrix)
        ['sex', 3, true, false, 'x'],

        // quizzes (quiz)
        ['sezz', 4, true, false, 'z'],

        // bureaus (bureau)
        ['suae', 4, false, true, 'eau'],

        // fees (fee), trees (tree), employees (employee)
        ['see', 3, true, true, 'ee'],

        // edges (edge)
        ['segd', 4, true, true, 'dge'],

        // outages (outage) - specific fix to avoid 'outag'
        ['segatuo', 7, true, true, 'outage'],

        // traces (trace), faces (face), places (place), pieces (piece)
        ['sec', 3, true, true, 'ce'],

        // roses (rose), garages (garage), cassettes (cassette),
        // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
        // shoes (shoe)
        ['se', 2, true, true, ['', 'e']],

        // status (status)
        ['sutats', 6, true, true, 'status'],

        // tags (tag)
        ['s', 1, true, true, ''],

        // chateaux (chateau)
        ['xuae', 4, false, true, 'eau'],

        // people (person)
        ['elpoep', 6, true, true, 'person'],
    ];

    /**
     * Map English singular to plural suffixes.
     *
     * @see http://english-zone.com/spelling/plurals.html
     */
    private const SINGULAR_MAP = [
        // First entry: singular suffix, reversed
        // Second entry: length of singular suffix
        // Third entry: Whether the suffix may succeed a vowel
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: plural suffix, normal

        // passerby (passersby)
        ['ybressap', 8, true, true, 'passersby'],

        // insigne (insignia, insignias)
        ['engisni', 7, true, true, ['insignia', 'insignias']],

        // nodes (node)
        ['edon', 4, true, true, 'nodes'],

        // axes (axis)
        ['sixa', 4, false, false, 'axes'],

        // criterion (criteria)
        ['airetirc', 8, false, false, 'criterion'],

        // nebulae (nebula)
        ['aluben', 6, false, false, 'nebulae'],

        // children (child)
        ['dlihc', 5, true, true, 'children'],

        // prices (price)
        ['eci', 3, false, true, 'ices'],

        // services (service)
        ['ecivres', 7, true, true, 'services'],

        // lives (life), wives (wife)
        ['efi', 3, false, true, 'ives'],

        // selfies (selfie)
        ['eifles', 6, true, true, 'selfies'],

        // movies (movie)
        ['eivom', 5, true, true, 'movies'],

        // lice (louse)
        ['esuol', 5, false, true, 'lice'],

        // mice (mouse)
        ['esuom', 5, false, true, 'mice'],

        // geese (goose)
        ['esoo', 4, false, true, 'eese'],

        // houses (house), bases (base)
        ['es', 2, true, true, 'ses'],

        // geese (goose)
        ['esoog', 5, true, true, 'geese'],

        // caves (cave)
        ['ev', 2, true, true, 'ves'],

        // drives (drive)
        ['evird', 5, false, true, 'drives'],

        // objectives (objective), alternative (alternatives)
        ['evit', 4, true, true, 'tives'],

        // moves (move)
        ['evom', 4, true, true, 'moves'],

        // staves (staff)
        ['ffats', 5, true, true, 'staves'],

        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        ['ff', 2, true, true, 'ffs'],

        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        ['f', 1, true, true, ['fs', 'ves']],

        // arches (arch)
        ['hc', 2, true, true, 'ches'],

        // bushes (bush)
        ['hs', 2, true, true, 'shes'],

        // teeth (tooth)
        ['htoot', 5, true, true, 'teeth'],

        // albums (album)
        ['mubla', 5, true, true, 'albums'],

        // quorums (quorum)
        ['murouq', 6, true, true, ['quora', 'quorums']],

        // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum)
        ['mu', 2, true, true, 'a'],

        // men (man), women (woman)
        ['nam', 3, true, true, 'men'],

        // people (person)
        ['nosrep', 6, true, true, ['persons', 'people']],

        // criteria (criterion)
        ['noiretirc', 9, true, true, 'criteria'],

        // phenomena (phenomenon)
        ['nonemonehp', 10, true, true, 'phenomena'],

        // echoes (echo)
        ['ohce', 4, true, true, 'echoes'],

        // heroes (hero)
        ['oreh', 4, true, true, 'heroes'],

        // atlases (atlas)
        ['salta', 5, true, true, 'atlases'],

        // aliases (alias)
        ['saila', 5, true, true, 'aliases'],

        // irises (iris)
        ['siri', 4, true, true, 'irises'],

        // analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
        // theses (thesis), emphases (emphasis), oases (oasis),
        // crises (crisis)
        ['sis', 3, true, true, 'ses'],

        // accesses (access), addresses (address), kisses (kiss)
        ['ss', 2, true, false, 'sses'],

        // syllabi (syllabus)
        ['suballys', 8, true, true, 'syllabi'],

        // buses (bus)
        ['sub', 3, true, true, 'buses'],

        // circuses (circus)
        ['suc', 3, true, true, 'cuses'],

        // hippocampi (hippocampus)
        ['supmacoppih', 11, false, false, 'hippocampi'],

        // campuses (campus)
        ['sup', 3, true, true, 'puses'],

        // status (status)
        ['sutats', 6, true, true, ['status', 'statuses']],

        // conspectuses (conspectus), prospectuses (prospectus)
        ['sutcep', 6, true, true, 'pectuses'],

        // nexuses (nexus)
        ['suxen', 5, false, false, 'nexuses'],

        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        ['su', 2, true, true, 'i'],

        // news (news)
        ['swen', 4, true, true, 'news'],

        // feet (foot)
        ['toof', 4, true, true, 'feet'],

        // chateaux (chateau), bureaus (bureau)
        ['uae', 3, false, true, ['eaus', 'eaux']],

        // oxen (ox)
        ['xo', 2, false, false, 'oxen'],

        // hoaxes (hoax)
        ['xaoh', 4, true, false, 'hoaxes'],

        // indices (index)
        ['xedni', 5, false, true, ['indicies', 'indexes']],

        // fax (faxes, faxxes)
        ['xaf', 3, true, true, ['faxes', 'faxxes']],

        // boxes (box)
        ['xo', 2, false, true, 'oxes'],

        // indexes (index), matrixes (matrix), appendices (appendix)
        ['x', 1, true, false, ['ces', 'xes']],

        // babies (baby)
        ['y', 1, false, true, 'ies'],

        // quizzes (quiz)
        ['ziuq', 4, true, false, 'quizzes'],

        // waltzes (waltz)
        ['z', 1, true, true, 'zes'],
    ];

    /**
     * A list of words which should not be inflected, reversed.
     */
    private const UNINFLECTED = [
        '',

        // data
        'atad',

        // deer
        'reed',

        // equipment
        'tnempiuqe',

        // feedback
        'kcabdeef',

        // fish
        'hsif',

        // health
        'htlaeh',

        // history
        'yrotsih',

        // info
        'ofni',

        // information
        'noitamrofni',

        // money
        'yenom',

        // moose
        'esoom',

        // series
        'seires',

        // sheep
        'peehs',

        // species
        'seiceps',

        // traffic
        'ciffart',

        // aircraft
        'tfarcria',

        // hardware
        'erawdrah',
    ];

    public function singularize(string $plural): array
    {
        $pluralRev = strrev($plural);
        $lowerPluralRev = strtolower($pluralRev);
        $pluralLength = \strlen($lowerPluralRev);

        // Check if the word is one which is not inflected, return early if so
        if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) {
            return [$plural];
        }

        // The outer loop iterates over the entries of the plural table
        // The inner loop $j iterates over the characters of the plural suffix
        // in the plural table to compare them with the characters of the actual
        // given plural suffix
        foreach (self::PLURAL_MAP as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;

            // Compare characters in the plural table and of the suffix of the
            // given plural one by one
            while ($suffix[$j] === $lowerPluralRev[$j]) {
                // Let $j point to the next character
                ++$j;

                // Successfully compared the last character
                // Add an entry with the singular suffix to the singular array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $pluralLength) {
                        $nextIsVowel = str_contains('aeiou', $lowerPluralRev[$j]);

                        if (!$map[2] && $nextIsVowel) {
                            // suffix may not succeed a vowel but next char is one
                            break;
                        }

                        if (!$map[3] && !$nextIsVowel) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }

                    $newBase = substr($plural, 0, $pluralLength - $suffixLength);
                    $newSuffix = $map[4];

                    // Check whether the first character in the plural suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = ctype_upper($pluralRev[$j - 1]);

                    if (\is_array($newSuffix)) {
                        $singulars = [];

                        foreach ($newSuffix as $newSuffixEntry) {
                            $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }

                        return $singulars;
                    }

                    return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)];
                }

                // Suffix is longer than word
                if ($j === $pluralLength) {
                    break;
                }
            }
        }

        // Assume that plural and singular is identical
        return [$plural];
    }

    public function pluralize(string $singular): array
    {
        $singularRev = strrev($singular);
        $lowerSingularRev = strtolower($singularRev);
        $singularLength = \strlen($lowerSingularRev);

        // Check if the word is one which is not inflected, return early if so
        if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) {
            return [$singular];
        }

        // The outer loop iterates over the entries of the singular table
        // The inner loop $j iterates over the characters of the singular suffix
        // in the singular table to compare them with the characters of the actual
        // given singular suffix
        foreach (self::SINGULAR_MAP as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;

            // Compare characters in the singular table and of the suffix of the
            // given plural one by one

            while ($suffix[$j] === $lowerSingularRev[$j]) {
                // Let $j point to the next character
                ++$j;

                // Successfully compared the last character
                // Add an entry with the plural suffix to the plural array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $singularLength) {
                        $nextIsVowel = str_contains('aeiou', $lowerSingularRev[$j]);

                        if (!$map[2] && $nextIsVowel) {
                            // suffix may not succeed a vowel but next char is one
                            break;
                        }

                        if (!$map[3] && !$nextIsVowel) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }

                    $newBase = substr($singular, 0, $singularLength - $suffixLength);
                    $newSuffix = $map[4];

                    // Check whether the first character in the singular suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = ctype_upper($singularRev[$j - 1]);

                    if (\is_array($newSuffix)) {
                        $plurals = [];

                        foreach ($newSuffix as $newSuffixEntry) {
                            $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }

                        return $plurals;
                    }

                    return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)];
                }

                // Suffix is longer than word
                if ($j === $singularLength) {
                    break;
                }
            }
        }

        // Assume that plural is singular with a trailing `s`
        return [$singular.'s'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

/**
 * A string whose value is computed lazily by a callback.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class LazyString implements \Stringable, \JsonSerializable
{
    private \Closure|string $value;

    /**
     * @param callable|array $callback A callable or a [Closure, method] lazy-callable
     */
    public static function fromCallable(callable|array $callback, mixed ...$arguments): static
    {
        if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) {
            throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '['.implode(', ', array_map('get_debug_type', $callback)).']'));
        }

        $lazyString = new static();
        $lazyString->value = static function () use (&$callback, &$arguments): string {
            static $value;

            if (null !== $arguments) {
                if (!\is_callable($callback)) {
                    $callback[0] = $callback[0]();
                    $callback[1] ??= '__invoke';
                }
                $value = $callback(...$arguments);
                $callback = !\is_scalar($value) && !$value instanceof \Stringable ? self::getPrettyName($callback) : 'callable';
                $arguments = null;
            }

            return $value ?? '';
        };

        return $lazyString;
    }

    public static function fromStringable(string|int|float|bool|\Stringable $value): static
    {
        if (\is_object($value)) {
            return static::fromCallable($value->__toString(...));
        }

        $lazyString = new static();
        $lazyString->value = (string) $value;

        return $lazyString;
    }

    /**
     * Tells whether the provided value can be cast to string.
     */
    final public static function isStringable(mixed $value): bool
    {
        return \is_string($value) || $value instanceof \Stringable || \is_scalar($value);
    }

    /**
     * Casts scalars and stringable objects to strings.
     *
     * @throws \TypeError When the provided value is not stringable
     */
    final public static function resolve(\Stringable|string|int|float|bool $value): string
    {
        return $value;
    }

    public function __toString(): string
    {
        if (\is_string($this->value)) {
            return $this->value;
        }

        try {
            return $this->value = ($this->value)();
        } catch (\Throwable $e) {
            if (\TypeError::class === $e::class && __FILE__ === $e->getFile()) {
                $type = explode(', ', $e->getMessage());
                $type = substr(array_pop($type), 0, -\strlen(' returned'));
                $r = new \ReflectionFunction($this->value);
                $callback = $r->getStaticVariables()['callback'];

                $e = new \TypeError(\sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
            }

            throw $e;
        }
    }

    public function __serialize(): array
    {
        if (self::class === (new \ReflectionMethod($this, '__sleep'))->class || self::class !== (new \ReflectionMethod($this, '__serialize'))->class) {
            $this->__toString();

            return ['value' => $this->value];
        }

        trigger_deprecation('symfony/string', '7.4', 'Implementing "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));

        $data = [];
        foreach ($this->__sleep() as $key) {
            try {
                if (($r = new \ReflectionProperty($this, $key))->isInitialized($this)) {
                    $data[$key] = $r->getValue($this);
                }
            } catch (\ReflectionException) {
                $data[$key] = $this->$key;
            }
        }

        return $data;
    }

    /**
     * @deprecated since Symfony 7.4, will be replaced by `__serialize()` in 8.0
     */
    public function __sleep(): array
    {
        trigger_deprecation('symfony/string', '7.4', 'Calling "%s::__sleep()" is deprecated, use "__serialize()" instead.', get_debug_type($this));

        $this->__toString();

        return ['value'];
    }

    public function jsonSerialize(): string
    {
        return $this->__toString();
    }

    private function __construct()
    {
    }

    private static function getPrettyName(callable $callback): string
    {
        if (\is_string($callback)) {
            return $callback;
        }

        if (\is_array($callback)) {
            $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0];
            $method = $callback[1];
        } elseif ($callback instanceof \Closure) {
            $r = new \ReflectionFunction($callback);

            if ($r->isAnonymous() || !$class = $r->getClosureCalledClass()) {
                return $r->name;
            }

            $class = $class->name;
            $method = $r->name;
        } else {
            $class = get_debug_type($callback);
            $method = '__invoke';
        }

        return $class.'::'.$method;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\String;

use Symfony\Component\String\Exception\ExceptionInterface;
use Symfony\Component\String\Exception\InvalidArgumentException;
use Symfony\Component\String\Exception\RuntimeException;

/**
 * Represents a string of abstract Unicode characters.
 *
 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
 * This class is the abstract type to use as a type-hint when the logic you want to
 * implement is Unicode-aware but doesn't care about code points vs grapheme clusters.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @throws ExceptionInterface
 */
abstract class AbstractUnicodeString extends AbstractString
{
    public const NFC = \Normalizer::NFC;
    public const NFD = \Normalizer::NFD;
    public const NFKC = \Normalizer::NFKC;
    public const NFKD = \Normalizer::NFKD;

    // all ASCII letters sorted by typical frequency of occurrence
    private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";

    // the subset of folded case mappings that is not in lower case mappings
    private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'ŉ', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ﬀ', 'ﬁ', 'ﬂ', 'ﬃ', 'ﬄ', 'ﬅ', 'ﬆ', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ'];
    private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ῖ', 'ῗ', 'ῢ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ'];

    // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD
    private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ŉ', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'Ǆ', 'ǅ', 'ǆ', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '｟', '｠', '｡', '､', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆'];
    private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))'];

    private static array $transliterators = [];
    private static array $tableZero;
    private static array $tableWide;

    public static function fromCodePoints(int ...$codes): static
    {
        $string = '';

        foreach ($codes as $code) {
            if (0x80 > $code %= 0x200000) {
                $string .= \chr($code);
            } elseif (0x800 > $code) {
                $string .= \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
            } elseif (0x10000 > $code) {
                $string .= \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
            } else {
                $string .= \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
            }
        }

        return new static($string);
    }

    /**
     * Generic UTF-8 to ASCII transliteration.
     *
     * Install the intl extension for best results.
     *
     * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs()
     */
    public function ascii(array $rules = []): self
    {
        $str = clone $this;
        $s = $str->string;
        $str->string = '';

        array_unshift($rules, 'nfd');
        $rules[] = 'latin-ascii';

        if (\function_exists('transliterator_transliterate')) {
            $rules[] = 'any-latin/bgn';
        }

        $rules[] = 'nfkd';
        $rules[] = '[:nonspacing mark:] remove';

        while (\strlen($s) - 1 > $i = strspn($s, self::ASCII)) {
            if (0 < --$i) {
                $str->string .= substr($s, 0, $i);
                $s = substr($s, $i);
            }

            if (!$rule = array_shift($rules)) {
                $rules = []; // An empty rule interrupts the next ones
            }

            if ($rule instanceof \Transliterator) {
                $s = $rule->transliterate($s);
            } elseif ($rule instanceof \Closure) {
                $s = $rule($s);
            } elseif ($rule) {
                if ('nfd' === $rule = strtolower($rule)) {
                    normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD);
                } elseif ('nfkd' === $rule) {
                    normalizer_is_normalized($s, self::NFKD) ?: $s = normalizer_normalize($s, self::NFKD);
                } elseif ('[:nonspacing mark:] remove' === $rule) {
                    $s = preg_replace('/\p{Mn}++/u', '', $s);
                } elseif ('latin-ascii' === $rule) {
                    $s = str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s);
                } elseif ('de-ascii' === $rule) {
                    $s = preg_replace("/([AUO])\u{0308}(?=\p{Ll})/u", '$1e', $s);
                    $s = str_replace(["a\u{0308}", "o\u{0308}", "u\u{0308}", "A\u{0308}", "O\u{0308}", "U\u{0308}"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s);
                } elseif (\function_exists('transliterator_transliterate')) {
                    if (null === $transliterator = self::$transliterators[$rule] ??= \Transliterator::create($rule)) {
                        if ('any-latin/bgn' === $rule) {
                            $rule = 'any-latin';
                            $transliterator = self::$transliterators[$rule] ??= \Transliterator::create($rule);
                        }

                        if (null === $transliterator) {
                            throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule));
                        }

                        self::$transliterators['any-latin/bgn'] = $transliterator;
                    }

                    $s = $transliterator->transliterate($s);
                }
            } elseif (!\function_exists('iconv')) {
                $s = preg_replace('/[^\x00-\x7F]/u', '?', $s);
            } else {
                $previousLocale = setlocale(\LC_CTYPE, 0);
                try {
                    setlocale(\LC_CTYPE, 'C');
                    $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) {
                        $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);

                        if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) {
                            throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
                        }

                        return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
                    }, $s);
                } finally {
                    setlocale(\LC_CTYPE, $previousLocale);
                }
            }
        }

        $str->string .= $s;

        return $str;
    }

    public function camel(): static
    {
        $str = clone $this;
        $str->string = str_replace(' ', '', preg_replace_callback('/\b.(?!\p{Lu})/u', static function ($m) {
            static $i = 0;

            return 1 === ++$i ? ('İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8')) : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
        }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string)));

        return $str;
    }

    /**
     * @return int[]
     */
    public function codePointsAt(int $offset): array
    {
        $str = $this->slice($offset, 1);

        if ('' === $str->string) {
            return [];
        }

        $codePoints = [];

        foreach (preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
            $codePoints[] = mb_ord($c, 'UTF-8');
        }

        return $codePoints;
    }

    public function folded(bool $compat = true): static
    {
        $str = clone $this;

        if (!$compat || !\defined('Normalizer::NFKC_CF')) {
            $str->string = normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC);
            $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $str->string), 'UTF-8');
        } else {
            $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF);
        }

        return $str;
    }

    public function join(array $strings, ?string $lastGlue = null): static
    {
        $str = clone $this;

        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : '';
        $str->string = implode($this->string, $strings).$tail;

        if (!preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        return $str;
    }

    public function lower(): static
    {
        $str = clone $this;
        $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8');

        return $str;
    }

    /**
     * @param string $locale In the format language_region (e.g. tr_TR)
     */
    public function localeLower(string $locale): static
    {
        if (null !== $transliterator = $this->getLocaleTransliterator($locale, 'Lower')) {
            $str = clone $this;
            $str->string = $transliterator->transliterate($str->string);

            return $str;
        }

        return $this->lower();
    }

    public function match(string $regexp, int $flags = 0, int $offset = 0): array
    {
        $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match';

        if ($this->ignoreCase) {
            $regexp .= 'i';
        }

        set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m));

        try {
            if (false === $match($regexp.'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
                throw new RuntimeException('Matching failed with error: '.preg_last_error_msg());
            }
        } finally {
            restore_error_handler();
        }

        return $matches;
    }

    public function normalize(int $form = self::NFC): static
    {
        if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD], true)) {
            throw new InvalidArgumentException('Unsupported normalization form.');
        }

        $str = clone $this;
        normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form);

        return $str;
    }

    public function padBoth(int $length, string $padStr = ' '): static
    {
        if ('' === $padStr || !preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $pad = clone $this;
        $pad->string = $padStr;

        return $this->pad($length, $pad, \STR_PAD_BOTH);
    }

    public function padEnd(int $length, string $padStr = ' '): static
    {
        if ('' === $padStr || !preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $pad = clone $this;
        $pad->string = $padStr;

        return $this->pad($length, $pad, \STR_PAD_RIGHT);
    }

    public function padStart(int $length, string $padStr = ' '): static
    {
        if ('' === $padStr || !preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }

        $pad = clone $this;
        $pad->string = $padStr;

        return $this->pad($length, $pad, \STR_PAD_LEFT);
    }

    public function replaceMatches(string $fromRegexp, string|callable $to): static
    {
        if ($this->ignoreCase) {
            $fromRegexp .= 'i';
        }

        if (\is_array($to) || $to instanceof \Closure) {
            $replace = 'preg_replace_callback';
            $to = static function (array $m) use ($to): string {
                $to = $to($m);

                if ('' !== $to && (!\is_string($to) || !preg_match('//u', $to))) {
                    throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.');
                }

                return $to;
            };
        } elseif ('' !== $to && !preg_match('//u', $to)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        } else {
            $replace = 'preg_replace';
        }

        set_error_handler(static fn ($t, $m) => throw new InvalidArgumentException($m));

        try {
            if (null === $string = $replace($fromRegexp.'u', $to, $this->string)) {
                $lastError = preg_last_error();

                foreach (get_defined_constants(true)['pcre'] as $k => $v) {
                    if ($lastError === $v && str_ends_with($k, '_ERROR')) {
                        throw new RuntimeException('Matching failed with '.$k.'.');
                    }
                }

                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            restore_error_handler();
        }

        $str = clone $this;
        $str->string = $string;

        return $str;
    }

    public function reverse(): static
    {
        $str = clone $this;
        $str->string = implode('', array_reverse(grapheme_str_split($str->string)));

        return $str;
    }

    public function snake(): static
    {
        $str = $this->camel();
        $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8');

        return $str;
    }

    public function title(bool $allWords = false): static
    {
        $str = clone $this;

        $limit = $allWords ? -1 : 1;

        $str->string = preg_replace_callback('/\b./u', static fn (array $m): string => mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'), $str->string, $limit);

        return $str;
    }

    /**
     * @param string $locale In the format language_region (e.g. tr_TR)
     */
    public function localeTitle(string $locale): static
    {
        if (null !== $transliterator = $this->getLocaleTransliterator($locale, 'Title')) {
            $str = clone $this;
            $str->string = $transliterator->transliterate($str->string);

            return $str;
        }

        return $this->title();
    }

    public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static
    {
        if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = preg_quote($chars);

        $str = clone $this;
        $str->string = preg_replace("{^[$chars]++|[$chars]++$}uD", '', $str->string);

        return $str;
    }

    public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static
    {
        if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = preg_quote($chars);

        $str = clone $this;
        $str->string = preg_replace("{[$chars]++$}uD", '', $str->string);

        return $str;
    }

    public function trimPrefix($prefix): static
    {
        if (!$this->ignoreCase) {
            return parent::trimPrefix($prefix);
        }

        $str = clone $this;

        if ($prefix instanceof \Traversable) {
            $prefix = iterator_to_array($prefix, false);
        } elseif ($prefix instanceof parent) {
            $prefix = $prefix->string;
        }

        $prefix = implode('|', array_map('preg_quote', (array) $prefix));
        $str->string = preg_replace("{^(?:$prefix)}iuD", '', $this->string);

        return $str;
    }

    public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): static
    {
        if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = preg_quote($chars);

        $str = clone $this;
        $str->string = preg_replace("{^[$chars]++}uD", '', $str->string);

        return $str;
    }

    public function trimSuffix($suffix): static
    {
        if (!$this->ignoreCase) {
            return parent::trimSuffix($suffix);
        }

        $str = clone $this;

        if ($suffix instanceof \Traversable) {
            $suffix = iterator_to_array($suffix, false);
        } elseif ($suffix instanceof parent) {
            $suffix = $suffix->string;
        }

        $suffix = implode('|', array_map('preg_quote', (array) $suffix));
        $str->string = preg_replace("{(?:$suffix)$}iuD", '', $this->string);

        return $str;
    }

    public function upper(): static
    {
        $str = clone $this;
        $str->string = mb_strtoupper($str->string, 'UTF-8');

        return $str;
    }

    /**
     * @param string $locale In the format language_region (e.g. tr_TR)
     */
    public function localeUpper(string $locale): static
    {
        if (null !== $transliterator = $this->getLocaleTransliterator($locale, 'Upper')) {
            $str = clone $this;
            $str->string = $transliterator->transliterate($str->string);

            return $str;
        }

        return $this->upper();
    }

    public function width(bool $ignoreAnsiDecoration = true): int
    {
        $width = 0;
        $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string);

        if (str_contains($s, "\r")) {
            $s = str_replace(["\r\n", "\r"], "\n", $s);
        }

        if (!$ignoreAnsiDecoration) {
            $s = preg_replace('/[\p{Cc}\x7F]++/u', '', $s);
        }

        foreach (explode("\n", $s) as $s) {
            if ($ignoreAnsiDecoration) {
                $s = preg_replace('/(?:\x1B(?:
                    \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [\x40-\x7E]
                    | [P\]X^_] .*? \x1B\\\\
                    | [\x41-\x7E]
                )|[\p{Cc}\x7F]++)/xu', '', $s);
            }

            $lineWidth = $this->wcswidth($s);

            if ($lineWidth > $width) {
                $width = $lineWidth;
            }
        }

        return $width;
    }

    private function pad(int $len, self $pad, int $type): static
    {
        $sLen = $this->length();

        if ($len <= $sLen) {
            return clone $this;
        }

        $padLen = $pad->length();
        $freeLen = $len - $sLen;
        $len = $freeLen % $padLen;

        switch ($type) {
            case \STR_PAD_RIGHT:
                return $this->append(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : ''));

            case \STR_PAD_LEFT:
                return $this->prepend(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : ''));

            case \STR_PAD_BOTH:
                $freeLen /= 2;

                $rightLen = ceil($freeLen);
                $len = $rightLen % $padLen;
                $str = $this->append(str_repeat($pad->string, intdiv($rightLen, $padLen)).($len ? $pad->slice(0, $len) : ''));

                $leftLen = floor($freeLen);
                $len = $leftLen % $padLen;

                return $str->prepend(str_repeat($pad->string, intdiv($leftLen, $padLen)).($len ? $pad->slice(0, $len) : ''));

            default:
                throw new InvalidArgumentException('Invalid padding type.');
        }
    }

    /**
     * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c.
     */
    private function wcswidth(string $string): int
    {
        $width = 0;
        $lastChar = null;
        $lastWidth = null;

        foreach (preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
            $codePoint = mb_ord($c, 'UTF-8');

            if (0 === $codePoint // NULL
                || 0x034F === $codePoint // COMBINING GRAPHEME JOINER
                || (0x200B <= $codePoint && 0x200F >= $codePoint) // ZERO WIDTH SPACE to RIGHT-TO-LEFT MARK
                || 0x2028 === $codePoint // LINE SEPARATOR
                || 0x2029 === $codePoint // PARAGRAPH SEPARATOR
                || (0x202A <= $codePoint && 0x202E >= $codePoint) // LEFT-TO-RIGHT EMBEDDING to RIGHT-TO-LEFT OVERRIDE
                || (0x2060 <= $codePoint && 0x2063 >= $codePoint) // WORD JOINER to INVISIBLE SEPARATOR
            ) {
                continue;
            }

            // Non printable characters
            if (32 > $codePoint // C0 control characters
                || (0x07F <= $codePoint && 0x0A0 > $codePoint) // C1 control characters and DEL
            ) {
                return -1;
            }

            if (0xFE0F === $codePoint) {
                if (\PCRE_VERSION_MAJOR < 10 || \PCRE_VERSION_MAJOR === 10 && \PCRE_VERSION_MINOR < 40) {
                    $regex = '/\p{So}/u';
                } else {
                    $regex = '/\p{Emoji}/u';
                }
                if (null !== $lastChar && 1 === $lastWidth && preg_match($regex, $lastChar)) {
                    ++$width;
                    $lastWidth = 2;
                }

                continue;
            }

            self::$tableZero ??= require __DIR__.'/Resources/data/wcswidth_table_zero.php';

            if ($codePoint >= self::$tableZero[0][0] && $codePoint <= self::$tableZero[$ubound = \count(self::$tableZero) - 1][1]) {
                $lbound = 0;
                while ($ubound >= $lbound) {
                    $mid = floor(($lbound + $ubound) / 2);

                    if ($codePoint > self::$tableZero[$mid][1]) {
                        $lbound = $mid + 1;
                    } elseif ($codePoint < self::$tableZero[$mid][0]) {
                        $ubound = $mid - 1;
                    } else {
                        continue 2;
                    }
                }
            }

            self::$tableWide ??= require __DIR__.'/Resources/data/wcswidth_table_wide.php';

            if ($codePoint >= self::$tableWide[0][0] && $codePoint <= self::$tableWide[$ubound = \count(self::$tableWide) - 1][1]) {
                $lbound = 0;
                while ($ubound >= $lbound) {
                    $mid = floor(($lbound + $ubound) / 2);

                    if ($codePoint > self::$tableWide[$mid][1]) {
                        $lbound = $mid + 1;
                    } elseif ($codePoint < self::$tableWide[$mid][0]) {
                        $ubound = $mid - 1;
                    } else {
                        $width += 2;
                        $lastChar = $c;
                        $lastWidth = 2;

                        continue 2;
                    }
                }
            }

            ++$width;
            $lastChar = $c;
            $lastWidth = 1;
        }

        return $width;
    }

    private function getLocaleTransliterator(string $locale, string $id): ?\Transliterator
    {
        $rule = $locale.'-'.$id;
        if (\array_key_exists($rule, self::$transliterators)) {
            return self::$transliterators[$rule];
        }

        if (null !== $transliterator = self::$transliterators[$rule] = \Transliterator::create($rule)) {
            return $transliterator;
        }

        // Try to find a parent locale (nl_BE -> nl)
        if (false === $i = strpos($locale, '_')) {
            return null;
        }

        $parentRule = substr_replace($locale, '-'.$id, $i);

        // Parent locale was already cached, return and store as current locale
        if (\array_key_exists($parentRule, self::$transliterators)) {
            return self::$transliterators[$rule] = self::$transliterators[$parentRule];
        }

        // Create transliterator based on parent locale and cache the result on both initial and parent locale values
        $transliterator = \Transliterator::create($parentRule);

        return self::$transliterators[$rule] = self::$transliterators[$parentRule] = $transliterator;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Translation;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface TranslatableInterface
{
    public function trans(TranslatorInterface $translator, ?string $locale = null): string;
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Translation;

interface LocaleAwareInterface
{
    /**
     * Sets the current locale.
     *
     * @return void
     *
     * @throws \InvalidArgumentException If the locale contains invalid characters
     */
    public function setLocale(string $locale);

    /**
     * Returns the current locale.
     */
    public function getLocale(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Translation\Test;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\TranslatableMessage;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\TranslatorTrait;

/**
 * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
 * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms.
 *
 * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
 * The mozilla code is also interesting to check for.
 *
 * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
 *
 * The goal to cover all languages is too far fetched so this test case is smaller.
 *
 * @author Clemens Tolboom clemens@build2be.nl
 */
class TranslatorTest extends TestCase
{
    private string $defaultLocale;

    protected function setUp(): void
    {
        $this->defaultLocale = \Locale::getDefault();
        \Locale::setDefault('en');
    }

    protected function tearDown(): void
    {
        \Locale::setDefault($this->defaultLocale);
    }

    public function getTranslator(): TranslatorInterface
    {
        return new class implements TranslatorInterface {
            use TranslatorTrait;
        };
    }

    /**
     * @dataProvider getTransTests
     */
    #[DataProvider('getTransTests')]
    public function testTrans($expected, $id, $parameters)
    {
        $translator = $this->getTranslator();

        $this->assertEquals($expected, $translator->trans($id, $parameters));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    #[DataProvider('getTransChoiceTests')]
    public function testTransChoiceWithExplicitLocale($expected, $id, $number)
    {
        $translator = $this->getTranslator();

        $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
    }

    /**
     * @requires extension intl
     *
     * @dataProvider getTransChoiceTests
     */
    #[DataProvider('getTransChoiceTests')]
    #[RequiresPhpExtension('intl')]
    public function testTransChoiceWithDefaultLocale($expected, $id, $number)
    {
        $translator = $this->getTranslator();

        $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    #[DataProvider('getTransChoiceTests')]
    public function testTransChoiceWithEnUsPosix($expected, $id, $number)
    {
        $translator = $this->getTranslator();
        $translator->setLocale('en_US_POSIX');

        $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
    }

    public function testGetSetLocale()
    {
        $translator = $this->getTranslator();

        $this->assertEquals('en', $translator->getLocale());
    }

    /**
     * @requires extension intl
     */
    #[RequiresPhpExtension('intl')]
    public function testGetLocaleReturnsDefaultLocaleIfNotSet()
    {
        $translator = $this->getTranslator();

        \Locale::setDefault('pt_BR');
        $this->assertEquals('pt_BR', $translator->getLocale());

        \Locale::setDefault('en');
        $this->assertEquals('en', $translator->getLocale());
    }

    public static function getTransTests()
    {
        yield ['Symfony is great!', 'Symfony is great!', []];
        yield ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']];

        if (class_exists(TranslatableMessage::class)) {
            yield ['He said "Symfony is awesome!".', 'He said "%what%".', ['%what%' => new TranslatableMessage('Symfony is %what%!', ['%what%' => 'awesome'])]];
        }
    }

    public static function getTransChoiceTests()
    {
        return [
            ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
            ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
            ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
            ['There are 0 apples', 'There is 1 apple|There are %count% apples', 0],
            ['There is 1 apple', 'There is 1 apple|There are %count% apples', 1],
            ['There are 10 apples', 'There is 1 apple|There are %count% apples', 10],
            // custom validation messages may be coded with a fixed value
            ['There are 2 apples', 'There are 2 apples', 2],
        ];
    }

    /**
     * @dataProvider getInterval
     */
    #[DataProvider('getInterval')]
    public function testInterval($expected, $number, $interval)
    {
        $translator = $this->getTranslator();

        $this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number]));
    }

    public static function getInterval()
    {
        return [
            ['foo', 3, '{1,2, 3 ,4}'],
            ['bar', 10, '{1,2, 3 ,4}'],
            ['bar', 3, '[1,2]'],
            ['foo', 1, '[1,2]'],
            ['foo', 2, '[1,2]'],
            ['bar', 1, ']1,2['],
            ['bar', 2, ']1,2['],
            ['foo', log(0), '[-Inf,2['],
            ['foo', -log(0), '[-2,+Inf]'],
        ];
    }

    /**
     * @dataProvider getChooseTests
     */
    #[DataProvider('getChooseTests')]
    public function testChoose($expected, $id, $number, $locale = null)
    {
        $translator = $this->getTranslator();

        $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number], null, $locale));
    }

    public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
    {
        $translator = $this->getTranslator();

        $this->assertEquals('There are two apples', $translator->trans('There are two apples', ['%count%' => 2]));
    }

    /**
     * @dataProvider getNonMatchingMessages
     */
    #[DataProvider('getNonMatchingMessages')]
    public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
    {
        $translator = $this->getTranslator();

        $this->expectException(\InvalidArgumentException::class);

        $translator->trans($id, ['%count%' => $number]);
    }

    public static function getNonMatchingMessages()
    {
        return [
            ['{0} There are no apples|{1} There is one apple', 2],
            ['{1} There is one apple|]1,Inf] There are %count% apples', 0],
            ['{1} There is one apple|]2,Inf] There are %count% apples', 2],
            ['{0} There are no apples|There is one apple', 2],
        ];
    }

    public static function getChooseTests()
    {
        return [
            ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
            ['There are no apples', '{0}     There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
            ['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],

            ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],

            ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
            ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10],
            ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]     There are %count% apples', 10],

            ['There are 0 apples', 'There is one apple|There are %count% apples', 0],
            ['There is one apple', 'There is one apple|There are %count% apples', 1],
            ['There are 10 apples', 'There is one apple|There are %count% apples', 10],

            ['There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0],
            ['There is one apple', 'one: There is one apple|more: There are %count% apples', 1],
            ['There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10],

            ['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0],
            ['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1],
            ['There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10],

            ['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0],
            ['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1],

            // Indexed only tests which are Gettext PoFile* compatible strings.
            ['There are 0 apples', 'There is one apple|There are %count% apples', 0],
            ['There is one apple', 'There is one apple|There are %count% apples', 1],
            ['There are 2 apples', 'There is one apple|There are %count% apples', 2],

            // Tests for float numbers
            ['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7],
            ['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1],
            ['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7],
            ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
            ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0],
            ['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],

            // Test texts with new-lines
            // with double-quotes and \n in id & double-quotes and actual newlines in text
            ["This is a text with a\n            new-line in it. Selector = 0.", '{0}This is a text with a
            new-line in it. Selector = 0.|{1}This is a text with a
            new-line in it. Selector = 1.|[1,Inf]This is a text with a
            new-line in it. Selector > 1.', 0],
            // with double-quotes and \n in id and single-quotes and actual newlines in text
            ["This is a text with a\n            new-line in it. Selector = 1.", '{0}This is a text with a
            new-line in it. Selector = 0.|{1}This is a text with a
            new-line in it. Selector = 1.|[1,Inf]This is a text with a
            new-line in it. Selector > 1.', 1],
            ["This is a text with a\n            new-line in it. Selector > 1.", '{0}This is a text with a
            new-line in it. Selector = 0.|{1}This is a text with a
            new-line in it. Selector = 1.|[1,Inf]This is a text with a
            new-line in it. Selector > 1.', 5],
            // with double-quotes and id split across lines
            ['This is a text with a
            new-line in it. Selector = 1.', '{0}This is a text with a
            new-line in it. Selector = 0.|{1}This is a text with a
            new-line in it. Selector = 1.|[1,Inf]This is a text with a
            new-line in it. Selector > 1.', 1],
            // with single-quotes and id split across lines
            ['This is a text with a
            new-line in it. Selector > 1.', '{0}This is a text with a
            new-line in it. Selector = 0.|{1}This is a text with a
            new-line in it. Selector = 1.|[1,Inf]This is a text with a
            new-line in it. Selector > 1.', 5],
            // with single-quotes and \n in text
            ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0],
            // with double-quotes and id split across lines
            ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1],
            // escape pipe
            ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0],
            // Empty plural set (2 plural forms) from a .PO file
            ['', '|', 1],
            // Empty plural set (3 plural forms) from a .PO file
            ['', '||', 1],

            // Floating values
            ['1.5 liters', '%count% liter|%count% liters', 1.5],
            ['1.5 litre', '%count% litre|%count% litres', 1.5, 'fr'],

            // Negative values
            ['-1 degree', '%count% degree|%count% degrees', -1],
            ['-1 degré', '%count% degré|%count% degrés', -1],
            ['-1.5 degrees', '%count% degree|%count% degrees', -1.5],
            ['-1.5 degré', '%count% degré|%count% degrés', -1.5, 'fr'],
            ['-2 degrees', '%count% degree|%count% degrees', -2],
            ['-2 degrés', '%count% degré|%count% degrés', -2],
        ];
    }

    /**
     * @dataProvider failingLangcodes
     */
    #[DataProvider('failingLangcodes')]
    public function testFailedLangcodes($nplural, $langCodes)
    {
        $matrix = $this->generateTestData($langCodes);
        $this->validateMatrix($nplural, $matrix, false);
    }

    /**
     * @dataProvider successLangcodes
     */
    #[DataProvider('successLangcodes')]
    public function testLangcodes($nplural, $langCodes)
    {
        $matrix = $this->generateTestData($langCodes);
        $this->validateMatrix($nplural, $matrix);
    }

    /**
     * This array should contain all currently known langcodes.
     *
     * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
     */
    public static function successLangcodes(): array
    {
        return [
            ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']],
            ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM', 'en_US_POSIX']],
            ['3', ['be', 'bs', 'cs', 'hr']],
            ['4', ['cy', 'mt', 'sl']],
            ['6', ['ar']],
        ];
    }

    /**
     * This array should be at least empty within the near future.
     *
     * This both depends on a complete list trying to add above as understanding
     * the plural rules of the current failing languages.
     *
     * @return array With nplural together with langcodes
     */
    public static function failingLangcodes(): array
    {
        return [
            ['1', ['fa']],
            ['2', ['jbo']],
            ['3', ['cbs']],
            ['4', ['gd', 'kw']],
            ['5', ['ga']],
        ];
    }

    /**
     * We validate only on the plural coverage. Thus the real rules is not tested.
     *
     * @param string $nplural Plural expected
     * @param array  $matrix  Containing langcodes and their plural index values
     */
    protected function validateMatrix(string $nplural, array $matrix, bool $expectSuccess = true)
    {
        foreach ($matrix as $langCode => $data) {
            $indexes = array_flip($data);
            if ($expectSuccess) {
                $this->assertCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms.");
            } else {
                $this->assertNotCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms.");
            }
        }
    }

    protected function generateTestData($langCodes)
    {
        $translator = new class {
            use TranslatorTrait {
                getPluralizationRule as public;
            }
        };

        $matrix = [];
        foreach ($langCodes as $langCode) {
            for ($count = 0; $count < 200; ++$count) {
                $plural = $translator->getPluralizationRule($count, $langCode);
                $matrix[$langCode][$count] = $plural;
            }
        }

        return $matrix;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Translation;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface TranslatorInterface
{
    /**
     * Translates the given message.
     *
     * When a number is provided as a parameter named "%count%", the message is parsed for plural
     * forms and a translation is chosen according to this number using the following rules:
     *
     * Given a message with different plural translations separated by a
     * pipe (|), this method returns the correct portion of the message based
     * on the given number, locale and the pluralization rules in the message
     * itself.
     *
     * The message supports two different types of pluralization rules:
     *
     * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
     * indexed:  There is one apple|There are %count% apples
     *
     * The indexed solution can also contain labels (e.g. one: There is one apple).
     * This is purely for making the translations more clear - it does not
     * affect the functionality.
     *
     * The two methods can also be mixed:
     *     {0} There are no apples|one: There is one apple|more: There are %count% apples
     *
     * An interval can represent a finite set of numbers:
     *  {1,2,3,4}
     *
     * An interval can represent numbers between two numbers:
     *  [1, +Inf]
     *  ]-1,2[
     *
     * The left delimiter can be [ (inclusive) or ] (exclusive).
     * The right delimiter can be [ (exclusive) or ] (inclusive).
     * Beside numbers, you can use -Inf and +Inf for the infinite.
     *
     * @see https://en.wikipedia.org/wiki/ISO_31-11
     *
     * @param string      $id         The message id (may also be an object that can be cast to string)
     * @param array       $parameters An array of parameters for the message
     * @param string|null $domain     The domain for the message or null to use the default
     * @param string|null $locale     The locale or null to use the default
     *
     * @throws \InvalidArgumentException If the locale contains invalid characters
     */
    public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string;

    /**
     * Returns the default locale.
     */
    public function getLocale(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Translation;

use Symfony\Component\Translation\Exception\InvalidArgumentException;

/**
 * A trait to help implement TranslatorInterface and LocaleAwareInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
trait TranslatorTrait
{
    private ?string $locale = null;

    /**
     * @return void
     */
    public function setLocale(string $locale)
    {
        $this->locale = $locale;
    }

    public function getLocale(): string
    {
        return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
    }

    public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
    {
        if (null === $id || '' === $id) {
            return '';
        }

        foreach ($parameters as $k => $v) {
            if ($v instanceof TranslatableInterface) {
                $parameters[$k] = $v->trans($this, $locale);
            }
        }

        if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
            return strtr($id, $parameters);
        }

        $number = (float) $parameters['%count%'];
        $locale = $locale ?: $this->getLocale();

        $parts = [];
        if (preg_match('/^\|++$/', $id)) {
            $parts = explode('|', $id);
        } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
            $parts = $matches[0];
        }

        $intervalRegexp = <<<'EOF'
            /^(?P<interval>
                ({\s*
                    (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
                \s*})

                    |

                (?P<left_delimiter>[\[\]])
                    \s*
                    (?P<left>-Inf|\-?\d+(\.\d+)?)
                    \s*,\s*
                    (?P<right>\+?Inf|\-?\d+(\.\d+)?)
                    \s*
                (?P<right_delimiter>[\[\]])
            )\s*(?P<message>.*?)$/xs
            EOF;

        $standardRules = [];
        foreach ($parts as $part) {
            $part = trim(str_replace('||', '|', $part));

            // try to match an explicit rule, then fallback to the standard ones
            if (preg_match($intervalRegexp, $part, $matches)) {
                if ($matches[2]) {
                    foreach (explode(',', $matches[3]) as $n) {
                        if ($number == $n) {
                            return strtr($matches['message'], $parameters);
                        }
                    }
                } else {
                    $leftNumber = '-Inf' === $matches['left'] ? -\INF : (float) $matches['left'];
                    $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : \INF;

                    if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
                        && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
                    ) {
                        return strtr($matches['message'], $parameters);
                    }
                }
            } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
                $standardRules[] = $matches[1];
            } else {
                $standardRules[] = $part;
            }
        }

        $position = $this->getPluralizationRule($number, $locale);

        if (!isset($standardRules[$position])) {
            // when there's exactly one rule given, and that rule is a standard
            // rule, use this rule
            if (1 === \count($parts) && isset($standardRules[0])) {
                return strtr($standardRules[0], $parameters);
            }

            $message = \sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);

            if (class_exists(InvalidArgumentException::class)) {
                throw new InvalidArgumentException($message);
            }

            throw new \InvalidArgumentException($message);
        }

        return strtr($standardRules[$position], $parameters);
    }

    /**
     * Returns the plural position to use for the given locale and number.
     *
     * The plural rules are derived from code of the Zend Framework (2010-09-25),
     * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
     * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     */
    private function getPluralizationRule(float $number, string $locale): int
    {
        $number = abs($number);

        return match ('pt_BR' !== $locale && 'en_US_POSIX' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
            'af',
            'bn',
            'bg',
            'ca',
            'da',
            'de',
            'el',
            'en',
            'en_US_POSIX',
            'eo',
            'es',
            'et',
            'eu',
            'fa',
            'fi',
            'fo',
            'fur',
            'fy',
            'gl',
            'gu',
            'ha',
            'he',
            'hu',
            'is',
            'it',
            'ku',
            'lb',
            'ml',
            'mn',
            'mr',
            'nah',
            'nb',
            'ne',
            'nl',
            'nn',
            'no',
            'oc',
            'om',
            'or',
            'pa',
            'pap',
            'ps',
            'pt',
            'so',
            'sq',
            'sv',
            'sw',
            'ta',
            'te',
            'tk',
            'ur',
            'zu' => (1 == $number) ? 0 : 1,
            'am',
            'bh',
            'fil',
            'fr',
            'gun',
            'hi',
            'hy',
            'ln',
            'mg',
            'nso',
            'pt_BR',
            'ti',
            'wa' => ($number < 2) ? 0 : 1,
            'be',
            'bs',
            'hr',
            'ru',
            'sh',
            'sr',
            'uk' => ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2),
            'cs',
            'sk' => (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2),
            'ga' => (1 == $number) ? 0 : ((2 == $number) ? 1 : 2),
            'lt' => ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2),
            'sl' => (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)),
            'mk' => (1 == $number % 10) ? 0 : 1,
            'mt' => (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)),
            'lv' => (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2),
            'pl' => (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2),
            'cy' => (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)),
            'ro' => (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2),
            'ar' => (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))),
            default => 0,
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Pierre du Plessis <pdples@gmail.com>
 */
final class Cursor
{
    /** @var resource */
    private $input;

    /**
     * @param resource|null $input
     */
    public function __construct(
        private OutputInterface $output,
        $input = null,
    ) {
        $this->input = $input ?? (\defined('STDIN') ? \STDIN : fopen('php://input', 'r+'));
    }

    /**
     * @return $this
     */
    public function moveUp(int $lines = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dA", $lines));

        return $this;
    }

    /**
     * @return $this
     */
    public function moveDown(int $lines = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dB", $lines));

        return $this;
    }

    /**
     * @return $this
     */
    public function moveRight(int $columns = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dC", $columns));

        return $this;
    }

    /**
     * @return $this
     */
    public function moveLeft(int $columns = 1): static
    {
        $this->output->write(\sprintf("\x1b[%dD", $columns));

        return $this;
    }

    /**
     * @return $this
     */
    public function moveToColumn(int $column): static
    {
        $this->output->write(\sprintf("\x1b[%dG", $column));

        return $this;
    }

    /**
     * @return $this
     */
    public function moveToPosition(int $column, int $row): static
    {
        $this->output->write(\sprintf("\x1b[%d;%dH", $row + 1, $column));

        return $this;
    }

    /**
     * @return $this
     */
    public function savePosition(): static
    {
        $this->output->write("\x1b7");

        return $this;
    }

    /**
     * @return $this
     */
    public function restorePosition(): static
    {
        $this->output->write("\x1b8");

        return $this;
    }

    /**
     * @return $this
     */
    public function hide(): static
    {
        $this->output->write("\x1b[?25l");

        return $this;
    }

    /**
     * @return $this
     */
    public function show(): static
    {
        $this->output->write("\x1b[?25h\x1b[?0c");

        return $this;
    }

    /**
     * Clears all the output from the current line.
     *
     * @return $this
     */
    public function clearLine(): static
    {
        $this->output->write("\x1b[2K");

        return $this;
    }

    /**
     * Clears all the output from the current line after the current position.
     */
    public function clearLineAfter(): self
    {
        $this->output->write("\x1b[K");

        return $this;
    }

    /**
     * Clears all the output from the cursors' current position to the end of the screen.
     *
     * @return $this
     */
    public function clearOutput(): static
    {
        $this->output->write("\x1b[0J");

        return $this;
    }

    /**
     * Clears the entire screen.
     *
     * @return $this
     */
    public function clearScreen(): static
    {
        $this->output->write("\x1b[2J");

        return $this;
    }

    /**
     * Returns the current cursor position as x,y coordinates.
     */
    public function getCurrentPosition(): array
    {
        static $isTtySupported;

        if (!$isTtySupported ??= '/' === \DIRECTORY_SEPARATOR && stream_isatty(\STDOUT)) {
            return [1, 1];
        }

        $sttyMode = shell_exec('stty -g');
        shell_exec('stty -icanon -echo');

        @fwrite($this->input, "\033[6n");

        $code = trim(fread($this->input, 1024));

        shell_exec(\sprintf('stty %s', $sttyMode));

        sscanf($code, "\033[%d;%dR", $row, $col);

        return [$col, $row];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Style;

/**
 * Output style helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface StyleInterface
{
    /**
     * Formats a command title.
     */
    public function title(string $message): void;

    /**
     * Formats a section title.
     */
    public function section(string $message): void;

    /**
     * Formats a list.
     */
    public function listing(array $elements): void;

    /**
     * Formats informational text.
     */
    public function text(string|array $message): void;

    /**
     * Formats a success result bar.
     */
    public function success(string|array $message): void;

    /**
     * Formats an error result bar.
     */
    public function error(string|array $message): void;

    /**
     * Formats an warning result bar.
     */
    public function warning(string|array $message): void;

    /**
     * Formats a note admonition.
     */
    public function note(string|array $message): void;

    /**
     * Formats a caution admonition.
     */
    public function caution(string|array $message): void;

    /**
     * Formats a table.
     */
    public function table(array $headers, array $rows): void;

    /**
     * Asks a question.
     *
     * @param (callable(mixed):mixed)|null $validator
     */
    public function ask(string $question, ?string $default = null, ?callable $validator = null): mixed;

    /**
     * Asks a question with the user input hidden.
     *
     * @param (callable(mixed):mixed)|null $validator
     */
    public function askHidden(string $question, ?callable $validator = null): mixed;

    /**
     * Asks for confirmation.
     */
    public function confirm(string $question, bool $default = true): bool;

    /**
     * Asks a choice question.
     */
    public function choice(string $question, array $choices, mixed $default = null): mixed;

    /**
     * Add newline(s).
     */
    public function newLine(int $count = 1): void;

    /**
     * Starts the progress output.
     */
    public function progressStart(int $max = 0): void;

    /**
     * Advances the progress output X steps.
     */
    public function progressAdvance(int $step = 1): void;

    /**
     * Finishes the progress output.
     */
    public function progressFinish(): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Style;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Helper\OutputWrapper;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Helper\TreeHelper;
use Symfony\Component\Console\Helper\TreeNode;
use Symfony\Component\Console\Helper\TreeStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\TrimmedBufferOutput;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Terminal;

/**
 * Output decorator helpers for the Symfony Style Guide.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyStyle extends OutputStyle
{
    public const MAX_LINE_LENGTH = 120;

    private SymfonyQuestionHelper $questionHelper;
    private ProgressBar $progressBar;
    private int $lineLength;
    private TrimmedBufferOutput $bufferedOutput;

    public function __construct(
        private InputInterface $input,
        private OutputInterface $output,
    ) {
        $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), false, clone $output->getFormatter());
        // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
        $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
        $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);

        parent::__construct($output);
    }

    /**
     * Formats a message as a block of text.
     */
    public function block(string|array $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true): void
    {
        $messages = \is_array($messages) ? array_values($messages) : [$messages];

        $this->autoPrependBlock();
        $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
        $this->newLine();
    }

    public function title(string $message): void
    {
        $this->autoPrependBlock();
        $this->writeln([
            \sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
            \sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))),
        ]);
        $this->newLine();
    }

    public function section(string $message): void
    {
        $this->autoPrependBlock();
        $this->writeln([
            \sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
            \sprintf('<comment>%s</>', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message)))),
        ]);
        $this->newLine();
    }

    public function listing(array $elements): void
    {
        $this->autoPrependText();
        $elements = array_map(static fn ($element) => \sprintf(' * %s', $element), $elements);

        $this->writeln($elements);
        $this->newLine();
    }

    public function text(string|array $message): void
    {
        $this->autoPrependText();

        $messages = \is_array($message) ? array_values($message) : [$message];
        foreach ($messages as $message) {
            $this->writeln(\sprintf(' %s', $message));
        }
    }

    /**
     * Formats a command comment.
     */
    public function comment(string|array $message): void
    {
        $this->block($message, null, null, '<fg=default;bg=default> // </>', false, false);
    }

    public function success(string|array $message): void
    {
        $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
    }

    public function error(string|array $message): void
    {
        $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
    }

    public function warning(string|array $message): void
    {
        $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true);
    }

    public function note(string|array $message): void
    {
        $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
    }

    /**
     * Formats an info message.
     */
    public function info(string|array $message): void
    {
        $this->block($message, 'INFO', 'fg=green', ' ', true);
    }

    public function caution(string|array $message): void
    {
        $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
    }

    public function table(array $headers, array $rows): void
    {
        $this->createTable()
            ->setHeaders($headers)
            ->setRows($rows)
            ->render()
        ;

        $this->newLine();
    }

    /**
     * Formats a horizontal table.
     */
    public function horizontalTable(array $headers, array $rows): void
    {
        $this->createTable()
            ->setHorizontal(true)
            ->setHeaders($headers)
            ->setRows($rows)
            ->render()
        ;

        $this->newLine();
    }

    /**
     * Formats a list of key/value horizontally.
     *
     * Each row can be one of:
     * * 'A title'
     * * ['key' => 'value']
     * * new TableSeparator()
     */
    public function definitionList(string|array|TableSeparator ...$list): void
    {
        $headers = [];
        $row = [];
        foreach ($list as $value) {
            if ($value instanceof TableSeparator) {
                $headers[] = $value;
                $row[] = $value;
                continue;
            }
            if (\is_string($value)) {
                $headers[] = new TableCell($value, ['colspan' => 2]);
                $row[] = null;
                continue;
            }
            if (!\is_array($value)) {
                throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
            }
            $headers[] = key($value);
            $row[] = current($value);
        }

        $this->horizontalTable($headers, [$row]);
    }

    public function ask(string $question, ?string $default = null, ?callable $validator = null): mixed
    {
        $question = new Question($question, $default);
        $question->setValidator($validator);

        return $this->askQuestion($question);
    }

    public function askHidden(string $question, ?callable $validator = null): mixed
    {
        $question = new Question($question);

        $question->setHidden(true);
        $question->setValidator($validator);

        return $this->askQuestion($question);
    }

    public function confirm(string $question, bool $default = true): bool
    {
        return $this->askQuestion(new ConfirmationQuestion($question, $default));
    }

    public function choice(string $question, array $choices, mixed $default = null, bool $multiSelect = false): mixed
    {
        if (null !== $default) {
            $values = array_flip($choices);
            $default = $values[$default] ?? $default;
        }

        $questionChoice = new ChoiceQuestion($question, $choices, $default);
        $questionChoice->setMultiselect($multiSelect);

        return $this->askQuestion($questionChoice);
    }

    public function progressStart(int $max = 0): void
    {
        $this->progressBar = $this->createProgressBar($max);
        $this->progressBar->start();
    }

    public function progressAdvance(int $step = 1): void
    {
        $this->getProgressBar()->advance($step);
    }

    public function progressFinish(): void
    {
        $this->getProgressBar()->finish();
        $this->newLine(2);
        unset($this->progressBar);
    }

    public function createProgressBar(int $max = 0): ProgressBar
    {
        $progressBar = parent::createProgressBar($max);

        if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
            $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591
            $progressBar->setProgressCharacter('');
            $progressBar->setBarCharacter('▓'); // dark shade character \u2593
        }

        return $progressBar;
    }

    /**
     * @see ProgressBar::iterate()
     *
     * @template TKey
     * @template TValue
     *
     * @param iterable<TKey, TValue> $iterable
     * @param int|null               $max      Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
     *
     * @return iterable<TKey, TValue>
     */
    public function progressIterate(iterable $iterable, ?int $max = null): iterable
    {
        yield from $this->createProgressBar()->iterate($iterable, $max);

        $this->newLine(2);
    }

    public function askQuestion(Question $question): mixed
    {
        if ($this->input->isInteractive()) {
            $this->autoPrependBlock();
        }

        $this->questionHelper ??= new SymfonyQuestionHelper();

        $answer = $this->questionHelper->ask($this->input, $this, $question);

        if ($this->input->isInteractive()) {
            if ($this->output instanceof ConsoleSectionOutput) {
                // add the new line of the `return` to submit the input to ConsoleSectionOutput, because ConsoleSectionOutput is holding all it's lines.
                // this is relevant when a `ConsoleSectionOutput::clear` is called.
                $this->output->addNewLineOfInputSubmit();
            }
            $this->newLine();
            $this->bufferedOutput->write("\n");
        }

        return $answer;
    }

    public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL): void
    {
        if (!is_iterable($messages)) {
            $messages = [$messages];
        }

        foreach ($messages as $message) {
            parent::writeln($message, $type);
            $this->writeBuffer($message, true, $type);
        }
    }

    public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL): void
    {
        if (!is_iterable($messages)) {
            $messages = [$messages];
        }

        foreach ($messages as $message) {
            parent::write($message, $newline, $type);
            $this->writeBuffer($message, $newline, $type);
        }
    }

    public function newLine(int $count = 1): void
    {
        parent::newLine($count);
        $this->bufferedOutput->write(str_repeat("\n", $count));
    }

    /**
     * Returns a new instance which makes use of stderr if available.
     */
    public function getErrorStyle(): self
    {
        return new self($this->input, $this->getErrorOutput());
    }

    public function createTable(): Table
    {
        $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
        $style = clone Table::getStyleDefinition('symfony-style-guide');
        $style->setCellHeaderFormat('<info>%s</info>');

        return (new Table($output))->setStyle($style);
    }

    private function getProgressBar(): ProgressBar
    {
        return $this->progressBar
            ?? throw new RuntimeException('The ProgressBar is not started.');
    }

    /**
     * @param iterable<string, iterable|string|TreeNode> $nodes
     */
    public function tree(iterable $nodes, string $root = ''): void
    {
        $this->createTree($nodes, $root)->render();
    }

    /**
     * @param iterable<string, iterable|string|TreeNode> $nodes
     */
    public function createTree(iterable $nodes, string $root = ''): TreeHelper
    {
        $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;

        return TreeHelper::createTree($output, $root, $nodes, TreeStyle::default());
    }

    private function autoPrependBlock(): void
    {
        $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);

        if (!isset($chars[0])) {
            $this->newLine(); // empty history, so we should start with a new line.

            return;
        }
        // Prepend new line for each non LF chars (This means no blank line was output before)
        $this->newLine(2 - substr_count($chars, "\n"));
    }

    private function autoPrependText(): void
    {
        $fetched = $this->bufferedOutput->fetch();
        // Prepend new line if last char isn't EOL:
        if ($fetched && !str_ends_with($fetched, "\n")) {
            $this->newLine();
        }
    }

    private function writeBuffer(string $message, bool $newLine, int $type): void
    {
        // We need to know if the last chars are PHP_EOL
        $this->bufferedOutput->write($message, $newLine, $type);
    }

    private function createBlock(iterable $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array
    {
        $indentLength = 0;
        $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
        $lines = [];

        if (null !== $type) {
            $type = \sprintf('[%s] ', $type);
            $indentLength = Helper::width($type);
            $lineIndentation = str_repeat(' ', $indentLength);
        }

        // wrap and add newlines for each element
        $outputWrapper = new OutputWrapper();
        foreach ($messages as $key => $message) {
            if ($escape) {
                $message = OutputFormatter::escape($message);
            }

            $message = str_replace("\r\n", "\n", $message);

            $lines = array_merge(
                $lines,
                explode("\n", $outputWrapper->wrap(
                    $message,
                    $this->lineLength - $prefixLength - $indentLength,
                    "\n"
                ))
            );

            if (\count($messages) > 1 && $key < \count($messages) - 1) {
                $lines[] = '';
            }
        }

        $firstLineIndex = 0;
        if ($padding && $this->isDecorated()) {
            $firstLineIndex = 1;
            array_unshift($lines, '');
            $lines[] = '';
        }

        foreach ($lines as $i => &$line) {
            if (null !== $type) {
                $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
            }

            $line = $prefix.$line;
            $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));

            if ($style) {
                $line = \sprintf('<%s>%s</>', $style, $line);
            }
        }

        return $lines;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Style;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Decorates output to add console style guide helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
abstract class OutputStyle implements OutputInterface, StyleInterface
{
    public function __construct(
        private OutputInterface $output,
    ) {
    }

    public function newLine(int $count = 1): void
    {
        $this->output->write(str_repeat(\PHP_EOL, $count));
    }

    public function createProgressBar(int $max = 0): ProgressBar
    {
        return new ProgressBar($this->output, $max);
    }

    public function write(string|iterable $messages, bool $newline = false, int $type = self::OUTPUT_NORMAL): void
    {
        $this->output->write($messages, $newline, $type);
    }

    public function writeln(string|iterable $messages, int $type = self::OUTPUT_NORMAL): void
    {
        $this->output->writeln($messages, $type);
    }

    public function setVerbosity(int $level): void
    {
        $this->output->setVerbosity($level);
    }

    public function getVerbosity(): int
    {
        return $this->output->getVerbosity();
    }

    public function setDecorated(bool $decorated): void
    {
        $this->output->setDecorated($decorated);
    }

    public function isDecorated(): bool
    {
        return $this->output->isDecorated();
    }

    public function setFormatter(OutputFormatterInterface $formatter): void
    {
        $this->output->setFormatter($formatter);
    }

    public function getFormatter(): OutputFormatterInterface
    {
        return $this->output->getFormatter();
    }

    public function isSilent(): bool
    {
        // @deprecated since Symfony 7.2, change to $this->output->isSilent() in 8.0
        return method_exists($this->output, 'isSilent') ? $this->output->isSilent() : self::VERBOSITY_SILENT === $this->output->getVerbosity();
    }

    public function isQuiet(): bool
    {
        return $this->output->isQuiet();
    }

    public function isVerbose(): bool
    {
        return $this->output->isVerbose();
    }

    public function isVeryVerbose(): bool
    {
        return $this->output->isVeryVerbose();
    }

    public function isDebug(): bool
    {
        return $this->output->isDebug();
    }

    protected function getErrorOutput(): OutputInterface
    {
        if (!$this->output instanceof ConsoleOutputInterface) {
            return $this->output;
        }

        return $this->output->getErrorOutput();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester\Constraint;

use PHPUnit\Framework\Constraint\Constraint;
use Symfony\Component\Console\Command\Command;

final class CommandIsSuccessful extends Constraint
{
    public function toString(): string
    {
        return 'is successful';
    }

    protected function matches($other): bool
    {
        return Command::SUCCESS === $other;
    }

    protected function failureDescription($other): string
    {
        return 'the command '.$this->toString();
    }

    protected function additionalFailureDescription($other): string
    {
        $mapping = [
            Command::FAILURE => 'Command failed.',
            Command::INVALID => 'Command was invalid.',
        ];

        return $mapping[$other] ?? \sprintf('Command returned exit status %d.', $other);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use PHPUnit\Framework\Assert;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful;

/**
 * @author Amrouche Hamza <hamza.simperfit@gmail.com>
 */
trait TesterTrait
{
    private StreamOutput $output;

    /**
     * @var list<string>
     */
    private array $inputs = [];
    private bool $captureStreamsIndependently = false;
    private InputInterface $input;
    private int $statusCode;

    /**
     * Gets the display returned by the last execution of the command or application.
     *
     * @throws \RuntimeException If it's called before the execute method
     */
    public function getDisplay(bool $normalize = false): string
    {
        if (!isset($this->output)) {
            throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?');
        }

        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(\PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the output written to STDERR by the application.
     *
     * @param bool $normalize Whether to normalize end of lines to \n or not
     */
    public function getErrorOutput(bool $normalize = false): string
    {
        if (!$this->captureStreamsIndependently) {
            throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
        }

        rewind($this->output->getErrorOutput()->getStream());

        $display = stream_get_contents($this->output->getErrorOutput()->getStream());

        if ($normalize) {
            $display = str_replace(\PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the command or application.
     */
    public function getInput(): InputInterface
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the command or application.
     */
    public function getOutput(): OutputInterface
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the command or application.
     *
     * @throws \RuntimeException If it's called before the execute method
     */
    public function getStatusCode(): int
    {
        return $this->statusCode ?? throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?');
    }

    public function assertCommandIsSuccessful(string $message = ''): void
    {
        Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message);
    }

    /**
     * Sets the user inputs.
     *
     * @param list<string> $inputs An array of strings representing each input
     *                             passed to the command input stream
     *
     * @return $this
     */
    public function setInputs(array $inputs): static
    {
        $this->inputs = $inputs;

        return $this;
    }

    /**
     * Initializes the output property.
     *
     * Available options:
     *
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     */
    private function initOutput(array $options): void
    {
        $this->captureStreamsIndependently = $options['capture_stderr_separately'] ?? false;
        if (!$this->captureStreamsIndependently) {
            $this->output = new StreamOutput(fopen('php://memory', 'w', false));
            if (isset($options['decorated'])) {
                $this->output->setDecorated($options['decorated']);
            }
            if (isset($options['verbosity'])) {
                $this->output->setVerbosity($options['verbosity']);
            }
        } else {
            $this->output = new ConsoleOutput(
                $options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL,
                $options['decorated'] ?? null
            );

            $errorOutput = new StreamOutput(fopen('php://memory', 'w', false));
            $errorOutput->setFormatter($this->output->getFormatter());
            $errorOutput->setVerbosity($this->output->getVerbosity());
            $errorOutput->setDecorated($this->output->isDecorated());

            $reflectedOutput = new \ReflectionObject($this->output);
            $strErrProperty = $reflectedOutput->getProperty('stderr');
            $strErrProperty->setValue($this->output, $errorOutput);

            $reflectedParent = $reflectedOutput->getParentClass();
            $streamProperty = $reflectedParent->getProperty('stream');
            $streamProperty->setValue($this->output, fopen('php://memory', 'w', false));
        }
    }

    /**
     * @param list<string> $inputs
     *
     * @return resource
     */
    private static function createStream(array $inputs)
    {
        $stream = fopen('php://memory', 'r+', false);

        foreach ($inputs as $input) {
            fwrite($stream, $input);

            if (!str_ends_with($input, "\x4")) {
                fwrite($stream, \PHP_EOL);
            }
        }

        rewind($stream);

        return $stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;

/**
 * Eases the testing of console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class CommandTester
{
    use TesterTrait;

    private Command $command;

    public function __construct(
        callable|Command $command,
    ) {
        $this->command = $command instanceof Command ? $command : new Command(null, $command);
    }

    /**
     * Executes the command.
     *
     * Available execution options:
     *
     *  * interactive:               Sets the input interactive flag
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     *
     * @param array $input   An array of command arguments and options
     * @param array $options An array of execution options
     *
     * @return int The command exit code
     */
    public function execute(array $input, array $options = []): int
    {
        // set the command name automatically if the application requires
        // this argument and no command name was passed
        if (!isset($input['command'])
            && (null !== $application = $this->command->getApplication())
            && $application->getDefinition()->hasArgument('command')
        ) {
            $input = array_merge(['command' => $this->command->getName()], $input);
        }

        $this->input = new ArrayInput($input);
        // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN.
        $this->input->setStream(self::createStream($this->inputs));

        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        if (!isset($options['decorated'])) {
            $options['decorated'] = false;
        }

        $this->initOutput($options);

        return $this->statusCode = $this->command->run($this->input, $this->output);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;

/**
 * Eases the testing of command completion.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class CommandCompletionTester
{
    public function __construct(
        private Command $command,
    ) {
    }

    /**
     * Create completion suggestions from input tokens.
     */
    public function complete(array $input): array
    {
        $currentIndex = \count($input);
        if ('' === end($input)) {
            array_pop($input);
        }
        array_unshift($input, $this->command->getName());

        $completionInput = CompletionInput::fromTokens($input, $currentIndex);
        $completionInput->bind($this->command->getDefinition());
        $suggestions = new CompletionSuggestions();

        $this->command->complete($completionInput, $suggestions);

        $options = [];
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $options[] = '--'.$option->getName();
        }

        return array_map('strval', array_merge($options, $suggestions->getValueSuggestions()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;

/**
 * Eases the testing of console applications.
 *
 * When testing an application, don't forget to disable the auto exit flag:
 *
 *     $application = new Application();
 *     $application->setAutoExit(false);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApplicationTester
{
    use TesterTrait;

    public function __construct(
        private Application $application,
    ) {
    }

    /**
     * Executes the application.
     *
     * Available options:
     *
     *  * interactive:               Sets the input interactive flag
     *  * decorated:                 Sets the output decorated flag
     *  * verbosity:                 Sets the output verbosity flag
     *  * capture_stderr_separately: Make output of stdOut and stdErr separately available
     *
     * @return int The command exit code
     */
    public function run(array $input, array $options = []): int
    {
        $this->input = new ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        if ($this->inputs) {
            $this->input->setStream(self::createStream($this->inputs));
        }

        $this->initOutput($options);

        // Temporarily clear SHELL_VERBOSITY to prevent Application::configureIO
        // from overriding the interactive and verbosity settings set above
        $prevShellVerbosity = [getenv('SHELL_VERBOSITY'), $_ENV['SHELL_VERBOSITY'] ?? false, $_SERVER['SHELL_VERBOSITY'] ?? false];
        if (\function_exists('putenv')) {
            @putenv('SHELL_VERBOSITY');
        }
        unset($_ENV['SHELL_VERBOSITY'], $_SERVER['SHELL_VERBOSITY']);

        try {
            return $this->statusCode = $this->application->run($this->input, $this->output);
        } finally {
            if (false !== $prevShellVerbosity[0]) {
                if (\function_exists('putenv')) {
                    @putenv('SHELL_VERBOSITY='.$prevShellVerbosity[0]);
                }
            }
            if (false !== $prevShellVerbosity[1]) {
                $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity[1];
            }
            if (false !== $prevShellVerbosity[2]) {
                $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity[2];
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\CompleteCommand;
use Symfony\Component\Console\Command\DumpCompletionCommand;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Event\ConsoleAlarmEvent;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleSignalEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\NamespaceNotFoundException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\ProcessHelper;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputAwareInterface;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SignalRegistry\SignalRegistry;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\ErrorHandler\ErrorHandler;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Service\ResetInterface;

/**
 * An Application is the container for a collection of commands.
 *
 * It is the main entry point of a Console application.
 *
 * This class is optimized for a standard CLI environment.
 *
 * Usage:
 *
 *     $app = new Application('myapp', '1.0 (stable)');
 *     $app->addCommand(new SimpleCommand());
 *     $app->run();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Application implements ResetInterface
{
    private array $commands = [];
    private bool $wantHelps = false;
    private ?Command $runningCommand = null;
    private ?CommandLoaderInterface $commandLoader = null;
    private bool $catchExceptions = true;
    private bool $catchErrors = false;
    private bool $autoExit = true;
    private InputDefinition $definition;
    private HelperSet $helperSet;
    private ?EventDispatcherInterface $dispatcher = null;
    private Terminal $terminal;
    private string $defaultCommand;
    private bool $singleCommand = false;
    private bool $initialized = false;
    private ?SignalRegistry $signalRegistry = null;
    private array $signalsToDispatchEvent = [];
    private ?int $alarmInterval = null;

    public function __construct(
        private string $name = 'UNKNOWN',
        private string $version = 'UNKNOWN',
    ) {
        $this->terminal = new Terminal();
        $this->defaultCommand = 'list';
        if (\defined('SIGINT') && SignalRegistry::isSupported()) {
            $this->signalRegistry = new SignalRegistry();
            $this->signalsToDispatchEvent = [\SIGINT, \SIGQUIT, \SIGTERM, \SIGUSR1, \SIGUSR2, \SIGALRM];
        }
    }

    /**
     * @final
     */
    public function setDispatcher(EventDispatcherInterface $dispatcher): void
    {
        $this->dispatcher = $dispatcher;
    }

    public function setCommandLoader(CommandLoaderInterface $commandLoader): void
    {
        $this->commandLoader = $commandLoader;
    }

    public function getSignalRegistry(): SignalRegistry
    {
        if (!$this->signalRegistry) {
            throw new RuntimeException('Signals are not supported. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
        }

        return $this->signalRegistry;
    }

    public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent): void
    {
        $this->signalsToDispatchEvent = $signalsToDispatchEvent;
    }

    /**
     * Sets the interval to schedule a SIGALRM signal in seconds.
     */
    public function setAlarmInterval(?int $seconds): void
    {
        $this->alarmInterval = $seconds;
        $this->scheduleAlarm();
    }

    /**
     * Gets the interval in seconds on which a SIGALRM signal is dispatched.
     */
    public function getAlarmInterval(): ?int
    {
        return $this->alarmInterval;
    }

    private function scheduleAlarm(): void
    {
        if (null !== $this->alarmInterval) {
            $this->getSignalRegistry()->scheduleAlarm($this->alarmInterval);
        }
    }

    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     *
     * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
     */
    public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
    {
        if (\function_exists('putenv')) {
            @putenv('LINES='.$this->terminal->getHeight());
            @putenv('COLUMNS='.$this->terminal->getWidth());
        }

        $input ??= new ArgvInput();
        $output ??= new ConsoleOutput();

        $renderException = function (\Throwable $e) use ($output) {
            if ($output instanceof ConsoleOutputInterface) {
                $this->renderThrowable($e, $output->getErrorOutput());
            } else {
                $this->renderThrowable($e, $output);
            }
        };
        if ($phpHandler = set_exception_handler($renderException)) {
            restore_exception_handler();
            if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
                $errorHandler = true;
            } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
                $phpHandler[0]->setExceptionHandler($errorHandler);
            }
        }

        $empty = new \stdClass();
        $prevShellVerbosity = [$_ENV['SHELL_VERBOSITY'] ?? $empty, $_SERVER['SHELL_VERBOSITY'] ?? $empty, getenv('SHELL_VERBOSITY')];

        try {
            $this->configureIO($input, $output);

            $exitCode = $this->doRun($input, $output);
        } catch (\Throwable $e) {
            if ($e instanceof \Exception && !$this->catchExceptions) {
                throw $e;
            }
            if (!$e instanceof \Exception && !$this->catchErrors) {
                throw $e;
            }

            $renderException($e);

            $exitCode = $e->getCode();
            if (is_numeric($exitCode)) {
                $exitCode = (int) $exitCode;
                if ($exitCode <= 0) {
                    $exitCode = 1;
                }
            } else {
                $exitCode = 1;
            }
        } finally {
            // if the exception handler changed, keep it
            // otherwise, unregister $renderException
            if (!$phpHandler) {
                if (set_exception_handler($renderException) === $renderException) {
                    restore_exception_handler();
                }
                restore_exception_handler();
            } elseif (!$errorHandler) {
                $finalHandler = $phpHandler[0]->setExceptionHandler(null);
                if ($finalHandler !== $renderException) {
                    $phpHandler[0]->setExceptionHandler($finalHandler);
                }
            }

            // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it
            // to its previous value to avoid one command verbosity to spread to other commands
            if ($empty === $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity[0]) {
                unset($_ENV['SHELL_VERBOSITY']);
            }
            if ($empty === $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity[1]) {
                unset($_SERVER['SHELL_VERBOSITY']);
            }
            if (\function_exists('putenv')) {
                @putenv('SHELL_VERBOSITY'.(false === ($prevShellVerbosity[2] ?? false) ? '' : '='.$prevShellVerbosity[2]));
            }
        }

        if ($this->autoExit) {
            if ($exitCode > 255) {
                $exitCode = 255;
            }

            exit($exitCode);
        }

        return $exitCode;
    }

    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     */
    public function doRun(InputInterface $input, OutputInterface $output): int
    {
        if (true === $input->hasParameterOption(['--version', '-V'], true)) {
            $output->writeln($this->getLongVersion());

            return 0;
        }

        try {
            // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface) {
            // Errors must be ignored, full binding/validation happens later when the command is known.
        }

        $name = $this->getCommandName($input);
        if (true === $input->hasParameterOption(['--help', '-h'], true)) {
            if (!$name) {
                $name = 'help';
                $input = new ArrayInput(['command_name' => $this->defaultCommand]);
            } else {
                $this->wantHelps = true;
            }
        }

        if (!$name) {
            $name = $this->defaultCommand;
            $definition = $this->getDefinition();
            $definition->setArguments(array_merge(
                $definition->getArguments(),
                [
                    'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
                ]
            ));
        }

        try {
            $this->runningCommand = null;
            // the command name MUST be the first element of the input
            $command = $this->find($name);
        } catch (\Throwable $e) {
            if (($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) && 1 === \count($alternatives = $e->getAlternatives()) && $input->isInteractive()) {
                $alternative = $alternatives[0];

                $style = new SymfonyStyle($input, $output);
                $output->writeln('');
                $formattedBlock = (new FormatterHelper())->formatBlock(\sprintf('Command "%s" is not defined.', $name), 'error', true);
                $output->writeln($formattedBlock);
                if (!$style->confirm(\sprintf('Do you want to run "%s" instead? ', $alternative), false)) {
                    if (null !== $this->dispatcher) {
                        $event = new ConsoleErrorEvent($input, $output, $e);
                        $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);

                        return $event->getExitCode();
                    }

                    return 1;
                }

                $command = $this->find($alternative);
            } else {
                if (null !== $this->dispatcher) {
                    $event = new ConsoleErrorEvent($input, $output, $e);
                    $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);

                    if (0 === $event->getExitCode()) {
                        return 0;
                    }

                    $e = $event->getError();
                }

                try {
                    if ($e instanceof CommandNotFoundException && $namespace = $this->findNamespace($name)) {
                        $helper = new DescriptorHelper();
                        $helper->describe($output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output, $this, [
                            'format' => 'txt',
                            'raw_text' => false,
                            'namespace' => $namespace,
                            'short' => false,
                        ]);

                        return isset($event) ? $event->getExitCode() : 1;
                    }

                    throw $e;
                } catch (NamespaceNotFoundException) {
                    throw $e;
                }
            }
        }

        if ($command instanceof LazyCommand) {
            $command = $command->getCommand();
        }

        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;

        return $exitCode;
    }

    public function reset(): void
    {
    }

    public function setHelperSet(HelperSet $helperSet): void
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Get the helper set associated with the command.
     */
    public function getHelperSet(): HelperSet
    {
        return $this->helperSet ??= $this->getDefaultHelperSet();
    }

    public function setDefinition(InputDefinition $definition): void
    {
        $this->definition = $definition;
    }

    /**
     * Gets the InputDefinition related to this Application.
     */
    public function getDefinition(): InputDefinition
    {
        $this->definition ??= $this->getDefaultInputDefinition();

        if ($this->singleCommand) {
            $this->definition->setArguments();
        }

        return $this->definition;
    }

    /**
     * Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        if (
            CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType()
            && 'command' === $input->getCompletionName()
        ) {
            foreach ($this->all() as $name => $command) {
                // skip hidden commands and aliased commands as they already get added below
                if ($command->isHidden() || $command->getName() !== $name) {
                    continue;
                }
                $suggestions->suggestValue(new Suggestion($command->getName(), $command->getDescription()));
                foreach ($command->getAliases() as $name) {
                    $suggestions->suggestValue(new Suggestion($name, $command->getDescription()));
                }
            }

            return;
        }

        if (CompletionInput::TYPE_OPTION_NAME === $input->getCompletionType()) {
            $suggestions->suggestOptions($this->getDefinition()->getOptions());
        }

        if (
            CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType()
            && ($definition = $this->getDefinition())->hasOption($input->getCompletionName())
        ) {
            $definition->getOption($input->getCompletionName())->complete($input, $suggestions);

            return;
        }
    }

    /**
     * Gets the help message.
     */
    public function getHelp(): string
    {
        return $this->getLongVersion();
    }

    /**
     * Gets whether to catch exceptions or not during commands execution.
     */
    public function areExceptionsCaught(): bool
    {
        return $this->catchExceptions;
    }

    /**
     * Sets whether to catch exceptions or not during commands execution.
     */
    public function setCatchExceptions(bool $boolean): void
    {
        $this->catchExceptions = $boolean;
    }

    /**
     * Sets whether to catch errors or not during commands execution.
     */
    public function setCatchErrors(bool $catchErrors = true): void
    {
        $this->catchErrors = $catchErrors;
    }

    /**
     * Gets whether to automatically exit after a command execution or not.
     */
    public function isAutoExitEnabled(): bool
    {
        return $this->autoExit;
    }

    /**
     * Sets whether to automatically exit after a command execution or not.
     */
    public function setAutoExit(bool $boolean): void
    {
        $this->autoExit = $boolean;
    }

    /**
     * Gets the name of the application.
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Sets the application name.
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }

    /**
     * Gets the application version.
     */
    public function getVersion(): string
    {
        return $this->version;
    }

    /**
     * Sets the application version.
     */
    public function setVersion(string $version): void
    {
        $this->version = $version;
    }

    /**
     * Returns the long version of the application.
     */
    public function getLongVersion(): string
    {
        if ('UNKNOWN' !== $this->getName()) {
            if ('UNKNOWN' !== $this->getVersion()) {
                return \sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion());
            }

            return $this->getName();
        }

        return 'Console Tool';
    }

    /**
     * Registers a new command.
     */
    public function register(string $name): Command
    {
        return $this->addCommand(new Command($name));
    }

    /**
     * Adds an array of command objects.
     *
     * If a Command is not enabled it will not be added.
     *
     * @param callable[]|Command[] $commands An array of commands
     */
    public function addCommands(array $commands): void
    {
        foreach ($commands as $command) {
            $this->addCommand($command);
        }
    }

    /**
     * @deprecated since Symfony 7.4, use Application::addCommand() instead
     */
    public function add(Command $command): ?Command
    {
        trigger_deprecation('symfony/console', '7.4', 'The "%s()" method is deprecated and will be removed in Symfony 8.0, use "%s::addCommand()" instead.', __METHOD__, self::class);

        return $this->addCommand($command);
    }

    /**
     * Adds a command object.
     *
     * If a command with the same name already exists, it will be overridden.
     * If the command is not enabled it will not be added.
     */
    public function addCommand(callable|Command $command): ?Command
    {
        $this->init();

        if (!$command instanceof Command) {
            $command = new Command(null, $command);
        }

        $command->setApplication($this);

        if (!$command->isEnabled()) {
            $command->setApplication(null);

            return null;
        }

        if (!$command instanceof LazyCommand) {
            // Will throw if the command is not correctly initialized.
            $command->getDefinition();
        }

        if (!$command->getName()) {
            throw new LogicException(\sprintf('The command defined in "%s" cannot have an empty name.', get_debug_type($command)));
        }

        $this->commands[$command->getName()] = $command;

        foreach ($command->getAliases() as $alias) {
            $this->commands[$alias] = $command;
        }

        return $command;
    }

    /**
     * Returns a registered command by name or alias.
     *
     * @throws CommandNotFoundException When given command name does not exist
     */
    public function get(string $name): Command
    {
        $this->init();

        if (!$this->has($name)) {
            throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name));
        }

        // When the command has a different name than the one used at the command loader level
        if (!isset($this->commands[$name])) {
            throw new CommandNotFoundException(\sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name));
        }

        $command = $this->commands[$name];

        if ($this->wantHelps) {
            $this->wantHelps = false;

            $helpCommand = $this->get('help');
            $helpCommand->setCommand($command);

            return $helpCommand;
        }

        return $command;
    }

    /**
     * Returns true if the command exists, false otherwise.
     */
    public function has(string $name): bool
    {
        $this->init();

        return isset($this->commands[$name]) || ($this->commandLoader?->has($name) && $this->addCommand($this->commandLoader->get($name)));
    }

    /**
     * Returns an array of all unique namespaces used by currently registered commands.
     *
     * It does not return the global namespace which always exists.
     *
     * @return string[]
     */
    public function getNamespaces(): array
    {
        $namespaces = [];
        foreach ($this->all() as $command) {
            if ($command->isHidden()) {
                continue;
            }

            $namespaces[] = $this->extractAllNamespaces($command->getName());

            foreach ($command->getAliases() as $alias) {
                $namespaces[] = $this->extractAllNamespaces($alias);
            }
        }

        return array_values(array_unique(array_filter(array_merge([], ...$namespaces))));
    }

    /**
     * Finds a registered namespace by a name or an abbreviation.
     *
     * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous
     */
    public function findNamespace(string $namespace): string
    {
        $allNamespaces = $this->getNamespaces();
        $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $namespace))).'[^:]*';
        $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);

        if (!$namespaces) {
            $message = \sprintf('There are no commands defined in the "%s" namespace.', $namespace);

            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
                if (1 == \count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }

                $message .= implode("\n    ", $alternatives);
            }

            throw new NamespaceNotFoundException($message, $alternatives);
        }

        $exact = \in_array($namespace, $namespaces, true);
        if (\count($namespaces) > 1 && !$exact) {
            throw new NamespaceNotFoundException(\sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
        }

        return $exact ? $namespace : reset($namespaces);
    }

    /**
     * Finds a command by name or alias.
     *
     * Contrary to get, this command tries to find the best
     * match if you give it an abbreviation of a name or alias.
     *
     * @throws CommandNotFoundException When command name is incorrect or ambiguous
     */
    public function find(string $name): Command
    {
        $this->init();

        $aliases = [];

        foreach ($this->commands as $command) {
            foreach ($command->getAliases() as $alias) {
                if (!$this->has($alias)) {
                    $this->commands[$alias] = $command;
                }
            }
        }

        if ($this->has($name)) {
            return $this->get($name);
        }

        $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
        $expr = implode('[^:]*:', array_map('preg_quote', explode(':', $name))).'[^:]*';
        $commands = preg_grep('{^'.$expr.'}', $allCommands);

        if (!$commands) {
            $commands = preg_grep('{^'.$expr.'}i', $allCommands);
        }

        // if no commands matched or we just matched namespaces
        if (!$commands || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) {
            if (false !== $pos = strrpos($name, ':')) {
                // check if a namespace exists and contains commands
                $this->findNamespace(substr($name, 0, $pos));
            }

            $message = \sprintf('Command "%s" is not defined.', $name);

            if ($alternatives = $this->findAlternatives($name, $allCommands)) {
                $wantHelps = $this->wantHelps;
                $this->wantHelps = false;

                // remove hidden commands
                if ($alternatives = array_filter($alternatives, fn ($name) => !$this->get($name)->isHidden())) {
                    $message .= \sprintf("\n\nDid you mean %s?\n    %s", 1 === \count($alternatives) ? 'this' : 'one of these', implode("\n    ", $alternatives));
                }
                $this->wantHelps = $wantHelps;
            }

            throw new CommandNotFoundException($message, array_values($alternatives));
        }

        // filter out aliases for commands which are already on the list
        if (\count($commands) > 1) {
            $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
            $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) {
                if (!$commandList[$nameOrAlias] instanceof Command) {
                    $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
                }

                $commandName = $commandList[$nameOrAlias]->getName();

                $aliases[$nameOrAlias] = $commandName;

                return $commandName === $nameOrAlias || !\in_array($commandName, $commands, true);
            }));
        }

        // check whether all commands left are aliases to the same one
        if (\count($commands) > 1) {
            $uniqueCommands = array_unique(array_map(function ($nameOrAlias) use (&$commandList) {
                if (!$commandList[$nameOrAlias] instanceof Command) {
                    $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
                }

                return $commandList[$nameOrAlias]->getName();
            }, $commands));

            if (1 === \count($uniqueCommands)) {
                $commands = [reset($uniqueCommands)];
            }
        }

        if (\count($commands) > 1) {
            $usableWidth = $this->terminal->getWidth() - 10;
            $abbrevs = array_values($commands);
            $maxLen = 0;
            foreach ($abbrevs as $abbrev) {
                $maxLen = max(Helper::width($abbrev), $maxLen);
            }
            $abbrevs = array_map(static function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) {
                if ($commandList[$cmd]->isHidden()) {
                    unset($commands[array_search($cmd, $commands)]);

                    return false;
                }

                $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription();

                return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev;
            }, array_values($commands));

            if (\count($commands) > 1) {
                $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs));

                throw new CommandNotFoundException(\sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands));
            }
        }

        $command = $commands ? $this->get(reset($commands)) : null;

        if (!$command || $command->isHidden()) {
            throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name));
        }

        return $command;
    }

    /**
     * Gets the commands (registered in the given namespace if provided).
     *
     * The array keys are the full names and the values the command instances.
     *
     * @return Command[]
     */
    public function all(?string $namespace = null): array
    {
        $this->init();

        if (null === $namespace) {
            if (!$this->commandLoader) {
                return $this->commands;
            }

            $commands = $this->commands;
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }

            return $commands;
        }

        $commands = [];
        foreach ($this->commands as $name => $command) {
            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
                $commands[$name] = $command;
            }
        }

        if ($this->commandLoader) {
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }
        }

        return $commands;
    }

    /**
     * Returns an array of possible abbreviations given a set of names.
     *
     * @return string[][]
     */
    public static function getAbbreviations(array $names): array
    {
        $abbrevs = [];
        foreach ($names as $name) {
            for ($len = \strlen($name); $len > 0; --$len) {
                $abbrev = substr($name, 0, $len);
                $abbrevs[$abbrev][] = $name;
            }
        }

        return $abbrevs;
    }

    public function renderThrowable(\Throwable $e, OutputInterface $output): void
    {
        $output->writeln('', OutputInterface::VERBOSITY_QUIET);

        $this->doRenderThrowable($e, $output);

        if (null !== $this->runningCommand) {
            $output->writeln(\sprintf('<info>%s</info>', OutputFormatter::escape(\sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET);
            $output->writeln('', OutputInterface::VERBOSITY_QUIET);
        }
    }

    protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void
    {
        do {
            $message = trim($e->getMessage());
            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $class = get_debug_type($e);
                $title = \sprintf('  [%s%s]  ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '');
                $len = Helper::width($title);
            } else {
                $len = 0;
            }

            if (str_contains($message, "@anonymous\0")) {
                $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', static fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message);
            }

            $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX;
            $lines = [];
            foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) {
                foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
                    // pre-format lines to get the right string length
                    $lineLength = Helper::width($line) + 4;
                    $lines[] = [$line, $lineLength];

                    $len = max($lineLength, $len);
                }
            }

            $messages = [];
            if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = \sprintf('<comment>%s</comment>', OutputFormatter::escape(\sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
            }
            $messages[] = $emptyLine = \sprintf('<error>%s</error>', str_repeat(' ', $len));
            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = \sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::width($title))));
            }
            foreach ($lines as $line) {
                $messages[] = \sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
            }
            $messages[] = $emptyLine;
            $messages[] = '';

            $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);

            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);

                // exception related properties
                $trace = $e->getTrace();

                array_unshift($trace, [
                    'function' => '',
                    'file' => $e->getFile() ?: 'n/a',
                    'line' => $e->getLine() ?: 'n/a',
                    'args' => [],
                ]);

                for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
                    $class = $trace[$i]['class'] ?? '';
                    $type = $trace[$i]['type'] ?? '';
                    $function = $trace[$i]['function'] ?? '';
                    $file = $trace[$i]['file'] ?? 'n/a';
                    $line = $trace[$i]['line'] ?? 'n/a';

                    $output->writeln(\sprintf(' %s%s at <info>%s:%s</info>', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET);
                }

                $output->writeln('', OutputInterface::VERBOSITY_QUIET);
            }
        } while ($e = $e->getPrevious());
    }

    /**
     * Configures the input and output instances based on the user arguments and options.
     */
    protected function configureIO(InputInterface $input, OutputInterface $output): void
    {
        if ($input->hasParameterOption(['--ansi'], true)) {
            $output->setDecorated(true);
        } elseif ($input->hasParameterOption(['--no-ansi'], true)) {
            $output->setDecorated(false);
        }

        $shellVerbosity = match (true) {
            $input->hasParameterOption(['--silent'], true) => -2,
            $input->hasParameterOption(['--quiet', '-q'], true) => -1,
            $input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true) => 3,
            $input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true) => 2,
            $input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true) => 1,
            default => (int) ($_ENV['SHELL_VERBOSITY'] ?? $_SERVER['SHELL_VERBOSITY'] ?? getenv('SHELL_VERBOSITY')),
        };

        $output->setVerbosity(match ($shellVerbosity) {
            -2 => OutputInterface::VERBOSITY_SILENT,
            -1 => OutputInterface::VERBOSITY_QUIET,
            1 => OutputInterface::VERBOSITY_VERBOSE,
            2 => OutputInterface::VERBOSITY_VERY_VERBOSE,
            3 => OutputInterface::VERBOSITY_DEBUG,
            default => ($shellVerbosity = 0) ?: $output->getVerbosity(),
        });

        if (0 > $shellVerbosity || $input->hasParameterOption(['--no-interaction', '-n'], true)) {
            $input->setInteractive(false);
        }

        if (\function_exists('putenv')) {
            @putenv('SHELL_VERBOSITY='.$shellVerbosity);
        }
        $_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
        $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
    }

    /**
     * Runs the current command.
     *
     * If an event dispatcher has been attached to the application,
     * events are also dispatched during the life-cycle of the command.
     *
     * @return int 0 if everything went fine, or an error code
     */
    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output): int
    {
        foreach ($command->getHelperSet() as $helper) {
            if ($helper instanceof InputAwareInterface) {
                $helper->setInput($input);
            }
        }

        $registeredSignals = false;
        if (($commandSignals = $command->getSubscribedSignals()) || $this->dispatcher && $this->signalsToDispatchEvent) {
            $signalRegistry = $this->getSignalRegistry();

            $registeredSignals = true;
            $this->getSignalRegistry()->pushCurrentHandlers();

            if ($this->dispatcher) {
                // We register application signals, so that we can dispatch the event
                foreach ($this->signalsToDispatchEvent as $signal) {
                    $signalEvent = new ConsoleSignalEvent($command, $input, $output, $signal);
                    $alarmEvent = \SIGALRM === $signal ? new ConsoleAlarmEvent($command, $input, $output) : null;

                    $signalRegistry->register($signal, function ($signal) use ($signalEvent, $alarmEvent, $command, $commandSignals, $input, $output) {
                        $this->dispatcher->dispatch($signalEvent, ConsoleEvents::SIGNAL);
                        $exitCode = $signalEvent->getExitCode();

                        if (null !== $alarmEvent) {
                            if (false !== $exitCode) {
                                $alarmEvent->setExitCode($exitCode);
                            } else {
                                $alarmEvent->abortExit();
                            }
                            $this->dispatcher->dispatch($alarmEvent);
                            $exitCode = $alarmEvent->getExitCode();
                        }

                        // If the command is signalable, we call the handleSignal() method
                        if (\in_array($signal, $commandSignals, true)) {
                            $exitCode = $command->handleSignal($signal, $exitCode);
                        }

                        if (\SIGALRM === $signal) {
                            $this->scheduleAlarm();
                        }

                        if (false !== $exitCode) {
                            $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode, $signal);
                            $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);

                            exit($event->getExitCode());
                        }
                    });
                }

                // then we register command signals, but not if already handled after the dispatcher
                $commandSignals = array_diff($commandSignals, $this->signalsToDispatchEvent);
            }

            foreach ($commandSignals as $signal) {
                $signalRegistry->register($signal, function (int $signal) use ($command): void {
                    if (\SIGALRM === $signal) {
                        $this->scheduleAlarm();
                    }

                    if (false !== $exitCode = $command->handleSignal($signal)) {
                        exit($exitCode);
                    }
                });
            }
        }

        if (null === $this->dispatcher) {
            try {
                return $command->run($input, $output);
            } finally {
                if ($registeredSignals) {
                    $this->getSignalRegistry()->popPreviousHandlers();
                }
            }
        }

        // bind before the console.command event, so the listeners have access to input options/arguments
        try {
            $command->mergeApplicationDefinition();
            $input->bind($command->getDefinition());
        } catch (ExceptionInterface) {
            // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
        }

        $event = new ConsoleCommandEvent($command, $input, $output);
        $e = null;

        try {
            $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND);

            if ($event->commandShouldRun()) {
                $exitCode = $command->run($input, $output);
            } else {
                $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
            }
        } catch (\Throwable $e) {
            $event = new ConsoleErrorEvent($input, $output, $e, $command);
            $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
            $e = $event->getError();

            if (0 === $exitCode = $event->getExitCode()) {
                $e = null;
            }
        } finally {
            if ($registeredSignals) {
                $this->getSignalRegistry()->popPreviousHandlers();
            }
        }

        $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
        $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);

        if (null !== $e) {
            throw $e;
        }

        return $event->getExitCode();
    }

    /**
     * Gets the name of the command based on input.
     */
    protected function getCommandName(InputInterface $input): ?string
    {
        return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument();
    }

    /**
     * Gets the default input definition.
     */
    protected function getDefaultInputDefinition(): InputDefinition
    {
        return new InputDefinition([
            new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
            new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the <info>'.$this->defaultCommand.'</info> command'),
            new InputOption('--silent', null, InputOption::VALUE_NONE, 'Do not output any message'),
            new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Only errors are displayed. All other output is suppressed'),
            new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
            new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
            new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null),
            new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
        ]);
    }

    /**
     * Gets the default commands that should always be available.
     *
     * @return Command[]
     */
    protected function getDefaultCommands(): array
    {
        return [new HelpCommand(), new ListCommand(), new CompleteCommand(), new DumpCompletionCommand()];
    }

    /**
     * Gets the default helper set with the helpers that should always be available.
     */
    protected function getDefaultHelperSet(): HelperSet
    {
        return new HelperSet([
            new FormatterHelper(),
            new DebugFormatterHelper(),
            new ProcessHelper(),
            new QuestionHelper(),
        ]);
    }

    /**
     * Returns abbreviated suggestions in string format.
     */
    private function getAbbreviationSuggestions(array $abbrevs): string
    {
        return '    '.implode("\n    ", $abbrevs);
    }

    /**
     * Returns the namespace part of the command name.
     *
     * This method is not part of public API and should not be used directly.
     */
    public function extractNamespace(string $name, ?int $limit = null): string
    {
        $parts = explode(':', $name, -1);

        return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
    }

    /**
     * Finds alternative of $name among $collection,
     * if nothing is found in $collection, try in $abbrevs.
     *
     * @return string[]
     */
    private function findAlternatives(string $name, iterable $collection): array
    {
        $threshold = 1e3;
        $alternatives = [];

        $collectionParts = [];
        foreach ($collection as $item) {
            $collectionParts[$item] = explode(':', $item);
        }

        foreach (explode(':', $name) as $i => $subname) {
            foreach ($collectionParts as $collectionName => $parts) {
                $exists = isset($alternatives[$collectionName]);
                if (!isset($parts[$i]) && $exists) {
                    $alternatives[$collectionName] += $threshold;
                    continue;
                } elseif (!isset($parts[$i])) {
                    continue;
                }

                $lev = levenshtein($subname, $parts[$i]);
                if ($lev <= \strlen($subname) / 3 || '' !== $subname && str_contains($parts[$i], $subname)) {
                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
                } elseif ($exists) {
                    $alternatives[$collectionName] += $threshold;
                }
            }
        }

        foreach ($collection as $item) {
            $lev = levenshtein($name, $item);
            if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) {
                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
            }
        }

        $alternatives = array_filter($alternatives, static fn ($lev) => $lev < 2 * $threshold);
        ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE);

        return array_keys($alternatives);
    }

    /**
     * Sets the default Command name.
     *
     * @return $this
     */
    public function setDefaultCommand(string $commandName, bool $isSingleCommand = false): static
    {
        $this->defaultCommand = explode('|', ltrim($commandName, '|'))[0];

        if ($isSingleCommand) {
            // Ensure the command exist
            $this->find($commandName);

            $this->singleCommand = true;
        }

        return $this;
    }

    /**
     * @internal
     */
    public function isSingleCommand(): bool
    {
        return $this->singleCommand;
    }

    private function splitStringByWidth(string $string, int $width): array
    {
        // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
        // additionally, array_slice() is not enough as some character has doubled width.
        // we need a function to split string not by character count but by string width
        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return str_split($string, $width);
        }

        $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
        $lines = [];
        $line = '';

        $offset = 0;
        while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) {
            $offset += \strlen($m[0]);

            foreach (preg_split('//u', $m[0]) as $char) {
                // test if $char could be appended to current line
                if (Helper::width($line.$char) <= $width) {
                    $line .= $char;
                    continue;
                }
                // if not, push current line to array and make new line
                $lines[] = str_pad($line, $width);
                $line = $char;
            }
        }

        $lines[] = \count($lines) ? str_pad($line, $width) : $line;

        mb_convert_variables($encoding, 'utf8', $lines);

        return $lines;
    }

    /**
     * Returns all namespaces of the command name.
     *
     * @return string[]
     */
    private function extractAllNamespaces(string $name): array
    {
        // -1 as third argument is needed to skip the command short name when exploding
        $parts = explode(':', $name, -1);
        $namespaces = [];

        foreach ($parts as $part) {
            if (\count($namespaces)) {
                $namespaces[] = end($namespaces).':'.$part;
            } else {
                $namespaces[] = $part;
            }
        }

        return $namespaces;
    }

    private function init(): void
    {
        if ($this->initialized) {
            return;
        }
        $this->initialized = true;

        if ((new \ReflectionMethod($this, 'add'))->getDeclaringClass()->getName() !== (new \ReflectionMethod($this, 'addCommand'))->getDeclaringClass()->getName()) {
            $adder = $this->add(...);
        } else {
            $adder = $this->addCommand(...);
        }

        foreach ($this->getDefaultCommands() as $command) {
            $adder($command);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Interaction;

use Symfony\Component\Console\Attribute\InteractiveAttributeInterface;
use Symfony\Component\Console\Attribute\MapInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @internal
 */
final class Interaction
{
    public function __construct(
        private readonly object $owner,
        private readonly InteractiveAttributeInterface $attribute,
    ) {
    }

    /**
     * @param \Closure(\ReflectionFunction $function, InputInterface $input, OutputInterface $output): array $parameterResolver
     */
    public function interact(InputInterface $input, OutputInterface $output, \Closure $parameterResolver): void
    {
        if ($this->owner instanceof MapInput) {
            $function = $this->attribute->getFunction($this->owner->resolveValue($input));
            $function->invoke(...$parameterResolver($function, $input, $output));
            $this->owner->setValue($input, $function->getClosureThis());

            return;
        }

        $function = $this->attribute->getFunction($this->owner);
        $function->invoke(...$args = $parameterResolver($function, $input, $output));
        foreach ($function->getParameters() as $i => $parameter) {
            if (\is_object($args[$i]) && $spec = MapInput::tryFrom($parameter)) {
                $spec->setValue($input, $args[$i]);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\CommandLoader;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;

/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface CommandLoaderInterface
{
    /**
     * Loads a command.
     *
     * @throws CommandNotFoundException
     */
    public function get(string $name): Command;

    /**
     * Checks if a command exists.
     */
    public function has(string $name): bool;

    /**
     * @return string[]
     */
    public function getNames(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\CommandLoader;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;

/**
 * A simple command loader using factories to instantiate commands lazily.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class FactoryCommandLoader implements CommandLoaderInterface
{
    /**
     * @param callable[] $factories Indexed by command names
     */
    public function __construct(
        private array $factories,
    ) {
    }

    public function has(string $name): bool
    {
        return isset($this->factories[$name]);
    }

    public function get(string $name): Command
    {
        if (!isset($this->factories[$name])) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }

        $factory = $this->factories[$name];

        return $factory();
    }

    public function getNames(): array
    {
        return array_keys($this->factories);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\CommandLoader;

use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;

/**
 * Loads commands from a PSR-11 container.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ContainerCommandLoader implements CommandLoaderInterface
{
    /**
     * @param array $commandMap An array with command names as keys and service ids as values
     */
    public function __construct(
        private ContainerInterface $container,
        private array $commandMap,
    ) {
    }

    public function get(string $name): Command
    {
        if (!$this->has($name)) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }

        return $this->container->get($this->commandMap[$name]);
    }

    public function has(string $name): bool
    {
        return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
    }

    public function getNames(): array
    {
        return array_keys($this->commandMap);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter style interface for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterStyleInterface
{
    /**
     * Sets style foreground color.
     */
    public function setForeground(?string $color): void;

    /**
     * Sets style background color.
     */
    public function setBackground(?string $color): void;

    /**
     * Sets some specific style option.
     */
    public function setOption(string $option): void;

    /**
     * Unsets some specific style option.
     */
    public function unsetOption(string $option): void;

    /**
     * Sets multiple style options at once.
     */
    public function setOptions(array $options): void;

    /**
     * Applies the style to a given text.
     */
    public function apply(string $text): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Contracts\Service\ResetInterface;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OutputFormatterStyleStack implements ResetInterface
{
    /**
     * @var OutputFormatterStyleInterface[]
     */
    private array $styles = [];

    private OutputFormatterStyleInterface $emptyStyle;

    public function __construct(?OutputFormatterStyleInterface $emptyStyle = null)
    {
        $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle();
        $this->reset();
    }

    /**
     * Resets stack (ie. empty internal arrays).
     */
    public function reset(): void
    {
        $this->styles = [];
    }

    /**
     * Pushes a style in the stack.
     */
    public function push(OutputFormatterStyleInterface $style): void
    {
        $this->styles[] = $style;
    }

    /**
     * Pops a style from the stack.
     *
     * @throws InvalidArgumentException When style tags incorrectly nested
     */
    public function pop(?OutputFormatterStyleInterface $style = null): OutputFormatterStyleInterface
    {
        if (!$this->styles) {
            return $this->emptyStyle;
        }

        if (null === $style) {
            return array_pop($this->styles);
        }

        foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
            if ($style->apply('') === $stackedStyle->apply('')) {
                $this->styles = \array_slice($this->styles, 0, $index);

                return $stackedStyle;
            }
        }

        throw new InvalidArgumentException('Incorrectly nested style tag found.');
    }

    /**
     * Computes current style with stacks top codes.
     */
    public function getCurrent(): OutputFormatterStyleInterface
    {
        if (!$this->styles) {
            return $this->emptyStyle;
        }

        return $this->styles[\count($this->styles) - 1];
    }

    /**
     * @return $this
     */
    public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle): static
    {
        $this->emptyStyle = $emptyStyle;

        return $this;
    }

    public function getEmptyStyle(): OutputFormatterStyleInterface
    {
        return $this->emptyStyle;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
 */
final class NullOutputFormatter implements OutputFormatterInterface
{
    private NullOutputFormatterStyle $style;

    public function format(?string $message): ?string
    {
        return null;
    }

    public function getStyle(string $name): OutputFormatterStyleInterface
    {
        // to comply with the interface we must return a OutputFormatterStyleInterface
        return $this->style ??= new NullOutputFormatterStyle();
    }

    public function hasStyle(string $name): bool
    {
        return false;
    }

    public function isDecorated(): bool
    {
        return false;
    }

    public function setDecorated(bool $decorated): void
    {
        // do nothing
    }

    public function setStyle(string $name, OutputFormatterStyleInterface $style): void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
 */
final class NullOutputFormatterStyle implements OutputFormatterStyleInterface
{
    public function apply(string $text): string
    {
        return $text;
    }

    public function setBackground(?string $color): void
    {
        // do nothing
    }

    public function setForeground(?string $color): void
    {
        // do nothing
    }

    public function setOption(string $option): void
    {
        // do nothing
    }

    public function setOptions(array $options): void
    {
        // do nothing
    }

    public function unsetOption(string $option): void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output that supports word wrapping.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
interface WrappableOutputFormatterInterface extends OutputFormatterInterface
{
    /**
     * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping).
     */
    public function formatAndWrap(?string $message, int $width): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

use Symfony\Component\Console\Color;

/**
 * Formatter style class for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
    private Color $color;
    private string $foreground;
    private string $background;
    private array $options;
    private ?string $href = null;
    private bool $handlesHrefGracefully;

    /**
     * Initializes output formatter style.
     *
     * @param string|null $foreground The style foreground color name
     * @param string|null $background The style background color name
     */
    public function __construct(?string $foreground = null, ?string $background = null, array $options = [])
    {
        $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options);
    }

    public function setForeground(?string $color): void
    {
        $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options);
    }

    public function setBackground(?string $color): void
    {
        $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options);
    }

    public function setHref(string $url): void
    {
        $this->href = $url;
    }

    public function setOption(string $option): void
    {
        $this->options[] = $option;
        $this->color = new Color($this->foreground, $this->background, $this->options);
    }

    public function unsetOption(string $option): void
    {
        $pos = array_search($option, $this->options);
        if (false !== $pos) {
            unset($this->options[$pos]);
        }

        $this->color = new Color($this->foreground, $this->background, $this->options);
    }

    public function setOptions(array $options): void
    {
        $this->color = new Color($this->foreground, $this->background, $this->options = $options);
    }

    public function apply(string $text): string
    {
        $this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR')
            && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100)
            && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']);

        if (null !== $this->href && $this->handlesHrefGracefully) {
            $text = "\033]8;;$this->href\033\\$text\033]8;;\033\\";
        }

        return $this->color->apply($text);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterInterface
{
    /**
     * Sets the decorated flag.
     */
    public function setDecorated(bool $decorated): void;

    /**
     * Whether the output will decorate messages.
     */
    public function isDecorated(): bool;

    /**
     * Sets a new style.
     */
    public function setStyle(string $name, OutputFormatterStyleInterface $style): void;

    /**
     * Checks if output formatter has style with specified name.
     */
    public function hasStyle(string $name): bool;

    /**
     * Gets style options from style with specified name.
     *
     * @throws \InvalidArgumentException When style isn't defined
     */
    public function getStyle(string $name): OutputFormatterStyleInterface;

    /**
     * Formats a message according to the given styles.
     */
    public function format(?string $message): ?string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Helper\Helper;

use function Symfony\Component\String\b;

/**
 * Formatter class for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
class OutputFormatter implements WrappableOutputFormatterInterface
{
    private array $styles = [];
    private OutputFormatterStyleStack $styleStack;

    public function __clone()
    {
        $this->styleStack = clone $this->styleStack;
        foreach ($this->styles as $key => $value) {
            $this->styles[$key] = clone $value;
        }
    }

    /**
     * Escapes "<" and ">" special chars in given text.
     */
    public static function escape(string $text): string
    {
        $text = preg_replace('/([^\\\\]|^)([<>])/', '$1\\\\$2', $text);

        return self::escapeTrailingBackslash($text);
    }

    /**
     * Escapes trailing "\" in given text.
     *
     * @internal
     */
    public static function escapeTrailingBackslash(string $text): string
    {
        if (str_ends_with($text, '\\')) {
            $len = \strlen($text);
            $text = rtrim($text, '\\');
            $text = str_replace("\0", '', $text);
            $text .= str_repeat("\0", $len - \strlen($text));
        }

        return $text;
    }

    /**
     * Initializes console output formatter.
     *
     * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
     */
    public function __construct(
        private bool $decorated = false,
        array $styles = [],
    ) {
        $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
        $this->setStyle('info', new OutputFormatterStyle('green'));
        $this->setStyle('comment', new OutputFormatterStyle('yellow'));
        $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));

        foreach ($styles as $name => $style) {
            $this->setStyle($name, $style);
        }

        $this->styleStack = new OutputFormatterStyleStack();
    }

    public function setDecorated(bool $decorated): void
    {
        $this->decorated = $decorated;
    }

    public function isDecorated(): bool
    {
        return $this->decorated;
    }

    public function setStyle(string $name, OutputFormatterStyleInterface $style): void
    {
        $this->styles[strtolower($name)] = $style;
    }

    public function hasStyle(string $name): bool
    {
        return isset($this->styles[strtolower($name)]);
    }

    public function getStyle(string $name): OutputFormatterStyleInterface
    {
        if (!$this->hasStyle($name)) {
            throw new InvalidArgumentException(\sprintf('Undefined style: "%s".', $name));
        }

        return $this->styles[strtolower($name)];
    }

    public function format(?string $message): ?string
    {
        return $this->formatAndWrap($message, 0);
    }

    public function formatAndWrap(?string $message, int $width): string
    {
        if (null === $message) {
            return '';
        }

        // For ASCII-only strings, byte positions equal character positions,
        // so we can use native strlen/substr which is much faster than Helper::length/substr.
        $isAscii = !preg_match('/[\x80-\xFF]/', $message);

        $offset = 0;
        $output = '';
        $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
        $closeTagRegex = '[a-z][^<>]*+';
        $currentLineLength = 0;
        preg_match_all("#<(($openTagRegex) | /($closeTagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE);
        foreach ($matches[0] as $i => $match) {
            $pos = $match[1];
            $text = $match[0];

            if (0 != $pos && '\\' == $message[$pos - 1]) {
                continue;
            }

            if ($isAscii) {
                // For ASCII, byte position = character position, no conversion needed
                $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
                $offset = $pos + \strlen($text);
            } else {
                // convert byte position to character position.
                $pos = Helper::length(substr($message, 0, $pos));
                // add the text up to the next tag
                $output .= $this->applyCurrentStyle(Helper::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
                $offset = $pos + Helper::length($text);
            }

            // opening tag?
            if ($open = '/' !== $text[1]) {
                $tag = $matches[1][$i][0];
            } else {
                $tag = $matches[3][$i][0] ?? '';
            }

            if (!$open && !$tag) {
                // </>
                $this->styleStack->pop();
            } elseif (null === $style = $this->createStyleFromString($tag)) {
                $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
            } elseif ($open) {
                $this->styleStack->push($style);
            } else {
                $this->styleStack->pop($style);
            }
        }

        $output .= $this->applyCurrentStyle($isAscii ? substr($message, $offset) : Helper::substr($message, $offset), $output, $width, $currentLineLength);

        return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']);
    }

    public function getStyleStack(): OutputFormatterStyleStack
    {
        return $this->styleStack;
    }

    /**
     * Tries to create new style instance from string.
     */
    private function createStyleFromString(string $string): ?OutputFormatterStyleInterface
    {
        if (isset($this->styles[$string])) {
            return $this->styles[$string];
        }

        if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) {
            return null;
        }

        $style = new OutputFormatterStyle();
        foreach ($matches as $match) {
            array_shift($match);
            $match[0] = strtolower($match[0]);

            if ('fg' == $match[0]) {
                $style->setForeground(strtolower($match[1]));
            } elseif ('bg' == $match[0]) {
                $style->setBackground(strtolower($match[1]));
            } elseif ('href' === $match[0]) {
                $url = preg_replace('{\\\\([<>])}', '$1', $match[1]);
                $style->setHref($url);
            } elseif ('options' === $match[0]) {
                preg_match_all('([^,;]+)', strtolower($match[1]), $options);
                $options = array_shift($options);
                foreach ($options as $option) {
                    $style->setOption($option);
                }
            } else {
                return null;
            }
        }

        return $style;
    }

    /**
     * Applies current style from stack to text, if must be applied.
     */
    private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string
    {
        if ('' === $text) {
            return '';
        }

        if (!$width) {
            return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text;
        }

        if (!$currentLineLength && '' !== $current) {
            $text = ltrim($text);
        }

        if ($currentLineLength) {
            $lines = explode("\n", $text, 2);
            $prefix = Helper::substr($lines[0], 0, $i = $width - $currentLineLength)."\n";
            $text = Helper::substr($lines[0], $i);

            if (isset($lines[1])) {
                // $prefix may contain the full first line in which the \n is already a part of $prefix.
                if ('' !== $text) {
                    $text .= "\n";
                }

                $text .= $lines[1];
            }
        } else {
            $prefix = '';
        }

        preg_match('~(\\n)$~', $text, $matches);
        $text = $prefix.$this->addLineBreaks($text, $width);
        $text = rtrim($text, "\n").($matches[1] ?? '');

        if (!$currentLineLength && '' !== $current && !str_ends_with($current, "\n")) {
            $text = "\n".$text;
        }

        $lines = explode("\n", $text);

        foreach ($lines as $i => $line) {
            $currentLineLength = 0 === $i ? $currentLineLength + Helper::length($line) : Helper::length($line);
            if ($width <= $currentLineLength) {
                $currentLineLength = 0;
            }
        }

        if ($this->isDecorated()) {
            foreach ($lines as $i => $line) {
                $lines[$i] = $this->styleStack->getCurrent()->apply($line);
            }
        }

        return implode("\n", $lines);
    }

    private function addLineBreaks(string $text, int $width): string
    {
        $encoding = mb_detect_encoding($text, null, true) ?: 'UTF-8';

        return b($text)->toUnicodeString($encoding)->wordwrap($width, "\n", true)->toByteString($encoding);
    }
}
#compdef {{ COMMAND_NAME }}

# This file is part of the Symfony package.
#
# (c) Fabien Potencier <fabien@symfony.com>
#
# For the full copyright and license information, please view
# https://symfony.com/doc/current/contributing/code/license.html

#
# zsh completions for {{ COMMAND_NAME }}
#
# References:
#   - https://github.com/spf13/cobra/blob/master/zsh_completions.go
#   - https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Console/Resources/completion.bash
#
_sf_{{ COMMAND_NAME }}() {
    local lastParam flagPrefix requestComp out comp
    local -a completions

    # The user could have moved the cursor backwards on the command-line.
    # We need to trigger completion from the $CURRENT location, so we need
    # to truncate the command-line ($words) up to the $CURRENT location.
    # (We cannot use $CURSOR as its value does not work when a command is an alias.)
    words=("${=words[1,CURRENT]}") lastParam=${words[-1]}

    # For zsh, when completing a flag with an = (e.g., {{ COMMAND_NAME }} -n=<TAB>)
    # completions must be prefixed with the flag
    setopt local_options BASH_REMATCH
    if [[ "${lastParam}" =~ '-.*=' ]]; then
        # We are dealing with a flag with an =
        flagPrefix="-P ${BASH_REMATCH}"
    fi

    # Prepare the command to obtain completions
    requestComp="${words[0]} ${words[1]} _complete --no-interaction -szsh -a{{ VERSION }} -c$((CURRENT-1))" i=""
    for w in ${words[@]}; do
        w=$(printf -- '%b' "$w")
        # remove quotes from typed values
        quote="${w:0:1}"
        if [ "$quote" = \' ]; then
            w="${w%\'}"
            w="${w#\'}"
        elif [ "$quote" = \" ]; then
            w="${w%\"}"
            w="${w#\"}"
        fi
        # empty values are ignored
        if [ ! -z "$w" ]; then
            i="${i}-i${w} "
        fi
    done

    # Ensure at least 1 input
    if [ "${i}" = "" ]; then
        requestComp="${requestComp} -i\" \""
    else
        requestComp="${requestComp} ${i}"
    fi

    # Use eval to handle any environment variables and such
    out=$(eval SHELL_VERBOSITY=0 ${requestComp} 2>/dev/null)

    while IFS='\n' read -r comp; do
        if [ -n "$comp" ]; then
            # If requested, completions are returned with a description.
            # The description is preceded by a TAB character.
            # For zsh's _describe, we need to use a : instead of a TAB.
            # We first need to escape any : as part of the completion itself.
            comp=${comp//:/\\:}
            local tab=$(printf '\t')
            comp=${comp//$tab/:}
            completions+=${comp}
        fi
    done < <(printf "%s\n" "${out[@]}")

    # Let inbuilt _describe handle completions
    eval _describe "completions" completions $flagPrefix
    return $?
}

compdef _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }}
# This file is part of the Symfony package.
#
# (c) Fabien Potencier <fabien@symfony.com>
#
# For the full copyright and license information, please view
# https://symfony.com/doc/current/contributing/code/license.html

function _sf_{{ COMMAND_NAME }}
    set sf_cmd (commandline -o)
    set c (count (commandline -oc))

    set completecmd "$sf_cmd[1]" "_complete" "--no-interaction" "-sfish" "-a{{ VERSION }}"

    for i in $sf_cmd
        if [ $i != "" ]
            set completecmd $completecmd "-i$i"
        end
    end

    set completecmd $completecmd "-c$c"

    set sfcomplete (env SHELL_VERBOSITY=0 $completecmd)

    for i in $sfcomplete
        echo $i
    end
end

complete -c '{{ COMMAND_NAME }}' -a '(_sf_{{ COMMAND_NAME }})' -f
MZ                @                                       	!L!This program cannot be run in DOS mode.
$       ,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;B        PE  L MoO         	  
         8           @                      `     ?   @                           "  P    @                      P  p   !                             8!  @                                          .text   	      
                    `.rdata  	       
                 @  @.data      0                    @  .rsrc       @                    @  @.reloc     P      "              @  B                                                                                                                                                                                                                                                                                                                                                        j$@ x  j @ e EPV  @ EЃPV @ MX @ e EP5H @ L @ YY5\ @ EP5` @ D @ YYP @ MMT @ 3H  ; 0@ u  h@   l3@ $40@ 5h3@ 40@ h$0@ h(0@ h 0@  @ 00@ }j  Yjh"@   3ۉ]d   p]俀3@ SVW0 @ ;t;u3Fuh  4 @ 3F|3@ ;u
j\  Y;|3@ u,5|3@ h @ h @   YYtE      5<0@ |3@ ;uh @ h @ l  YY|3@    9]uSW8 @ 93@ th3@   Yt
SjS3@ $0@  @ 5$0@ 5(0@ 5 0@ 80@ 9,0@ u7P @ E	MPQ  YYËeE80@ 39,0@ uPh @ 9<0@ u @ E80@   øMZ  f9  @ t3M< @   @ 8PE  uH  t  uՃ   v39   xtv39   j,0@ p @ jl @ YY3@ 3@  @ t3@  @ p3@  @  x3@ V    =0@  uh@  @ Yg  =0@ u	j @ Y3{  U(  H1@ D1@ @1@ <1@ 581@ =41@ f`1@ fT1@ f01@ f,1@ f%(1@ f-$1@ X1@ E L1@ EP1@ E\1@ 0@   P1@ L0@ @0@ 	 D0@     0@ 0@  @ 0@ j?  Yj   @ h!@ $ @ =0@  uj  Yh	 ( @ P, @ ËUE 8csmu*xu$@= t=!t="t= @u  3] hH@   @ 3% @ jh("@ b  53@ 5 @ YEuu @ Ygj  Ye 53@ ։E53@ YYEEPEPu5l @ YPU  Eu֣3@ uփ3@ E	   E  j  YËUuNYH]ËV!@ !@ W;stЃ;r_^ËV"@ "@ W;stЃ;r_^% @ ̋UMMZ  f9t3]ËA<8PE  u3ҹ  f9H]̋UEH<ASVq3WDv}H;r	X;r
B(;r3_^[]̋UjhH"@ he@ d    PSVW 0@ 1E3PEd    eE    h  @ *tUE-  @ Ph  @ Pt;@$ЃEMd    Y_^[]ËE3=  ËeE3Md    Y_^[]% @ % @ he@ d5    D$l$l$+SVW 0@ 1E3PeuEEEEd    ËMd    Y__^[]QËUuuuuh@ h 0@    ]ËVh   h   3V   tVVVVV   ^3ËU 0@ e e SWN@  ;tt	У0@ `VEP< @ u3u @ 3 @ 3 @ 3EP @ E3E3;uO@u5 0@ ։50@ ^_[%t @ %x @ %| @ % @ % @ % @ % @ % @ % @ Pd5    D$+d$SVW( 0@ 3PEuEEd    ËMd    Y__^[]QËM3M%T @ T$BJ3J3l"@ s                                                                                                                                                                                                                                                     #  #  #  )  r)  b)  H)  4)  )  (  (  (  (  (  (  )      #  $  %  %  &  d&  &  $      ('  '  '  '  '  (  ((  6(  '  H(  Z(  t(  (  '  '   '  '  '  l'  ^'  R'  F'  >'  >(  0'  '  )          @         W@ @                     MoO       l   !    @0@ 0@ bad allocation      H                                                            0@ !@    RSDSьJ!LZ    c:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdb     e                            @ @                 :@             @ @ @ "   d"@                        "          #      $#          &  D   H#          (  h                       #  #  #  )  r)  b)  H)  4)  )  (  (  (  (  (  (  )      #  $  %  %  &  d&  &  $      ('  '  '  '  '  (  ((  6(  '  H(  Z(  t(  (  '  '   '  '  '  l'  ^'  R'  F'  >'  >(  0'  '  )      GetConsoleMode  SetConsoleMode  ;GetStdHandle  KERNEL32.dll   ??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A  J?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A  ??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z  _??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  {??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z  MSVCP90.dll _amsg_exit   __getmainargs ,_cexit  |_exit f _XcptFilter exit   __initenv _initterm _initterm_e <_configthreadlocale  __setusermatherr  _adjust_fdiv   __p__commode   __p__fmode  j_encode_pointer  __set_app_type  K_crt_debugger_hook  C ?terminate@@YAXXZ MSVCR90.dll _unlock  __dllonexit v_lock _onexit `_decode_pointer s_except_handler4_common _invoke_watson  ?_controlfp_s  InterlockedExchange !Sleep InterlockedCompareExchange  -TerminateProcess  GetCurrentProcess >UnhandledExceptionFilter  SetUnhandledExceptionFilter IsDebuggerPresent TQueryPerformanceCounter fGetTickCount  GetCurrentThreadId  GetCurrentProcessId OGetSystemTimeAsFileTime s __CxxFrameHandler3                                                    N@D   $!@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            8                   P                   h                	                   	     @  (        C  V        (4   V S _ V E R S I O N _ I N F O                                                  S t r i n g F i l e I n f o   b   0 4 0 9 0 4 b 0    Q  F i l e D e s c r i p t i o n     R e a d s   f r o m   s t d i n   w i t h o u t   l e a k i n g   i n f o   t o   t h e   t e r m i n a l   a n d   o u t p u t s   b a c k   t o   s t d o u t     6   F i l e V e r s i o n     1 ,   0 ,   0 ,   0     8   I n t e r n a l N a m e   h i d d e n i n p u t   P   L e g a l C o p y r i g h t   J o r d i   B o g g i a n o   -   2 0 1 2   H   O r i g i n a l F i l e n a m e   h i d d e n i n p u t . e x e   :   P r o d u c t N a m e     H i d d e n   I n p u t     :   P r o d u c t V e r s i o n   1 ,   0 ,   0 ,   0     D    V a r F i l e I n f o     $    T r a n s l a t i o n     	<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING   @  00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}666 777*7w7|77777888=8E8P8V8\8b8h8n8t8z88889      $   0001 1t1x12 2@2\2`2h2t2 0     0                                                                                                                                                  # This file is part of the Symfony package.
#
# (c) Fabien Potencier <fabien@symfony.com>
#
# For the full copyright and license information, please view
# https://symfony.com/doc/current/contributing/code/license.html

_sf_{{ COMMAND_NAME }}() {

    # Use the default completion for shell redirect operators.
    for w in '>' '>>' '&>' '<'; do
        if [[ $w = "${COMP_WORDS[COMP_CWORD-1]}" ]]; then
            compopt -o filenames
            COMPREPLY=($(compgen -f -- "${COMP_WORDS[COMP_CWORD]}"))
            return 0
        fi
    done

    # Use newline as only separator to allow space in completion values
    local IFS=$'\n'
    local sf_cmd="${COMP_WORDS[0]}"

    # for an alias, get the real script behind it
    sf_cmd_type=$(type -t $sf_cmd)
    if [[ $sf_cmd_type == "alias" ]]; then
        sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/")
    elif [[ $sf_cmd_type == "file" ]]; then
        sf_cmd=$(type -p $sf_cmd)
    fi

    if [[ $sf_cmd_type != "function" && ! -x $sf_cmd ]]; then
        return 1
    fi

    local cur prev words cword
    _get_comp_words_by_ref -n := cur prev words cword

    local completecmd=("$sf_cmd" "_complete" "--no-interaction" "-sbash" "-c$cword" "-a{{ VERSION }}")
    for w in ${words[@]}; do
        w="${w//\\\\/\\}"
        # remove quotes from typed values
        quote="${w:0:1}"
        if [ "$quote" == \' ]; then
            w="${w%\'}"
            w="${w#\'}"
        elif [ "$quote" == \" ]; then
            w="${w%\"}"
            w="${w#\"}"
        fi
        # empty values are ignored
        if [ ! -z "$w" ]; then
            completecmd+=("-i$w")
        fi
    done

    local sfcomplete
    if sfcomplete=$(SHELL_VERBOSITY=0 ${completecmd[@]} 2>&1); then
        local quote suggestions
        quote=${cur:0:1}

        # Use single quotes by default if suggestions contains backslash (FQCN)
        if [ "$quote" == '' ] && [[ "$sfcomplete" =~ \\ ]]; then
            quote=\'
        fi

        if [ "$quote" == \' ]; then
            # single quotes: no additional escaping (does not accept ' in values)
            suggestions=$(for s in $sfcomplete; do printf $'%q%q%q\n' "$quote" "$s" "$quote"; done)
        elif [ "$quote" == \" ]; then
            # double quotes: double escaping for \ $ ` "
            suggestions=$(for s in $sfcomplete; do
                s=${s//\\/\\\\}
                s=${s//\$/\\\$}
                s=${s//\`/\\\`}
                s=${s//\"/\\\"}
                printf $'%q%q%q\n' "$quote" "$s" "$quote";
            done)
        else
            # no quotes: double escaping
            suggestions=$(for s in $sfcomplete; do printf $'%q\n' $(printf '%q' "$s"); done)
        fi
        COMPREPLY=($(IFS=$'\n' compgen -W "$suggestions" -- $(printf -- "%q" "$cur")))
        __ltrim_colon_completions "$cur"
    else
        if [[ "$sfcomplete" != *"Command \"_complete\" is not defined."* ]]; then
            >&2 echo
            >&2 echo $sfcomplete
        fi

        return 1
    fi
}

complete -F _sf_{{ COMMAND_NAME }} {{ COMMAND_NAME }}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class Color
{
    private const COLORS = [
        'black' => 0,
        'red' => 1,
        'green' => 2,
        'yellow' => 3,
        'blue' => 4,
        'magenta' => 5,
        'cyan' => 6,
        'white' => 7,
        'default' => 9,
    ];

    private const BRIGHT_COLORS = [
        'gray' => 0,
        'bright-red' => 1,
        'bright-green' => 2,
        'bright-yellow' => 3,
        'bright-blue' => 4,
        'bright-magenta' => 5,
        'bright-cyan' => 6,
        'bright-white' => 7,
    ];

    private const AVAILABLE_OPTIONS = [
        'bold' => ['set' => 1, 'unset' => 22],
        'underscore' => ['set' => 4, 'unset' => 24],
        'blink' => ['set' => 5, 'unset' => 25],
        'reverse' => ['set' => 7, 'unset' => 27],
        'conceal' => ['set' => 8, 'unset' => 28],
    ];

    private string $foreground;
    private string $background;
    private array $options = [];

    public function __construct(string $foreground = '', string $background = '', array $options = [])
    {
        $this->foreground = $this->parseColor($foreground);
        $this->background = $this->parseColor($background, true);

        foreach ($options as $option) {
            if (!isset(self::AVAILABLE_OPTIONS[$option])) {
                throw new InvalidArgumentException(\sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS))));
            }

            $this->options[$option] = self::AVAILABLE_OPTIONS[$option];
        }
    }

    public function apply(string $text): string
    {
        return $this->set().$text.$this->unset();
    }

    public function set(): string
    {
        $setCodes = [];
        if ('' !== $this->foreground) {
            $setCodes[] = $this->foreground;
        }
        if ('' !== $this->background) {
            $setCodes[] = $this->background;
        }
        foreach ($this->options as $option) {
            $setCodes[] = $option['set'];
        }
        if (0 === \count($setCodes)) {
            return '';
        }

        return \sprintf("\033[%sm", implode(';', $setCodes));
    }

    public function unset(): string
    {
        $unsetCodes = [];
        if ('' !== $this->foreground) {
            $unsetCodes[] = 39;
        }
        if ('' !== $this->background) {
            $unsetCodes[] = 49;
        }
        foreach ($this->options as $option) {
            $unsetCodes[] = $option['unset'];
        }
        if (0 === \count($unsetCodes)) {
            return '';
        }

        return \sprintf("\033[%sm", implode(';', $unsetCodes));
    }

    private function parseColor(string $color, bool $background = false): string
    {
        if ('' === $color) {
            return '';
        }

        if ('#' === $color[0]) {
            return ($background ? '4' : '3').Terminal::getColorMode()->convertFromHexToAnsiColorCode($color);
        }

        if (isset(self::COLORS[$color])) {
            return ($background ? '4' : '3').self::COLORS[$color];
        }

        if (isset(self::BRIGHT_COLORS[$color])) {
            return ($background ? '10' : '9').self::BRIGHT_COLORS[$color];
        }

        throw new InvalidArgumentException(\sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * Represents an incorrect namespace typed in the console.
 *
 * @author Pierre du Plessis <pdples@gmail.com>
 */
class NamespaceNotFoundException extends CommandNotFoundException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * ExceptionInterface.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * Represents an incorrect option name or value typed in the console.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
{
    /**
     * @internal
     */
    public static function fromEnumValue(string $name, string $value, array|\Closure $suggestedValues): self
    {
        $error = \sprintf('The value "%s" is not valid for the "%s" option.', $value, $name);

        if (\is_array($suggestedValues)) {
            $error .= \sprintf(' Supported values are "%s".', implode('", "', $suggestedValues));
        }

        return new self($error);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
    /**
     * @internal
     */
    public static function fromEnumValue(string $name, string $value, array|\Closure $suggestedValues): self
    {
        $error = \sprintf('The value "%s" is not valid for the "%s" argument.', $value, $name);

        if (\is_array($suggestedValues)) {
            $error .= \sprintf(' Supported values are "%s".', implode('", "', $suggestedValues));
        }

        return new self($error);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * Represents failure to read input from stdin.
 *
 * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
 */
class MissingInputException extends RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * Represents an incorrect command name typed in the console.
 *
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
{
    /**
     * @param string          $message      Exception message to throw
     * @param string[]        $alternatives List of similar defined names
     * @param int             $code         Exception code
     * @param \Throwable|null $previous     Previous exception used for the exception chaining
     */
    public function __construct(
        string $message,
        private array $alternatives = [],
        int $code = 0,
        ?\Throwable $previous = null,
    ) {
        parent::__construct($message, $code, $previous);
    }

    /**
     * @return string[]
     */
    public function getAlternatives(): array
    {
        return $this->alternatives;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

/**
 * @author Jérôme Tamarelle <jerome@tamarelle.net>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Exception;

use Symfony\Component\Console\Messenger\RunCommandContext;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunCommandFailedException extends RuntimeException
{
    public function __construct(\Throwable|string $exception, public readonly RunCommandContext $context)
    {
        parent::__construct(
            $exception instanceof \Throwable ? $exception->getMessage() : $exception,
            $exception instanceof \Throwable && \is_int($exception->getCode()) ? $exception->getCode() : 0,
            $exception instanceof \Throwable ? $exception : null,
        );
    }
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Logger;

use Psr\Log\AbstractLogger;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * PSR-3 compliant console logger.
 *
 * @author Kévin Dunglas <dunglas@gmail.com>
 *
 * @see https://www.php-fig.org/psr/psr-3/
 */
class ConsoleLogger extends AbstractLogger
{
    public const INFO = 'info';
    public const ERROR = 'error';

    private array $verbosityLevelMap = [
        LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
        LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
        LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
        LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
        LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
        LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
        LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
        LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
    ];
    private array $formatLevelMap = [
        LogLevel::EMERGENCY => self::ERROR,
        LogLevel::ALERT => self::ERROR,
        LogLevel::CRITICAL => self::ERROR,
        LogLevel::ERROR => self::ERROR,
        LogLevel::WARNING => self::INFO,
        LogLevel::NOTICE => self::INFO,
        LogLevel::INFO => self::INFO,
        LogLevel::DEBUG => self::INFO,
    ];
    private bool $errored = false;

    public function __construct(
        private OutputInterface $output,
        array $verbosityLevelMap = [],
        array $formatLevelMap = [],
    ) {
        $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
        $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
    }

    public function log($level, $message, array $context = []): void
    {
        if (!isset($this->verbosityLevelMap[$level])) {
            throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level));
        }

        $output = $this->output;

        // Write to the error output if necessary and available
        if (self::ERROR === $this->formatLevelMap[$level]) {
            if ($this->output instanceof ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            $this->errored = true;
        }

        // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
        // We only do it for efficiency here as the message formatting is relatively expensive.
        if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
            $output->writeln(\sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
        }
    }

    /**
     * Returns true when any messages have been logged at error levels.
     */
    public function hasErrored(): bool
    {
        return $this->errored;
    }

    /**
     * Interpolates context values into the message placeholders.
     *
     * @author PHP Framework Interoperability Group
     */
    private function interpolate(string $message, array $context): string
    {
        if (!str_contains($message, '{')) {
            return $message;
        }

        $replacements = [];
        foreach ($context as $key => $val) {
            if (null === $val || \is_scalar($val) || $val instanceof \Stringable) {
                $replacements["{{$key}}"] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                $replacements["{{$key}}"] = $val->format(\DateTimeInterface::RFC3339);
            } elseif (\is_object($val)) {
                $replacements["{{$key}}"] = '[object '.$val::class.']';
            } else {
                $replacements["{{$key}}"] = '['.\gettype($val).']';
            }
        }

        return strtr($message, $replacements);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\DependencyInjection;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;

/**
 * Registers console commands.
 *
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class AddConsoleCommandPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        $commandServices = $container->findTaggedServiceIds('console.command', true);
        $lazyCommandMap = [];
        $lazyCommandRefs = [];
        $serviceIds = [];

        foreach ($commandServices as $id => $tags) {
            $definition = $container->getDefinition($id);
            $class = $container->getParameterBag()->resolveValue($definition->getClass());

            if (!$r = $container->getReflectionClass($class)) {
                throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
            }

            if (!$r->isSubclassOf(Command::class)) {
                if (!$r->hasMethod('__invoke')) {
                    throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must either be a subclass of "%s" or have an "__invoke()" method.', $id, 'console.command', Command::class));
                }

                $invokableRef = new Reference($id);
                $definition = $container->register($id .= '.command', $class = Command::class)
                    ->addMethodCall('setCode', [$invokableRef]);
            } else {
                $invokableRef = null;
            }

            $definition->addTag('container.no_preload');

            /** @var AsCommand|null $attribute */
            $attribute = ($r->getAttributes(AsCommand::class)[0] ?? null)?->newInstance();

            if (Command::class !== (new \ReflectionMethod($class, 'getDefaultName'))->class) {
                trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultName()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', $class);

                $defaultName = $class::getDefaultName();
            } else {
                $defaultName = $attribute?->name;
            }

            $aliases = str_replace('%', '%%', $tags[0]['command'] ?? $defaultName ?? '');
            $aliases = explode('|', $aliases);
            $commandName = array_shift($aliases);

            if ($isHidden = '' === $commandName) {
                $commandName = array_shift($aliases);
            }

            if (null === $commandName) {
                if ($definition->isPrivate() || $definition->hasTag('container.private')) {
                    $commandId = 'console.command.public_alias.'.$id;
                    $container->setAlias($commandId, $id)->setPublic(true);
                    $id = $commandId;
                }
                $serviceIds[] = $id;

                continue;
            }

            $description = $tags[0]['description'] ?? null;
            $help = $tags[0]['help'] ?? null;
            $usages = $tags[0]['usages'] ?? null;

            unset($tags[0]);
            $lazyCommandMap[$commandName] = $id;
            $lazyCommandRefs[$id] = new TypedReference($id, $class);

            foreach ($aliases as $alias) {
                $lazyCommandMap[$alias] = $id;
            }

            foreach ($tags as $tag) {
                if (isset($tag['command'])) {
                    $aliases[] = $tag['command'];
                    $lazyCommandMap[$tag['command']] = $id;
                }

                $description ??= $tag['description'] ?? null;
                $help ??= $tag['help'] ?? null;
                $usages ??= $tag['usages'] ?? null;
            }

            $definition->addMethodCall('setName', [$commandName]);

            if ($aliases) {
                $definition->addMethodCall('setAliases', [$aliases]);
            }

            if ($isHidden) {
                $definition->addMethodCall('setHidden', [true]);
            }

            if ($help && $invokableRef) {
                $definition->addMethodCall('setHelp', [str_replace('%', '%%', $help)]);
            }

            if ($usages) {
                foreach ($usages as $usage) {
                    $definition->addMethodCall('addUsage', [$usage]);
                }
            }

            if (!$description) {
                if (Command::class !== (new \ReflectionMethod($class, 'getDefaultDescription'))->class) {
                    trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultDescription()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', $class);

                    $description = $class::getDefaultDescription();
                } else {
                    $description = $attribute?->description;
                }
            }

            if ($description) {
                $escapedDescription = str_replace('%', '%%', $description);
                $definition->addMethodCall('setDescription', [$escapedDescription]);

                $container->register('.'.$id.'.lazy', LazyCommand::class)
                    ->setArguments([$commandName, $aliases, $escapedDescription, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);

                $lazyCommandRefs[$id] = new Reference('.'.$id.'.lazy');
            }
        }

        $container
            ->register('console.command_loader', ContainerCommandLoader::class)
            ->setPublic(true)
            ->addTag('container.no_preload')
            ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);

        $container->setParameter('console.command.ids', $serviceIds);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Messenger;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunCommandContext
{
    public function __construct(
        public readonly RunCommandMessage $message,
        public readonly int $exitCode,
        public readonly string $output,
    ) {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Messenger;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\RunCommandFailedException;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Messenger\Exception\RecoverableExceptionInterface;
use Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunCommandMessageHandler
{
    public function __construct(
        private readonly Application $application,
    ) {
    }

    public function __invoke(RunCommandMessage $message): RunCommandContext
    {
        $input = new StringInput($message->input);
        $output = new BufferedOutput();

        $this->application->setCatchExceptions($message->catchExceptions);

        try {
            $exitCode = $this->application->run($input, $output);
        } catch (UnrecoverableExceptionInterface|RecoverableExceptionInterface $e) {
            throw $e;
        } catch (\Throwable $e) {
            throw new RunCommandFailedException($e, new RunCommandContext($message, Command::FAILURE, $output->fetch()));
        }

        if ($message->throwOnFailure && Command::SUCCESS !== $exitCode) {
            throw new RunCommandFailedException(\sprintf('Command "%s" exited with code "%s".', $message->input, $exitCode), new RunCommandContext($message, $exitCode, $output->fetch()));
        }

        return new RunCommandContext($message, $exitCode, $output->fetch());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Messenger;

use Symfony\Component\Console\Exception\RunCommandFailedException;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class RunCommandMessage implements \Stringable
{
    /**
     * @param bool $throwOnFailure  If the command has a non-zero exit code, throw {@see RunCommandFailedException}
     * @param bool $catchExceptions @see Application::setCatchExceptions()
     */
    public function __construct(
        public readonly string $input,
        public readonly bool $throwOnFailure = true,
        public readonly bool $catchExceptions = false,
    ) {
    }

    public function __toString(): string
    {
        return $this->input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\DataCollector;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Debug\CliRequest;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SignalRegistry\SignalMap;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\VarDumper\Cloner\Data;

/**
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class CommandDataCollector extends DataCollector
{
    public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
    {
        if (!$request instanceof CliRequest) {
            return;
        }

        $command = $request->command;
        $application = $command->getApplication();

        $this->data = [
            'command' => $command->invokableCommandInfo ?? $this->cloneVar($command->command),
            'exit_code' => $command->exitCode,
            'interrupted_by_signal' => $command->interruptedBySignal,
            'duration' => $command->duration,
            'max_memory_usage' => $command->maxMemoryUsage,
            'verbosity_level' => match ($command->output->getVerbosity()) {
                OutputInterface::VERBOSITY_SILENT => 'silent',
                OutputInterface::VERBOSITY_QUIET => 'quiet',
                OutputInterface::VERBOSITY_NORMAL => 'normal',
                OutputInterface::VERBOSITY_VERBOSE => 'verbose',
                OutputInterface::VERBOSITY_VERY_VERBOSE => 'very verbose',
                OutputInterface::VERBOSITY_DEBUG => 'debug',
            },
            'interactive' => $command->isInteractive,
            'validate_input' => !$command->ignoreValidation,
            'enabled' => $command->isEnabled(),
            'visible' => !$command->isHidden(),
            'input' => $this->cloneVar($command->input),
            'output' => $this->cloneVar($command->output),
            'interactive_inputs' => array_map($this->cloneVar(...), $command->interactiveInputs),
            'signalable' => $command->getSubscribedSignals(),
            'handled_signals' => $command->handledSignals,
            'helper_set' => array_map($this->cloneVar(...), iterator_to_array($command->getHelperSet())),
        ];

        $baseDefinition = $application->getDefinition();

        foreach ($command->arguments as $argName => $argValue) {
            if ($baseDefinition->hasArgument($argName)) {
                $this->data['application_inputs'][$argName] = $this->cloneVar($argValue);
            } else {
                $this->data['arguments'][$argName] = $this->cloneVar($argValue);
            }
        }

        foreach ($command->options as $optName => $optValue) {
            if ($baseDefinition->hasOption($optName)) {
                $this->data['application_inputs']['--'.$optName] = $this->cloneVar($optValue);
            } else {
                $this->data['options'][$optName] = $this->cloneVar($optValue);
            }
        }
    }

    public function getName(): string
    {
        return 'command';
    }

    /**
     * @return array{
     *     class?: class-string,
     *     executor?: string,
     *     file: string,
     *     line: int,
     * }
     */
    public function getCommand(): array
    {
        if (\is_array($this->data['command'])) {
            return $this->data['command'];
        }

        $class = $this->data['command']->getType();
        $r = new \ReflectionMethod($class, 'execute');

        if (Command::class !== $r->getDeclaringClass()) {
            return [
                'executor' => $class.'::'.$r->name,
                'file' => $r->getFileName(),
                'line' => $r->getStartLine(),
            ];
        }

        $r = new \ReflectionClass($class);

        return [
            'class' => $class,
            'file' => $r->getFileName(),
            'line' => $r->getStartLine(),
        ];
    }

    public function getInterruptedBySignal(): ?string
    {
        if (isset($this->data['interrupted_by_signal'])) {
            return \sprintf('%s (%d)', SignalMap::getSignalName($this->data['interrupted_by_signal']), $this->data['interrupted_by_signal']);
        }

        return null;
    }

    public function getDuration(): string
    {
        return $this->data['duration'];
    }

    public function getMaxMemoryUsage(): string
    {
        return $this->data['max_memory_usage'];
    }

    public function getVerbosityLevel(): string
    {
        return $this->data['verbosity_level'];
    }

    public function getInteractive(): bool
    {
        return $this->data['interactive'];
    }

    public function getValidateInput(): bool
    {
        return $this->data['validate_input'];
    }

    public function getEnabled(): bool
    {
        return $this->data['enabled'];
    }

    public function getVisible(): bool
    {
        return $this->data['visible'];
    }

    public function getInput(): Data
    {
        return $this->data['input'];
    }

    public function getOutput(): Data
    {
        return $this->data['output'];
    }

    /**
     * @return Data[]
     */
    public function getArguments(): array
    {
        return $this->data['arguments'] ?? [];
    }

    /**
     * @return Data[]
     */
    public function getOptions(): array
    {
        return $this->data['options'] ?? [];
    }

    /**
     * @return Data[]
     */
    public function getApplicationInputs(): array
    {
        return $this->data['application_inputs'] ?? [];
    }

    /**
     * @return Data[]
     */
    public function getInteractiveInputs(): array
    {
        return $this->data['interactive_inputs'] ?? [];
    }

    public function getSignalable(): array
    {
        return array_map(
            static fn (int $signal): string => \sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal),
            $this->data['signalable']
        );
    }

    public function getHandledSignals(): array
    {
        $keys = array_map(
            static fn (int $signal): string => \sprintf('%s (%d)', SignalMap::getSignalName($signal), $signal),
            array_keys($this->data['handled_signals'])
        );

        return array_combine($keys, array_values($this->data['handled_signals']));
    }

    /**
     * @return Data[]
     */
    public function getHelperSet(): array
    {
        return $this->data['helper_set'] ?? [];
    }

    public function reset(): void
    {
        $this->data = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\SignalRegistry;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class SignalMap
{
    private static array $map;

    public static function getSignalName(int $signal): ?string
    {
        if (!\extension_loaded('pcntl')) {
            return null;
        }

        if (!isset(self::$map)) {
            $r = new \ReflectionExtension('pcntl');
            $c = $r->getConstants();
            $map = array_filter($c, static fn ($k) => str_starts_with($k, 'SIG') && !str_starts_with($k, 'SIG_') && 'SIGBABY' !== $k, \ARRAY_FILTER_USE_KEY);
            self::$map = array_flip($map);
        }

        return self::$map[$signal] ?? null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\SignalRegistry;

final class SignalRegistry
{
    /**
     * @var array<int, array<callable>>
     */
    private array $signalHandlers = [];

    /**
     * @var array<array<int, array<callable>>>
     */
    private array $stack = [];

    /**
     * @var array<int, callable|int|string>
     */
    private array $originalHandlers = [];

    public function __construct()
    {
        if (\function_exists('pcntl_async_signals')) {
            pcntl_async_signals(true);
        }
    }

    public function register(int $signal, callable $signalHandler): void
    {
        $previous = pcntl_signal_get_handler($signal);

        if (!isset($this->originalHandlers[$signal])) {
            $this->originalHandlers[$signal] = $previous;
        }

        if (!isset($this->signalHandlers[$signal])) {
            if (\is_callable($previous) && [$this, 'handle'] !== $previous) {
                $this->signalHandlers[$signal][] = $previous;
            }
        }

        $this->signalHandlers[$signal][] = $signalHandler;

        pcntl_signal($signal, [$this, 'handle']);
    }

    public static function isSupported(): bool
    {
        return \function_exists('pcntl_signal');
    }

    /**
     * @internal
     */
    public function handle(int $signal): void
    {
        $count = \count($this->signalHandlers[$signal]);

        foreach ($this->signalHandlers[$signal] as $i => $signalHandler) {
            $hasNext = $i !== $count - 1;
            $signalHandler($signal, $hasNext);
        }
    }

    /**
     * Pushes the current active handlers onto the stack and clears the active list.
     *
     * This prepares the registry for a new set of handlers within a specific scope.
     *
     * @internal
     */
    public function pushCurrentHandlers(): void
    {
        // Restore the original OS-level disposition while the active map is empty,
        // so signals are not routed through handle() without a registered handler.
        foreach ($this->signalHandlers as $signal => $handlers) {
            if (isset($this->originalHandlers[$signal])) {
                pcntl_signal($signal, $this->originalHandlers[$signal]);
            }
        }

        $this->stack[] = $this->signalHandlers;
        $this->signalHandlers = [];
    }

    /**
     * Restores the previous handlers from the stack, making them active.
     *
     * This also restores the original OS-level signal handler if no
     * more handlers are registered for a signal that was just popped.
     *
     * @internal
     */
    public function popPreviousHandlers(): void
    {
        $popped = $this->signalHandlers;
        $previous = array_pop($this->stack) ?? [];

        // Expose a transitional superset so handle() never reads a missing key
        // if a signal lands while the OS-level handlers below are being swapped.
        $this->signalHandlers = $previous + $popped;

        // Reinstall the registry handler for signals owned by the restored scope.
        foreach ($previous as $signal => $handlers) {
            pcntl_signal($signal, [$this, 'handle']);
        }

        // Restore the original OS-level handler for signals no scope owns anymore.
        foreach ($popped as $signal => $handlers) {
            if (!isset($previous[$signal]) && isset($this->originalHandlers[$signal])) {
                pcntl_signal($signal, $this->originalHandlers[$signal]);
            }
        }

        $this->signalHandlers = $previous;
    }

    /**
     * @internal
     */
    public function scheduleAlarm(int $seconds): void
    {
        pcntl_alarm($seconds);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\CI;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * Utility class for Github actions.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class GithubActionReporter
{
    /**
     * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85
     */
    private const ESCAPED_DATA = [
        '%' => '%25',
        "\r" => '%0D',
        "\n" => '%0A',
    ];

    /**
     * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94
     */
    private const ESCAPED_PROPERTIES = [
        '%' => '%25',
        "\r" => '%0D',
        "\n" => '%0A',
        ':' => '%3A',
        ',' => '%2C',
    ];

    public function __construct(
        private OutputInterface $output,
    ) {
    }

    public static function isGithubActionEnvironment(): bool
    {
        return false !== getenv('GITHUB_ACTIONS');
    }

    /**
     * Output an error using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
     */
    public function error(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        $this->log('error', $message, $file, $line, $col);
    }

    /**
     * Output a warning using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
     */
    public function warning(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        $this->log('warning', $message, $file, $line, $col);
    }

    /**
     * Output a debug log using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message
     */
    public function debug(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        $this->log('debug', $message, $file, $line, $col);
    }

    private function log(string $type, string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
    {
        // Some values must be encoded.
        $message = strtr($message, self::ESCAPED_DATA);

        if (!$file) {
            // No file provided, output the message solely:
            $this->output->writeln(\sprintf('::%s::%s', $type, $message));

            return;
        }

        $this->output->writeln(\sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion;

/**
 * Represents a single suggested value.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class Suggestion implements \Stringable
{
    public function __construct(
        private readonly string $value,
        private readonly string $description = '',
    ) {
    }

    public function getValue(): string
    {
        return $this->value;
    }

    public function getDescription(): string
    {
        return $this->description;
    }

    public function __toString(): string
    {
        return $this->getValue();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion\Output;

use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion\Output;

use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Jitendra A <adhocore@gmail.com>
 */
class ZshCompletionOutput implements CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
    {
        $values = [];
        foreach ($suggestions->getValueSuggestions() as $value) {
            $values[] = $value->getValue().($value->getDescription() ? "\t".$value->getDescription() : '');
        }
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--'.$option->getName().($option->getDescription() ? "\t".$option->getDescription() : '');
            if ($option->isNegatable()) {
                $values[] = '--no-'.$option->getName().($option->getDescription() ? "\t".$option->getDescription() : '');
            }
        }
        $output->write(implode("\n", $values)."\n");
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion\Output;

use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Guillaume Aveline <guillaume.aveline@pm.me>
 */
class FishCompletionOutput implements CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
    {
        $values = [];
        foreach ($suggestions->getValueSuggestions() as $value) {
            $values[] = $value->getValue().($value->getDescription() ? "\t".$value->getDescription() : '');
        }
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--'.$option->getName().($option->getDescription() ? "\t".$option->getDescription() : '');
            if ($option->isNegatable()) {
                $values[] = '--no-'.$option->getName().($option->getDescription() ? "\t".$option->getDescription() : '');
            }
        }
        $output->write(implode("\n", $values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion\Output;

use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class BashCompletionOutput implements CompletionOutputInterface
{
    public function write(CompletionSuggestions $suggestions, OutputInterface $output): void
    {
        $values = $suggestions->getValueSuggestions();
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--'.$option->getName();
            if ($option->isNegatable()) {
                $values[] = '--no-'.$option->getName();
            }
        }
        $output->writeln(implode("\n", $values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion;

use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * An input specialized for shell completion.
 *
 * This input allows unfinished option names or values and exposes what kind of
 * completion is expected.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompletionInput extends ArgvInput
{
    public const TYPE_ARGUMENT_VALUE = 'argument_value';
    public const TYPE_OPTION_VALUE = 'option_value';
    public const TYPE_OPTION_NAME = 'option_name';
    public const TYPE_NONE = 'none';

    private array $tokens;
    private int $currentIndex;
    private string $completionType;
    private ?string $completionName = null;
    private string $completionValue = '';

    /**
     * Converts a terminal string into tokens.
     *
     * This is required for shell completions without COMP_WORDS support.
     */
    public static function fromString(string $inputStr, int $currentIndex): self
    {
        preg_match_all('/(?<=^|\s)([\'"]?)(.+?)(?<!\\\\)\1(?=$|\s)/', $inputStr, $tokens);

        return self::fromTokens($tokens[0], $currentIndex);
    }

    /**
     * Create an input based on an COMP_WORDS token list.
     *
     * @param string[] $tokens       the set of split tokens (e.g. COMP_WORDS or argv)
     * @param int      $currentIndex the index of the cursor (e.g. COMP_CWORD)
     */
    public static function fromTokens(array $tokens, int $currentIndex): self
    {
        $input = new self($tokens);
        $input->tokens = $tokens;
        $input->currentIndex = $currentIndex;

        return $input;
    }

    public function bind(InputDefinition $definition): void
    {
        parent::bind($definition);

        $relevantToken = $this->getRelevantToken();
        if ('-' === $relevantToken[0]) {
            // the current token is an input option: complete either option name or option value
            [$optionToken, $optionValue] = explode('=', $relevantToken, 2) + ['', ''];

            $option = $this->getOptionFromToken($optionToken);
            if (null === $option && !$this->isCursorFree()) {
                $this->completionType = self::TYPE_OPTION_NAME;
                $this->completionValue = $relevantToken;

                return;
            }

            if ($option?->acceptValue()) {
                $this->completionType = self::TYPE_OPTION_VALUE;
                $this->completionName = $option->getName();
                $this->completionValue = $optionValue ?: (!str_starts_with($optionToken, '--') ? substr($optionToken, 2) : '');

                return;
            }
        }

        $previousToken = $this->tokens[$this->currentIndex - 1];
        if ('-' === $previousToken[0] && '' !== trim($previousToken, '-')) {
            // check if previous option accepted a value
            $previousOption = $this->getOptionFromToken($previousToken);
            if ($previousOption?->acceptValue()) {
                $this->completionType = self::TYPE_OPTION_VALUE;
                $this->completionName = $previousOption->getName();
                $this->completionValue = $relevantToken;

                return;
            }
        }

        // complete argument value
        $this->completionType = self::TYPE_ARGUMENT_VALUE;

        foreach ($this->definition->getArguments() as $argumentName => $argument) {
            if (!isset($this->arguments[$argumentName])) {
                break;
            }

            $argumentValue = $this->arguments[$argumentName];
            $this->completionName = $argumentName;
            if (\is_array($argumentValue)) {
                $this->completionValue = $argumentValue ? $argumentValue[array_key_last($argumentValue)] : null;
            } else {
                $this->completionValue = $argumentValue;
            }
        }

        if ($this->currentIndex >= \count($this->tokens)) {
            if (!isset($this->arguments[$argumentName]) || $this->definition->getArgument($argumentName)->isArray()) {
                $this->completionName = $argumentName;
            } else {
                // we've reached the end
                $this->completionType = self::TYPE_NONE;
                $this->completionName = null;
            }

            $this->completionValue = '';
        }
    }

    /**
     * Returns the type of completion required.
     *
     * TYPE_ARGUMENT_VALUE when completing the value of an input argument
     * TYPE_OPTION_VALUE   when completing the value of an input option
     * TYPE_OPTION_NAME    when completing the name of an input option
     * TYPE_NONE           when nothing should be completed
     *
     * TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component.
     *
     * @return self::TYPE_*
     */
    public function getCompletionType(): string
    {
        return $this->completionType;
    }

    /**
     * The name of the input option or argument when completing a value.
     *
     * @return string|null returns null when completing an option name
     */
    public function getCompletionName(): ?string
    {
        return $this->completionName;
    }

    /**
     * The value already typed by the user (or empty string).
     */
    public function getCompletionValue(): string
    {
        return $this->completionValue;
    }

    public function mustSuggestOptionValuesFor(string $optionName): bool
    {
        return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName();
    }

    public function mustSuggestArgumentValuesFor(string $argumentName): bool
    {
        return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName();
    }

    protected function parseToken(string $token, bool $parseOptions): bool
    {
        try {
            return parent::parseToken($token, $parseOptions);
        } catch (RuntimeException) {
            // suppress errors, completed input is almost never valid
        }

        return $parseOptions;
    }

    private function getOptionFromToken(string $optionToken): ?InputOption
    {
        $optionName = ltrim($optionToken, '-');
        if (!$optionName) {
            return null;
        }

        if ('-' === ($optionToken[1] ?? ' ')) {
            // long option name
            return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null;
        }

        // short option name
        return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null;
    }

    /**
     * The token of the cursor, or the last token if the cursor is at the end of the input.
     */
    private function getRelevantToken(): string
    {
        return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex];
    }

    /**
     * Whether the cursor is "free" (i.e. at the end of the input preceded by a space).
     */
    private function isCursorFree(): bool
    {
        $nrOfTokens = \count($this->tokens);
        if ($this->currentIndex > $nrOfTokens) {
            throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.');
        }

        return $this->currentIndex >= $nrOfTokens;
    }

    public function __toString(): string
    {
        $str = '';
        foreach ($this->tokens as $i => $token) {
            $str .= $token;

            if ($this->currentIndex === $i) {
                $str .= '|';
            }

            $str .= ' ';
        }

        if ($this->currentIndex > $i) {
            $str .= '|';
        }

        return rtrim($str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Completion;

use Symfony\Component\Console\Input\InputOption;

/**
 * Stores all completion suggestions for the current input.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompletionSuggestions
{
    private array $valueSuggestions = [];
    private array $optionSuggestions = [];

    /**
     * Add a suggested value for an input option or argument.
     *
     * @return $this
     */
    public function suggestValue(string|Suggestion $value): static
    {
        $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value;

        return $this;
    }

    /**
     * Add multiple suggested values at once for an input option or argument.
     *
     * @param list<string|Suggestion> $values
     *
     * @return $this
     */
    public function suggestValues(array $values): static
    {
        foreach ($values as $value) {
            $this->suggestValue($value);
        }

        return $this;
    }

    /**
     * Add a suggestion for an input option name.
     *
     * @return $this
     */
    public function suggestOption(InputOption $option): static
    {
        $this->optionSuggestions[] = $option;

        return $this;
    }

    /**
     * Add multiple suggestions for input option names at once.
     *
     * @param InputOption[] $options
     *
     * @return $this
     */
    public function suggestOptions(array $options): static
    {
        foreach ($options as $option) {
            $this->suggestOption($option);
        }

        return $this;
    }

    /**
     * @return InputOption[]
     */
    public function getOptionSuggestions(): array
    {
        return $this->optionSuggestions;
    }

    /**
     * @return Suggestion[]
     */
    public function getValueSuggestions(): array
    {
        return $this->valueSuggestions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Output\AnsiColorMode;

class Terminal
{
    public const DEFAULT_COLOR_MODE = AnsiColorMode::Ansi4;

    private static ?AnsiColorMode $colorMode = null;
    private static ?int $width = null;
    private static ?int $height = null;
    private static ?bool $stty = null;

    /**
     * About Ansi color types: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
     * For more information about true color support with terminals https://github.com/termstandard/colors/.
     */
    public static function getColorMode(): AnsiColorMode
    {
        // Use Cache from previous run (or user forced mode)
        if (null !== self::$colorMode) {
            return self::$colorMode;
        }

        // Try with $COLORTERM first
        if (\is_string($colorterm = getenv('COLORTERM'))) {
            $colorterm = strtolower($colorterm);

            if (str_contains($colorterm, 'truecolor')) {
                self::setColorMode(AnsiColorMode::Ansi24);

                return self::$colorMode;
            }

            if (str_contains($colorterm, '256color')) {
                self::setColorMode(AnsiColorMode::Ansi8);

                return self::$colorMode;
            }
        }

        // Try with $TERM
        if (\is_string($term = getenv('TERM'))) {
            $term = strtolower($term);

            if (str_contains($term, 'truecolor')) {
                self::setColorMode(AnsiColorMode::Ansi24);

                return self::$colorMode;
            }

            if (str_contains($term, '256color')) {
                self::setColorMode(AnsiColorMode::Ansi8);

                return self::$colorMode;
            }
        }

        self::setColorMode(self::DEFAULT_COLOR_MODE);

        return self::$colorMode;
    }

    /**
     * Force a terminal color mode rendering.
     */
    public static function setColorMode(?AnsiColorMode $colorMode): void
    {
        self::$colorMode = $colorMode;
    }

    /**
     * Gets the terminal width.
     */
    public function getWidth(): int
    {
        $width = getenv('COLUMNS');
        if (false !== $width) {
            return (int) trim($width);
        }

        if (null === self::$width) {
            self::initDimensions();
        }

        return self::$width ?: 80;
    }

    /**
     * Gets the terminal height.
     */
    public function getHeight(): int
    {
        $height = getenv('LINES');
        if (false !== $height) {
            return (int) trim($height);
        }

        if (null === self::$height) {
            self::initDimensions();
        }

        return self::$height ?: 50;
    }

    /**
     * @internal
     */
    public static function hasSttyAvailable(): bool
    {
        if (null !== self::$stty) {
            return self::$stty;
        }

        // skip check if shell_exec function is disabled
        if (!\function_exists('shell_exec')) {
            return false;
        }

        return self::$stty = (bool) @shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null'));
    }

    private static function initDimensions(): void
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $ansicon = getenv('ANSICON');
            if (false !== $ansicon && preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim($ansicon), $matches)) {
                // extract [w, H] from "wxh (WxH)"
                // or [w, h] from "wxh"
                self::$width = (int) $matches[1];
                self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
            } elseif (!sapi_windows_vt100_support(fopen('php://stdout', 'w')) && self::hasSttyAvailable()) {
                // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash)
                // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT
                self::initDimensionsUsingStty();
            } elseif (null !== $dimensions = self::getConsoleMode()) {
                // extract [w, h] from "wxh"
                self::$width = (int) $dimensions[0];
                self::$height = (int) $dimensions[1];
            }
        } else {
            self::initDimensionsUsingStty();
        }
    }

    /**
     * Initializes dimensions using the output of an stty columns line.
     */
    private static function initDimensionsUsingStty(): void
    {
        if ($sttyString = self::getSttyColumns()) {
            if (preg_match('/rows.(\d+);.columns.(\d+);/is', $sttyString, $matches)) {
                // extract [w, h] from "rows h; columns w;"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/is', $sttyString, $matches)) {
                // extract [w, h] from "; h rows; w columns"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            }
        }
    }

    /**
     * Runs and parses mode CON if it's available, suppressing any error output.
     *
     * @return int[]|null An array composed of the width and the height or null if it could not be parsed
     */
    private static function getConsoleMode(): ?array
    {
        $info = self::readFromProcess('mode CON');

        if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
            return null;
        }

        return [(int) $matches[2], (int) $matches[1]];
    }

    /**
     * Runs and parses stty -a if it's available, suppressing any error output.
     */
    private static function getSttyColumns(): ?string
    {
        return self::readFromProcess(['stty', '-a']);
    }

    private static function readFromProcess(string|array $command): ?string
    {
        if (!\function_exists('proc_open')) {
            return null;
        }

        $descriptorspec = [
            1 => ['pipe', 'w'],
            2 => ['pipe', 'w'],
        ];

        $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0;

        if (!$process = @proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true])) {
            return null;
        }

        $info = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        proc_close($process);

        if ($cp) {
            sapi_windows_cp_set($cp);
        }

        return $info;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

use Symfony\Component\Console\Attribute\Reflection\ReflectionMember;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\String\UnicodeString;

#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
class Option
{
    private const ALLOWED_TYPES = ['string', 'bool', 'int', 'float', 'array'];
    private const ALLOWED_UNION_TYPES = ['bool|string', 'bool|int', 'bool|float'];

    private string|bool|int|float|array|null $default = null;
    private array|\Closure $suggestedValues;
    private ?int $mode = null;
    /**
     * @var string|class-string<\BackedEnum>
     */
    private string $typeName = '';
    private bool $allowNull = false;
    private string $memberName = '';
    private string $sourceName = '';

    /**
     * Represents a console command --option definition.
     *
     * If unset, the `name` value will be inferred from the parameter definition.
     *
     * @param array|string|null                                                          $shortcut        The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param array<string|Suggestion>|callable(CompletionInput):list<string|Suggestion> $suggestedValues The values used for input completion
     */
    public function __construct(
        public string $description = '',
        public string $name = '',
        public array|string|null $shortcut = null,
        array|callable $suggestedValues = [],
    ) {
        $this->suggestedValues = \is_callable($suggestedValues) ? $suggestedValues(...) : $suggestedValues;
    }

    /**
     * @internal
     */
    public static function tryFrom(\ReflectionParameter|\ReflectionProperty $member): ?self
    {
        $reflection = new ReflectionMember($member);

        if (!$self = $reflection->getAttribute(self::class)) {
            return null;
        }

        $self->memberName = $reflection->getMemberName();
        $self->sourceName = $reflection->getSourceName();

        $name = $reflection->getName();
        $type = $reflection->getType();

        if (!$reflection->hasDefaultValue()) {
            throw new LogicException(\sprintf('The option %s "$%s" of "%s" must declare a default value.', $self->memberName, $name, $self->sourceName));
        }

        if (!$self->name) {
            $self->name = (new UnicodeString($name))->kebab();
        }

        $self->default = $reflection->getDefaultValue();
        $self->allowNull = $reflection->isNullable();

        if ($type instanceof \ReflectionUnionType) {
            return $self->handleUnion($type);
        }

        if (!$type instanceof \ReflectionNamedType) {
            throw new LogicException(\sprintf('The %s "$%s" of "%s" must have a named type. Untyped or Intersection types are not supported for command options.', $self->memberName, $name, $self->sourceName));
        }

        $self->typeName = $type->getName();
        $isBackedEnum = is_subclass_of($self->typeName, \BackedEnum::class);

        if (!\in_array($self->typeName, self::ALLOWED_TYPES, true) && !$isBackedEnum) {
            throw new LogicException(\sprintf('The type "%s" on %s "$%s" of "%s" is not supported as a command option. Only "%s" types and BackedEnum are allowed.', $self->typeName, $self->memberName, $name, $self->sourceName, implode('", "', self::ALLOWED_TYPES)));
        }

        if ('bool' === $self->typeName && $self->allowNull && \in_array($self->default, [true, false], true)) {
            throw new LogicException(\sprintf('The option %s "$%s" of "%s" must not be nullable when it has a default boolean value.', $self->memberName, $name, $self->sourceName));
        }

        if ($self->allowNull && null !== $self->default) {
            throw new LogicException(\sprintf('The option %s "$%s" of "%s" must either be not-nullable or have a default of null.', $self->memberName, $name, $self->sourceName));
        }

        if ('bool' === $self->typeName) {
            $self->mode = InputOption::VALUE_NONE;
            if (false !== $self->default) {
                $self->mode |= InputOption::VALUE_NEGATABLE;
            }
        } elseif ('array' === $self->typeName) {
            $self->mode = InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY;
        } else {
            $self->mode = InputOption::VALUE_REQUIRED;
        }

        if (\is_array($self->suggestedValues) && !\is_callable($self->suggestedValues) && 2 === \count($self->suggestedValues) && ($instance = $reflection->getSourceThis()) && $instance::class === $self->suggestedValues[0] && \is_callable([$instance, $self->suggestedValues[1]])) {
            $self->suggestedValues = [$instance, $self->suggestedValues[1]];
        }

        if ($isBackedEnum && !$self->suggestedValues) {
            $self->suggestedValues = array_column($self->typeName::cases(), 'value');
        }

        return $self;
    }

    /**
     * @internal
     */
    public function toInputOption(): InputOption
    {
        $default = InputOption::VALUE_NONE === (InputOption::VALUE_NONE & $this->mode) ? null : $this->default;
        $suggestedValues = \is_callable($this->suggestedValues) ? ($this->suggestedValues)(...) : $this->suggestedValues;

        return new InputOption($this->name, $this->shortcut, $this->mode, $this->description, $default, $suggestedValues);
    }

    /**
     * @internal
     */
    public function resolveValue(InputInterface $input): mixed
    {
        $value = $input->getOption($this->name);

        if (null === $value && \in_array($this->typeName, self::ALLOWED_UNION_TYPES, true)) {
            return true;
        }

        if (is_subclass_of($this->typeName, \BackedEnum::class) && (\is_string($value) || \is_int($value))) {
            return $this->typeName::tryFrom($value) ?? throw InvalidOptionException::fromEnumValue($this->name, $value, $this->suggestedValues);
        }

        if ('array' === $this->typeName && $this->allowNull && [] === $value) {
            return null;
        }

        if ('bool' !== $this->typeName) {
            return $value;
        }

        if ($this->allowNull && null === $value) {
            return null;
        }

        return $value ?? $this->default;
    }

    private function handleUnion(\ReflectionUnionType $type): self
    {
        $types = array_map(
            static fn (\ReflectionType $t) => $t instanceof \ReflectionNamedType ? $t->getName() : null,
            $type->getTypes(),
        );

        sort($types);

        $this->typeName = implode('|', array_filter($types));

        if (!\in_array($this->typeName, self::ALLOWED_UNION_TYPES, true)) {
            throw new LogicException(\sprintf('The union type for %s "$%s" of "%s" is not supported as a command option. Only "%s" types are allowed.', $this->memberName, $this->name, $this->sourceName, implode('", "', self::ALLOWED_UNION_TYPES)));
        }

        if (false !== $this->default) {
            throw new LogicException(\sprintf('The option %s "$%s" of "%s" must have a default value of false.', $this->memberName, $this->name, $this->sourceName));
        }

        $this->mode = InputOption::VALUE_OPTIONAL;

        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

use Symfony\Component\Console\Attribute\Reflection\ReflectionMember;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Interaction\Interaction;

/**
 * Maps a command input into an object (DTO).
 */
#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
final class MapInput
{
    /**
     * @var array<string, Argument|Option|self>
     */
    private array $definition = [];

    private \ReflectionClass $class;

    /**
     * @var list<Interact>
     */
    private array $interactiveAttributes = [];

    /**
     * @internal
     */
    public static function tryFrom(\ReflectionParameter|\ReflectionProperty $member): ?self
    {
        $reflection = new ReflectionMember($member);

        if (!$self = $reflection->getAttribute(self::class)) {
            return null;
        }

        $type = $reflection->getType();

        if (!$type instanceof \ReflectionNamedType) {
            throw new LogicException(\sprintf('The input %s "%s" must have a named type.', $reflection->getMemberName(), $member->name));
        }

        if (!class_exists($class = $type->getName())) {
            throw new LogicException(\sprintf('The input class "%s" does not exist.', $type->getName()));
        }

        $self->class = new \ReflectionClass($class);

        foreach ($self->class->getProperties() as $property) {
            if ($argument = Argument::tryFrom($property)) {
                $self->definition[$property->name] = $argument;
            } elseif ($option = Option::tryFrom($property)) {
                $self->definition[$property->name] = $option;
            } elseif ($input = self::tryFrom($property)) {
                $self->definition[$property->name] = $input;
            }

            if (isset($self->definition[$property->name]) && (!$property->isPublic() || $property->isStatic())) {
                throw new LogicException(\sprintf('The input property "%s::$%s" must be public and non-static.', $self->class->name, $property->name));
            }
        }

        if (!$self->definition) {
            throw new LogicException(\sprintf('The input class "%s" must have at least one argument or option.', $self->class->name));
        }

        foreach ($self->class->getMethods() as $method) {
            if ($attribute = Interact::tryFrom($method)) {
                $self->interactiveAttributes[] = $attribute;
            }
        }

        return $self;
    }

    /**
     * @internal
     */
    public function resolveValue(InputInterface $input): object
    {
        $instance = $this->class->newInstanceWithoutConstructor();

        foreach ($this->definition as $name => $spec) {
            // ignore required arguments that are not set yet (may happen in interactive mode)
            if ($spec instanceof Argument && $spec->isRequired() && \in_array($input->getArgument($spec->name), [null, []], true)) {
                continue;
            }

            $instance->$name = $spec->resolveValue($input);
        }

        return $instance;
    }

    /**
     * @internal
     */
    public function setValue(InputInterface $input, object $object): void
    {
        foreach ($this->definition as $name => $spec) {
            $property = $this->class->getProperty($name);

            if (!$property->isInitialized($object) || \in_array($value = $property->getValue($object), [null, []], true)) {
                continue;
            }

            match (true) {
                $spec instanceof Argument => $input->setArgument($spec->name, $value),
                $spec instanceof Option => $input->setOption($spec->name, $value),
                $spec instanceof self => $spec->setValue($input, $value),
                default => throw new LogicException('Unexpected specification type.'),
            };
        }
    }

    /**
     * @return iterable<Argument>
     */
    public function getArguments(): iterable
    {
        foreach ($this->definition as $spec) {
            if ($spec instanceof Argument) {
                yield $spec;
            } elseif ($spec instanceof self) {
                yield from $spec->getArguments();
            }
        }
    }

    /**
     * @return iterable<Option>
     */
    public function getOptions(): iterable
    {
        foreach ($this->definition as $spec) {
            if ($spec instanceof Option) {
                yield $spec;
            } elseif ($spec instanceof self) {
                yield from $spec->getOptions();
            }
        }
    }

    /**
     * @internal
     *
     * @return iterable<Interaction>
     */
    public function getPropertyInteractions(): iterable
    {
        foreach ($this->definition as $spec) {
            if ($spec instanceof self) {
                yield from $spec->getPropertyInteractions();
            } elseif ($spec instanceof Argument && $attribute = $spec->getInteractiveAttribute()) {
                yield new Interaction($this, $attribute);
            }
        }
    }

    /**
     * @internal
     *
     * @return iterable<Interaction>
     */
    public function getMethodInteractions(): iterable
    {
        foreach ($this->definition as $spec) {
            if ($spec instanceof self) {
                yield from $spec->getMethodInteractions();
            }
        }

        foreach ($this->interactiveAttributes as $attribute) {
            yield new Interaction($this, $attribute);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

/**
 * Service tag to autoconfigure commands.
 *
 * @final since Symfony 7.3
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsCommand
{
    /**
     * @param string      $name        The name of the command, used when calling it (i.e. "cache:clear")
     * @param string|null $description The description of the command, displayed with the help page
     * @param string[]    $aliases     The list of aliases of the command. The command will be executed when using one of them (i.e. "cache:clean")
     * @param bool        $hidden      If true, the command won't be shown when listing all the available commands, but it can still be run as any other command
     * @param string|null $help        The help content of the command, displayed with the help page
     * @param string[]    $usages      The list of usage examples, displayed with the help page
     */
    public function __construct(
        public string $name,
        public ?string $description = null,
        array $aliases = [],
        bool $hidden = false,
        public ?string $help = null,
        public array $usages = [],
    ) {
        if (!$hidden && !$aliases) {
            return;
        }

        $name = explode('|', $name);
        $name = array_merge($name, $aliases);

        if ($hidden && '' !== $name[0]) {
            array_unshift($name, '');
        }

        $this->name = implode('|', $name);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

use Symfony\Component\Console\Attribute\Reflection\ReflectionMember;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\String\UnicodeString;

#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
class Argument
{
    private const ALLOWED_TYPES = ['string', 'bool', 'int', 'float', 'array'];

    private string|bool|int|float|array|null $default = null;
    private array|\Closure $suggestedValues;
    private ?int $mode = null;
    /**
     * @var string|class-string<\BackedEnum>
     */
    private string $typeName = '';
    private ?InteractiveAttributeInterface $interactiveAttribute = null;

    /**
     * Represents a console command <argument> definition.
     *
     * If unset, the `name` value will be inferred from the parameter definition.
     *
     * @param array<string|Suggestion>|callable(CompletionInput):list<string|Suggestion> $suggestedValues The values used for input completion
     */
    public function __construct(
        public string $description = '',
        public string $name = '',
        array|callable $suggestedValues = [],
    ) {
        $this->suggestedValues = \is_callable($suggestedValues) ? $suggestedValues(...) : $suggestedValues;
    }

    /**
     * @internal
     */
    public static function tryFrom(\ReflectionParameter|\ReflectionProperty $member): ?self
    {
        $reflection = new ReflectionMember($member);

        if (!$self = $reflection->getAttribute(self::class)) {
            return null;
        }

        $type = $reflection->getType();
        $name = $reflection->getName();

        if (!$type instanceof \ReflectionNamedType) {
            throw new LogicException(\sprintf('The %s "$%s" of "%s" must have a named type. Untyped, Union or Intersection types are not supported for command arguments.', $reflection->getMemberName(), $name, $reflection->getSourceName()));
        }

        $self->typeName = $type->getName();
        $isBackedEnum = is_subclass_of($self->typeName, \BackedEnum::class);

        if (!\in_array($self->typeName, self::ALLOWED_TYPES, true) && !$isBackedEnum) {
            throw new LogicException(\sprintf('The type "%s" on %s "$%s" of "%s" is not supported as a command argument. Only "%s" types and backed enums are allowed.', $self->typeName, $reflection->getMemberName(), $name, $reflection->getSourceName(), implode('", "', self::ALLOWED_TYPES)));
        }

        if (!$self->name) {
            $self->name = (new UnicodeString($name))->kebab();
        }

        $self->default = $reflection->hasDefaultValue() ? $reflection->getDefaultValue() : null;

        $isOptional = $reflection->hasDefaultValue() || $reflection->isNullable();
        $self->mode = $isOptional ? InputArgument::OPTIONAL : InputArgument::REQUIRED;
        if ('array' === $self->typeName) {
            $self->mode |= InputArgument::IS_ARRAY;
        }

        if (\is_array($self->suggestedValues) && !\is_callable($self->suggestedValues) && 2 === \count($self->suggestedValues) && ($instance = $reflection->getSourceThis()) && $instance::class === $self->suggestedValues[0] && \is_callable([$instance, $self->suggestedValues[1]])) {
            // In case that the callback is declared as a static method `[Foo::class, 'methodName']` - yet it is not callable,
            // while non-static method `[Foo $instance, 'methodName']` would be callable, we transform the callback on the fly into a non-static version.
            $self->suggestedValues = [$instance, $self->suggestedValues[1]];
        }

        if ($isBackedEnum && !$self->suggestedValues) {
            $self->suggestedValues = array_column($self->typeName::cases(), 'value');
        }

        $self->interactiveAttribute = Ask::tryFrom($member, $self->name);

        if ($self->interactiveAttribute && $isOptional) {
            throw new LogicException(\sprintf('The %s "$%s" argument of "%s" cannot be both interactive and optional.', $reflection->getMemberName(), $self->name, $reflection->getSourceName()));
        }

        return $self;
    }

    /**
     * @internal
     */
    public function toInputArgument(): InputArgument
    {
        $suggestedValues = \is_callable($this->suggestedValues) ? ($this->suggestedValues)(...) : $this->suggestedValues;

        return new InputArgument($this->name, $this->mode, $this->description, $this->default, $suggestedValues);
    }

    /**
     * @internal
     */
    public function resolveValue(InputInterface $input): mixed
    {
        $value = $input->getArgument($this->name);

        if (is_subclass_of($this->typeName, \BackedEnum::class) && (\is_string($value) || \is_int($value))) {
            return $this->typeName::tryFrom($value) ?? throw InvalidArgumentException::fromEnumValue($this->name, $value, $this->suggestedValues);
        }

        return $value;
    }

    /**
     * @internal
     */
    public function getInteractiveAttribute(): ?InteractiveAttributeInterface
    {
        return $this->interactiveAttribute;
    }

    /**
     * @internal
     */
    public function isRequired(): bool
    {
        return InputArgument::REQUIRED === (InputArgument::REQUIRED & $this->mode);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

/**
 * @internal
 */
interface InteractiveAttributeInterface
{
    public function getFunction(object $instance): \ReflectionFunction;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute\Reflection;

/**
 * @internal
 */
class ReflectionMember
{
    public function __construct(
        private readonly \ReflectionParameter|\ReflectionProperty $member,
    ) {
    }

    /**
     * @template T of object
     *
     * @param class-string<T> $class
     *
     * @return T|null
     */
    public function getAttribute(string $class): ?object
    {
        return ($this->member->getAttributes($class, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null)?->newInstance();
    }

    public function getSourceName(): string
    {
        if ($this->member instanceof \ReflectionProperty) {
            return $this->member->getDeclaringClass()->name;
        }

        $function = $this->member->getDeclaringFunction();

        if ($function instanceof \ReflectionMethod) {
            return $function->class.'::'.$function->name.'()';
        }

        return $function->name.'()';
    }

    public function getSourceThis(): ?object
    {
        if ($this->member instanceof \ReflectionParameter) {
            return $this->member->getDeclaringFunction()->getClosureThis();
        }

        return null;
    }

    public function getType(): ?\ReflectionType
    {
        return $this->member->getType();
    }

    public function getName(): string
    {
        return $this->member->getName();
    }

    public function hasDefaultValue(): bool
    {
        if ($this->member instanceof \ReflectionParameter) {
            return $this->member->isDefaultValueAvailable();
        }

        return $this->member->hasDefaultValue();
    }

    public function getDefaultValue(): mixed
    {
        $defaultValue = $this->member->getDefaultValue();

        if ($defaultValue instanceof \BackedEnum) {
            return $defaultValue->value;
        }

        return $defaultValue;
    }

    public function isNullable(): bool
    {
        return (bool) $this->member->getType()?->allowsNull();
    }

    public function getMemberName(): string
    {
        return $this->member instanceof \ReflectionParameter ? 'parameter' : 'property';
    }

    public function isParameter(): bool
    {
        return $this->member instanceof \ReflectionParameter;
    }

    public function isProperty(): bool
    {
        return $this->member instanceof \ReflectionProperty;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

use Symfony\Component\Console\Exception\LogicException;

#[\Attribute(\Attribute::TARGET_METHOD)]
class Interact implements InteractiveAttributeInterface
{
    private \ReflectionMethod $method;

    /**
     * @internal
     */
    public static function tryFrom(\ReflectionMethod $method): ?self
    {
        /** @var self|null $self */
        if (!$self = ($method->getAttributes(self::class)[0] ?? null)?->newInstance()) {
            return null;
        }

        if (!$method->isPublic() || $method->isStatic()) {
            throw new LogicException(\sprintf('The interactive method "%s::%s()" must be public and non-static.', $method->getDeclaringClass()->getName(), $method->getName()));
        }

        if ('__invoke' === $method->getName()) {
            throw new LogicException(\sprintf('The "%s::__invoke()" method cannot be used as an interactive method.', $method->getDeclaringClass()->getName()));
        }

        $self->method = $method;

        return $self;
    }

    /**
     * @internal
     */
    public function getFunction(object $instance): \ReflectionFunction
    {
        return new \ReflectionFunction($this->method->getClosure($instance));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Attribute;

use Symfony\Component\Console\Attribute\Reflection\ReflectionMember;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;

#[\Attribute(\Attribute::TARGET_PARAMETER | \Attribute::TARGET_PROPERTY)]
class Ask implements InteractiveAttributeInterface
{
    public ?\Closure $normalizer;
    public ?\Closure $validator;
    private \Closure $closure;

    /**
     * @param string                     $question    The question to ask the user
     * @param string|bool|int|float|null $default     The default answer to return if the user enters nothing
     * @param bool                       $hidden      Whether the user response must be hidden or not
     * @param bool                       $multiline   Whether the user response should accept newline characters
     * @param bool                       $trimmable   Whether the user response must be trimmed or not
     * @param int|null                   $timeout     The maximum time the user has to answer the question in seconds
     * @param callable|null              $validator   The validator for the question
     * @param int|null                   $maxAttempts The maximum number of attempts allowed to answer the question.
     *                                                Null means an unlimited number of attempts
     */
    public function __construct(
        public string $question,
        public string|bool|int|float|null $default = null,
        public bool $hidden = false,
        public bool $multiline = false,
        public bool $trimmable = true,
        public ?int $timeout = null,
        ?callable $normalizer = null,
        ?callable $validator = null,
        public ?int $maxAttempts = null,
    ) {
        $this->normalizer = $normalizer ? $normalizer(...) : null;
        $this->validator = $validator ? $validator(...) : null;
    }

    /**
     * @internal
     */
    public static function tryFrom(\ReflectionParameter|\ReflectionProperty $member, string $name): ?self
    {
        $reflection = new ReflectionMember($member);

        if (!$self = $reflection->getAttribute(self::class)) {
            return null;
        }

        $type = $reflection->getType();

        if (!$type instanceof \ReflectionNamedType) {
            throw new LogicException(\sprintf('The %s "$%s" of "%s" must have a named type. Untyped, Union or Intersection types are not supported for interactive questions.', $reflection->getMemberName(), $name, $reflection->getSourceName()));
        }

        $self->closure = function (SymfonyStyle $io, InputInterface $input) use ($self, $reflection, $name, $type) {
            if ($reflection->isProperty() && isset($this->{$reflection->getName()})) {
                return;
            }

            if ($reflection->isParameter() && !\in_array($input->getArgument($name), [null, []], true)) {
                return;
            }

            if ('bool' === $type->getName()) {
                $self->default ??= false;

                if (!\is_bool($self->default)) {
                    throw new LogicException(\sprintf('The "%s::$default" value for the %s "$%s" of "%s" must be a boolean.', self::class, $reflection->getMemberName(), $name, $reflection->getSourceName()));
                }

                $question = new ConfirmationQuestion($self->question, $self->default);
            } else {
                $question = new Question($self->question, $self->default);
            }
            $question->setHidden($self->hidden);
            $question->setMultiline($self->multiline);
            $question->setTrimmable($self->trimmable);
            $question->setTimeout($self->timeout);

            if (!$self->validator && $reflection->isProperty() && 'array' !== $type->getName()) {
                $self->validator = fn (mixed $value): mixed => $this->{$reflection->getName()} = $value;
            }

            $question->setValidator($self->validator);
            $question->setMaxAttempts($self->maxAttempts);

            if ($self->normalizer) {
                $question->setNormalizer($self->normalizer);
            } elseif (is_subclass_of($type->getName(), \BackedEnum::class)) {
                /** @var class-string<\BackedEnum> $backedType */
                $backedType = $reflection->getType()->getName();
                $question->setNormalizer(static fn (string|int $value) => $backedType::tryFrom($value) ?? throw InvalidArgumentException::fromEnumValue($reflection->getName(), $value, array_column($backedType::cases(), 'value')));
            }

            if ('array' === $type->getName()) {
                $value = [];
                while ($v = $io->askQuestion($question)) {
                    if ("\x4" === $v || \PHP_EOL === $v || ($question->isTrimmable() && '' === $v = trim($v))) {
                        break;
                    }
                    $value[] = $v;
                }
            } else {
                $value = $io->askQuestion($question);
            }

            if (null === $value && !$reflection->isNullable()) {
                return;
            }

            if ($reflection->isProperty()) {
                $this->{$reflection->getName()} = $value;
            } else {
                $input->setArgument($name, $value);
            }
        };

        return $self;
    }

    /**
     * @internal
     */
    public function getFunction(object $instance): \ReflectionFunction
    {
        return new \ReflectionFunction($this->closure->bindTo($instance, $instance::class));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleSignalEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;

/**
 * Contains all events dispatched by an Application.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleEvents
{
    /**
     * The COMMAND event allows you to attach listeners before any command is
     * executed by the console. It also allows you to modify the command, input and output
     * before they are handed to the command.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
     */
    public const COMMAND = 'console.command';

    /**
     * The SIGNAL event allows you to perform some actions
     * after the command execution was interrupted.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent")
     */
    public const SIGNAL = 'console.signal';

    /**
     * The TERMINATE event allows you to attach listeners after a command is
     * executed by the console.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
     */
    public const TERMINATE = 'console.terminate';

    /**
     * The ERROR event occurs when an uncaught exception or error appears.
     *
     * This event allows you to deal with the exception/error or
     * to modify the thrown exception.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
     */
    public const ERROR = 'console.error';

    /**
     * Event aliases.
     *
     * These aliases can be consumed by RegisterListenersPass.
     */
    public const ALIASES = [
        ConsoleCommandEvent::class => self::COMMAND,
        ConsoleErrorEvent::class => self::ERROR,
        ConsoleSignalEvent::class => self::SIGNAL,
        ConsoleTerminateEvent::class => self::TERMINATE,
    ];
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Debug;

use Symfony\Component\Console\Command\TraceableCommand;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * @internal
 */
final class CliRequest extends Request
{
    public function __construct(
        public readonly TraceableCommand $command,
    ) {
        parent::__construct(
            attributes: ['_controller' => $command->command::class, '_virtual_type' => 'command'],
            server: $_SERVER,
        );
    }

    // Methods below allow to populate a profile, thus enable search and filtering
    public function getUri(): string
    {
        if ($this->server->has('SYMFONY_CLI_BINARY_NAME')) {
            $binary = $this->server->get('SYMFONY_CLI_BINARY_NAME').' console';
        } else {
            $binary = $this->server->get('argv')[0];
        }

        return $binary.' '.$this->command->input;
    }

    public function getMethod(): string
    {
        return $this->command->isInteractive ? 'INTERACTIVE' : 'BATCH';
    }

    public function getResponse(): Response
    {
        return new class($this->command->exitCode) extends Response {
            public function __construct(private readonly int $exitCode)
            {
                parent::__construct();
            }

            public function getStatusCode(): int
            {
                return $this->exitCode;
            }
        };
    }

    public function getClientIp(): string
    {
        $application = $this->command->getApplication();

        return $application->getName().' '.$application->getVersion();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BufferedOutput extends Output
{
    private string $buffer = '';

    /**
     * Empties buffer and returns its content.
     */
    public function fetch(): string
    {
        $content = $this->buffer;
        $this->buffer = '';

        return $content;
    }

    protected function doWrite(string $message, bool $newline): void
    {
        $this->buffer .= $message;

        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * StreamOutput writes the output to a given stream.
 *
 * Usage:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * As `StreamOutput` can use any stream, you can also use a file:
 *
 *     $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StreamOutput extends Output
{
    /** @var resource */
    private $stream;

    /**
     * @param resource                      $stream    A stream resource
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool|null                     $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @throws InvalidArgumentException When first argument is not a real stream
     */
    public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null)
    {
        if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) {
            throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
        }

        $this->stream = $stream;

        $decorated ??= $this->hasColorSupport();

        parent::__construct($verbosity, $decorated, $formatter);
    }

    /**
     * Gets the stream attached to this StreamOutput instance.
     *
     * @return resource
     */
    public function getStream()
    {
        return $this->stream;
    }

    protected function doWrite(string $message, bool $newline): void
    {
        if ($newline) {
            $message .= \PHP_EOL;
        }

        @fwrite($this->stream, $message);

        fflush($this->stream);
    }

    /**
     * Returns true if the stream supports colorization.
     *
     * Colorization is disabled if not supported by the stream:
     *
     * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo
     * terminals via named pipes, so we can only check the environment.
     *
     * Reference: Composer\XdebugHandler\Process::supportsColor
     * https://github.com/composer/xdebug-handler
     *
     * @return bool true if the stream supports colorization, false otherwise
     */
    protected function hasColorSupport(): bool
    {
        // Follow https://no-color.org/
        if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) {
            return false;
        }

        // Follow https://force-color.org/
        if ('' !== (($_SERVER['FORCE_COLOR'] ?? getenv('FORCE_COLOR'))[0] ?? '')) {
            return true;
        }

        // Detect msysgit/mingw and assume this is a tty because detection
        // does not work correctly, see https://github.com/composer/composer/issues/9690
        if (!@stream_isatty($this->stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) {
            return false;
        }

        if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($this->stream)) {
            return true;
        }

        if ('Hyper' === getenv('TERM_PROGRAM')
            || false !== getenv('COLORTERM')
            || false !== getenv('ANSICON')
            || 'ON' === getenv('ConEmuANSI')
        ) {
            return true;
        }

        if ('dumb' === $term = (string) getenv('TERM')) {
            return false;
        }

        // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157
        return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

/**
 * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
 * This adds information about stderr and section output stream.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface ConsoleOutputInterface extends OutputInterface
{
    /**
     * Gets the OutputInterface for errors.
     */
    public function getErrorOutput(): OutputInterface;

    public function setErrorOutput(OutputInterface $error): void;

    public function section(): ConsoleSectionOutput;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Terminal;

/**
 * @author Pierre du Plessis <pdples@gmail.com>
 * @author Gabriel Ostrolucký <gabriel.ostrolucky@gmail.com>
 */
class ConsoleSectionOutput extends StreamOutput
{
    private array $content = [];
    private int $lines = 0;
    private array $sections;
    private Terminal $terminal;
    private int $maxHeight = 0;

    /**
     * @param resource               $stream
     * @param ConsoleSectionOutput[] $sections
     */
    public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter)
    {
        parent::__construct($stream, $verbosity, $decorated, $formatter);
        array_unshift($sections, $this);
        $this->sections = &$sections;
        $this->terminal = new Terminal();
    }

    /**
     * Defines a maximum number of lines for this section.
     *
     * When more lines are added, the section will automatically scroll to the
     * end (i.e. remove the first lines to comply with the max height).
     */
    public function setMaxHeight(int $maxHeight): void
    {
        // when changing max height, clear output of current section and redraw again with the new height
        $previousMaxHeight = $this->maxHeight;
        $this->maxHeight = $maxHeight;
        $existingContent = $this->popStreamContentUntilCurrentSection($previousMaxHeight ? min($previousMaxHeight, $this->lines) : $this->lines);

        parent::doWrite($this->getVisibleContent(), false);
        parent::doWrite($existingContent, false);
    }

    /**
     * Clears previous output for this section.
     *
     * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared
     */
    public function clear(?int $lines = null): void
    {
        if (!$this->content || !$this->isDecorated()) {
            return;
        }

        if ($lines) {
            array_splice($this->content, -$lines);
        } else {
            $lines = $this->lines;
            $this->content = [];
        }

        $this->lines -= $lines;

        parent::doWrite($this->popStreamContentUntilCurrentSection($this->maxHeight ? min($this->maxHeight, $lines) : $lines), false);
    }

    /**
     * Overwrites the previous output with a new message.
     */
    public function overwrite(string|iterable $message): void
    {
        if (!$this->content || !$this->isDecorated()) {
            $this->writeln($message);

            return;
        }

        // Replace own content and write everything in a single cursor-up + erase
        // pass, to avoid the flicker (and the line-eating artifacts on some
        // terminals) caused by calling clear() then writeln() back-to-back.
        $linesCleared = $this->lines;
        $this->content = [];
        $this->lines = 0;

        if (!is_iterable($message)) {
            $message = [$message];
        }

        foreach ($message as $line) {
            $this->addContent($line, true);
        }

        $erasedContent = $this->popStreamContentUntilCurrentSection($this->maxHeight ? min($this->maxHeight, $linesCleared) : $linesCleared);

        parent::doWrite($this->getVisibleContent(), false);
        parent::doWrite($erasedContent, false);
    }

    public function getContent(): string
    {
        return implode('', $this->content);
    }

    public function getVisibleContent(): string
    {
        if (0 === $this->maxHeight) {
            return $this->getContent();
        }

        return implode('', \array_slice($this->content, -$this->maxHeight));
    }

    /**
     * @internal
     */
    public function addContent(string $input, bool $newline = true): int
    {
        $width = $this->terminal->getWidth();
        $lines = explode(\PHP_EOL, $input);
        $linesAdded = 0;
        $count = \count($lines) - 1;
        foreach ($lines as $i => $lineContent) {
            // re-add the line break (that has been removed in the above `explode()` for
            // - every line that is not the last line
            // - if $newline is required, also add it to the last line
            if ($i < $count || $newline) {
                $lineContent .= \PHP_EOL;
            }

            // skip line if there is no text (or newline for that matter)
            if ('' === $lineContent) {
                continue;
            }

            // For the first line, check if the previous line (last entry of `$this->content`)
            // needs to be continued (i.e. does not end with a line break).
            if (0 === $i
                && (false !== $lastLine = end($this->content))
                && !str_ends_with($lastLine, \PHP_EOL)
            ) {
                // deduct the line count of the previous line
                $this->lines -= (int) ceil($this->getDisplayLength($lastLine) / $width) ?: 1;
                // concatenate previous and new line
                $lineContent = $lastLine.$lineContent;
                // replace last entry of `$this->content` with the new expanded line
                array_splice($this->content, -1, 1, $lineContent);
            } else {
                // otherwise just add the new content
                $this->content[] = $lineContent;
            }

            $linesAdded += (int) ceil($this->getDisplayLength($lineContent) / $width) ?: 1;
        }

        $this->lines += $linesAdded;

        return $linesAdded;
    }

    /**
     * @internal
     */
    public function addNewLineOfInputSubmit(): void
    {
        $this->content[] = \PHP_EOL;
        ++$this->lines;
    }

    protected function doWrite(string $message, bool $newline): void
    {
        // Simulate newline behavior for consistent output formatting, avoiding extra logic
        if (!$newline && str_ends_with($message, \PHP_EOL)) {
            $message = substr($message, 0, -\strlen(\PHP_EOL));
            $newline = true;
        }

        if (!$this->isDecorated()) {
            parent::doWrite($message, $newline);

            return;
        }

        // Check if the previous line (last entry of `$this->content`) needs to be continued
        // (i.e. does not end with a line break). In which case, it needs to be erased first.
        $linesToClear = $deleteLastLine = ($lastLine = end($this->content) ?: '') && !str_ends_with($lastLine, \PHP_EOL) ? 1 : 0;

        $linesAdded = $this->addContent($message, $newline);

        if ($lineOverflow = $this->maxHeight > 0 && $this->lines > $this->maxHeight) {
            // on overflow, clear the whole section and redraw again (to remove the first lines)
            $linesToClear = $this->maxHeight;
        }

        $erasedContent = $this->popStreamContentUntilCurrentSection($linesToClear);

        if ($lineOverflow) {
            // redraw existing lines of the section
            $previousLinesOfSection = \array_slice($this->content, $this->lines - $this->maxHeight, $this->maxHeight - $linesAdded);
            parent::doWrite(implode('', $previousLinesOfSection), false);
        }

        // if the last line was removed, re-print its content together with the new content.
        // otherwise, just print the new content.
        parent::doWrite($deleteLastLine ? $lastLine.$message : $message, true);
        parent::doWrite($erasedContent, false);
    }

    /**
     * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits
     * current section. Then it erases content it crawled through. Optionally, it erases part of current section too.
     */
    private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string
    {
        $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection;
        $erasedContent = [];

        foreach ($this->sections as $section) {
            if ($section === $this) {
                break;
            }

            $numberOfLinesToClear += $section->maxHeight ? min($section->lines, $section->maxHeight) : $section->lines;
            if ('' !== $sectionContent = $section->getVisibleContent()) {
                if (!str_ends_with($sectionContent, \PHP_EOL)) {
                    $sectionContent .= \PHP_EOL;
                }
                $erasedContent[] = $sectionContent;
            }
        }

        if ($numberOfLinesToClear > 0) {
            // move cursor up n lines
            parent::doWrite(\sprintf("\x1b[%dA", $numberOfLinesToClear), false);
            // erase to end of screen
            parent::doWrite("\x1b[0J", false);
        }

        return implode('', array_reverse($erasedContent));
    }

    private function getDisplayLength(string $text): int
    {
        return Helper::width(Helper::removeDecoration($this->getFormatter(), str_replace("\t", '        ', $text)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\NullOutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * NullOutput suppresses all output.
 *
 *     $output = new NullOutput();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class NullOutput implements OutputInterface
{
    private NullOutputFormatter $formatter;

    public function setFormatter(OutputFormatterInterface $formatter): void
    {
        // do nothing
    }

    public function getFormatter(): OutputFormatterInterface
    {
        // to comply with the interface we must return a OutputFormatterInterface
        return $this->formatter ??= new NullOutputFormatter();
    }

    public function setDecorated(bool $decorated): void
    {
        // do nothing
    }

    public function isDecorated(): bool
    {
        return false;
    }

    public function setVerbosity(int $level): void
    {
        // do nothing
    }

    public function getVerbosity(): int
    {
        return self::VERBOSITY_SILENT;
    }

    public function isSilent(): bool
    {
        return true;
    }

    public function isQuiet(): bool
    {
        return false;
    }

    public function isVerbose(): bool
    {
        return false;
    }

    public function isVeryVerbose(): bool
    {
        return false;
    }

    public function isDebug(): bool
    {
        return false;
    }

    public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL): void
    {
        // do nothing
    }

    public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL): void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * OutputInterface is the interface implemented by all Output classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @method bool isSilent()
 */
interface OutputInterface
{
    public const VERBOSITY_SILENT = 8;
    public const VERBOSITY_QUIET = 16;
    public const VERBOSITY_NORMAL = 32;
    public const VERBOSITY_VERBOSE = 64;
    public const VERBOSITY_VERY_VERBOSE = 128;
    public const VERBOSITY_DEBUG = 256;

    public const OUTPUT_NORMAL = 1;
    public const OUTPUT_RAW = 2;
    public const OUTPUT_PLAIN = 4;

    /**
     * Writes a message to the output.
     *
     * @param bool $newline Whether to add a newline
     * @param int  $options A bitmask of options (one of the OUTPUT or VERBOSITY constants),
     *                      0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     */
    public function write(string|iterable $messages, bool $newline = false, int $options = 0): void;

    /**
     * Writes a message to the output and adds a newline at the end.
     *
     * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants),
     *                     0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     */
    public function writeln(string|iterable $messages, int $options = 0): void;

    /**
     * Sets the verbosity of the output.
     *
     * @param self::VERBOSITY_* $level
     */
    public function setVerbosity(int $level): void;

    /**
     * Gets the current verbosity of the output.
     *
     * @return self::VERBOSITY_*
     */
    public function getVerbosity(): int;

    /**
     * Returns whether verbosity is quiet (-q).
     */
    public function isQuiet(): bool;

    /**
     * Returns whether verbosity is verbose (-v).
     */
    public function isVerbose(): bool;

    /**
     * Returns whether verbosity is very verbose (-vv).
     */
    public function isVeryVerbose(): bool;

    /**
     * Returns whether verbosity is debug (-vvv).
     */
    public function isDebug(): bool;

    /**
     * Sets the decorated flag.
     */
    public function setDecorated(bool $decorated): void;

    /**
     * Gets the decorated flag.
     */
    public function isDecorated(): bool;

    public function setFormatter(OutputFormatterInterface $formatter): void;

    /**
     * Returns current output formatter instance.
     */
    public function getFormatter(): OutputFormatterInterface;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * A BufferedOutput that keeps only the last N chars.
 *
 * @author Jérémy Derussé <jeremy@derusse.com>
 */
class TrimmedBufferOutput extends Output
{
    private int $maxLength;
    private string $buffer = '';

    public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null)
    {
        if ($maxLength <= 0) {
            throw new InvalidArgumentException(\sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength));
        }

        parent::__construct($verbosity, $decorated, $formatter);
        $this->maxLength = $maxLength;
    }

    /**
     * Empties buffer and returns its content.
     */
    public function fetch(): string
    {
        $content = $this->buffer;
        $this->buffer = '';

        return $content;
    }

    protected function doWrite(string $message, bool $newline): void
    {
        $this->buffer .= $message;

        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }

        $this->buffer = substr($this->buffer, -$this->maxLength);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * Base class for output classes.
 *
 * There are six levels of verbosity:
 *
 *  * normal: no option passed (normal output)
 *  * verbose: -v (more output)
 *  * very verbose: -vv (highly extended output)
 *  * debug: -vvv (all debug output)
 *  * quiet: -q (only output errors)
 *  * silent: --silent (no output)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Output implements OutputInterface
{
    private int $verbosity;
    private OutputFormatterInterface $formatter;

    /**
     * @param int|null                      $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool                          $decorated Whether to decorate messages
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null)
    {
        $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL;
        $this->formatter = $formatter ?? new OutputFormatter();
        $this->formatter->setDecorated($decorated);
    }

    public function setFormatter(OutputFormatterInterface $formatter): void
    {
        $this->formatter = $formatter;
    }

    public function getFormatter(): OutputFormatterInterface
    {
        return $this->formatter;
    }

    public function setDecorated(bool $decorated): void
    {
        $this->formatter->setDecorated($decorated);
    }

    public function isDecorated(): bool
    {
        return $this->formatter->isDecorated();
    }

    public function setVerbosity(int $level): void
    {
        $this->verbosity = $level;
    }

    public function getVerbosity(): int
    {
        return $this->verbosity;
    }

    public function isSilent(): bool
    {
        return self::VERBOSITY_SILENT === $this->verbosity;
    }

    public function isQuiet(): bool
    {
        return self::VERBOSITY_QUIET === $this->verbosity;
    }

    public function isVerbose(): bool
    {
        return self::VERBOSITY_VERBOSE <= $this->verbosity;
    }

    public function isVeryVerbose(): bool
    {
        return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
    }

    public function isDebug(): bool
    {
        return self::VERBOSITY_DEBUG <= $this->verbosity;
    }

    public function writeln(string|iterable $messages, int $options = self::OUTPUT_NORMAL): void
    {
        $this->write($messages, true, $options);
    }

    public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL): void
    {
        if (!is_iterable($messages)) {
            $messages = [$messages];
        }

        $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
        $type = $types & $options ?: self::OUTPUT_NORMAL;

        $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
        $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;

        if ($verbosity > $this->getVerbosity()) {
            return;
        }

        foreach ($messages as $message) {
            switch ($type) {
                case OutputInterface::OUTPUT_NORMAL:
                    $message = $this->formatter->format($message);
                    break;
                case OutputInterface::OUTPUT_RAW:
                    break;
                case OutputInterface::OUTPUT_PLAIN:
                    $message = strip_tags($this->formatter->format($message));
                    break;
            }

            $this->doWrite($message ?? '', $newline);
        }
    }

    /**
     * Writes a message to the output.
     */
    abstract protected function doWrite(string $message, bool $newline): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Julien Boudry <julien@condorcet.vote>
 */
enum AnsiColorMode
{
    /*
     * Classical 4-bit Ansi colors, including 8 classical colors and 8 bright color. Output syntax is "ESC[${foreGroundColorcode};${backGroundColorcode}m"
     * Must be compatible with all terminals and it's the minimal version supported.
     */
    case Ansi4;

    /*
     * 8-bit Ansi colors (240 different colors + 16 duplicate color codes, ensuring backward compatibility).
     * Output syntax is: "ESC[38;5;${foreGroundColorcode};48;5;${backGroundColorcode}m"
     * Should be compatible with most terminals.
     */
    case Ansi8;

    /*
     * 24-bit Ansi colors (RGB).
     * Output syntax is: "ESC[38;2;${foreGroundColorcodeRed};${foreGroundColorcodeGreen};${foreGroundColorcodeBlue};48;2;${backGroundColorcodeRed};${backGroundColorcodeGreen};${backGroundColorcodeBlue}m"
     * May be compatible with many modern terminals.
     */
    case Ansi24;

    /**
     * Converts an RGB hexadecimal color to the corresponding Ansi code.
     */
    public function convertFromHexToAnsiColorCode(string $hexColor): string
    {
        $hexColor = str_replace('#', '', $hexColor);

        if (3 === \strlen($hexColor)) {
            $hexColor = $hexColor[0].$hexColor[0].$hexColor[1].$hexColor[1].$hexColor[2].$hexColor[2];
        }

        if (6 !== \strlen($hexColor)) {
            throw new InvalidArgumentException(\sprintf('Invalid "#%s" color.', $hexColor));
        }

        $color = hexdec($hexColor);

        $r = ($color >> 16) & 255;
        $g = ($color >> 8) & 255;
        $b = $color & 255;

        return match ($this) {
            self::Ansi4 => (string) $this->convertFromRGB($r, $g, $b),
            self::Ansi8 => '8;5;'.$this->convertFromRGB($r, $g, $b),
            self::Ansi24 => \sprintf('8;2;%d;%d;%d', $r, $g, $b),
        };
    }

    private function convertFromRGB(int $r, int $g, int $b): int
    {
        return match ($this) {
            self::Ansi4 => $this->degradeHexColorToAnsi4($r, $g, $b),
            self::Ansi8 => $this->degradeHexColorToAnsi8($r, $g, $b),
            default => throw new InvalidArgumentException("RGB cannot be converted to {$this->name}."),
        };
    }

    private function degradeHexColorToAnsi4(int $r, int $g, int $b): int
    {
        return round($b / 255) << 2 | (round($g / 255) << 1) | round($r / 255);
    }

    /**
     * Inspired from https://github.com/ajalt/colormath/blob/e464e0da1b014976736cf97250063248fc77b8e7/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/Ansi256.kt code (MIT license).
     */
    private function degradeHexColorToAnsi8(int $r, int $g, int $b): int
    {
        if ($r === $g && $g === $b) {
            if ($r < 8) {
                return 16;
            }

            if ($r > 248) {
                return 231;
            }

            return (int) round(($r - 8) / 247 * 24) + 232;
        }

        return 16 +
            (36 * (int) round($r / 255 * 5)) +
            (6 * (int) round($g / 255 * 5)) +
            (int) round($b / 255 * 5);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.
 *
 * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR.
 *
 *     $output = new ConsoleOutput();
 *
 * This is equivalent to:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *     $stdErr = new StreamOutput(fopen('php://stderr', 'w'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
    private OutputInterface $stderr;
    private array $consoleSectionOutputs = [];

    /**
     * @param int                           $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool|null                     $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct(int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null)
    {
        parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);

        if (null === $formatter) {
            // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter.
            $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated);

            return;
        }

        $actualDecorated = $this->isDecorated();
        $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());

        if (null === $decorated) {
            $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
        }
    }

    /**
     * Creates a new output section.
     */
    public function section(): ConsoleSectionOutput
    {
        return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter());
    }

    public function setDecorated(bool $decorated): void
    {
        parent::setDecorated($decorated);
        $this->stderr->setDecorated($decorated);
    }

    public function setFormatter(OutputFormatterInterface $formatter): void
    {
        parent::setFormatter($formatter);
        $this->stderr->setFormatter($formatter);
    }

    public function setVerbosity(int $level): void
    {
        parent::setVerbosity($level);
        $this->stderr->setVerbosity($level);
    }

    public function getErrorOutput(): OutputInterface
    {
        return $this->stderr;
    }

    public function setErrorOutput(OutputInterface $error): void
    {
        $this->stderr = $error;
    }

    /**
     * Returns true if current environment supports writing console output to
     * STDOUT.
     */
    protected function hasStdoutSupport(): bool
    {
        return false === $this->isRunningOS400();
    }

    /**
     * Returns true if current environment supports writing console output to
     * STDERR.
     */
    protected function hasStderrSupport(): bool
    {
        return false === $this->isRunningOS400();
    }

    /**
     * Checks if current executing environment is IBM iSeries (OS400), which
     * doesn't properly convert character-encodings between ASCII to EBCDIC.
     */
    private function isRunningOS400(): bool
    {
        $checks = [
            \function_exists('php_uname') ? php_uname('s') : '',
            getenv('OSTYPE'),
            \PHP_OS,
        ];

        return false !== stripos(implode(';', $checks), 'OS400');
    }

    /**
     * @return resource
     */
    private function openOutputStream()
    {
        static $stdout;

        if ($stdout) {
            return $stdout;
        }

        if (!$this->hasStdoutSupport()) {
            return $stdout = fopen('php://output', 'w');
        }

        // Use STDOUT when possible to prevent from opening too many file descriptors
        if (!\defined('STDOUT')) {
            return $stdout = @fopen('php://stdout', 'w') ?: fopen('php://output', 'w');
        }

        // On Windows, STDOUT is opened in text mode; reopen in binary mode to prevent \n to \r\n conversion
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $stdout = @fopen('php://stdout', 'w') ?: \STDOUT;
        }

        return $stdout = \STDOUT;
    }

    /**
     * @return resource
     */
    private function openErrorStream()
    {
        static $stderr;

        if ($stderr) {
            return $stderr;
        }

        if (!$this->hasStderrSupport()) {
            return $stderr = fopen('php://output', 'w');
        }

        // Use STDERR when possible to prevent from opening too many file descriptors
        if (!\defined('STDERR')) {
            return $stderr = @fopen('php://stderr', 'w') ?: fopen('php://output', 'w');
        }

        // On Windows, STDERR is opened in text mode; reopen in binary mode to prevent \n → \r\n conversion
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $stderr = @fopen('php://stderr', 'w') ?: \STDERR;
        }

        return $stderr ??= \STDERR;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Descriptor\ApplicationDescription;
use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * HelpCommand displays the help for a given command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelpCommand extends Command
{
    private Command $command;

    protected function configure(): void
    {
        $this->ignoreValidationErrors();

        $this
            ->setName('help')
            ->setDefinition([
                new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help', fn () => array_keys((new ApplicationDescription($this->getApplication()))->getCommands())),
                new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', static fn () => (new DescriptorHelper())->getFormats()),
                new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
            ])
            ->setDescription('Display help for a command')
            ->setHelp(<<<'EOF'
                The <info>%command.name%</info> command displays help for a given command:

                  <info>%command.full_name% list</info>

                You can also output the help in other formats by using the <info>--format</info> option:

                  <info>%command.full_name% --format=xml list</info>

                To display the list of available commands, please use the <info>list</info> command.
                EOF
            )
        ;
    }

    public function setCommand(Command $command): void
    {
        $this->command = $command;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->command ??= $this->getApplication()->find($input->getArgument('command_name'));

        $helper = new DescriptorHelper();
        $helper->describe($output, $this->command, [
            'format' => $input->getOption('format'),
            'raw_text' => $input->getOption('raw'),
        ]);

        unset($this->command);

        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\LockInterface;
use Symfony\Component\Lock\Store\FlockStore;
use Symfony\Component\Lock\Store\SemaphoreStore;

/**
 * Basic lock feature for commands.
 *
 * @author Geoffrey Brier <geoffrey.brier@gmail.com>
 */
trait LockableTrait
{
    private ?LockInterface $lock = null;

    private ?LockFactory $lockFactory = null;

    /**
     * Locks a command.
     */
    private function lock(?string $name = null, bool $blocking = false): bool
    {
        if (!class_exists(SemaphoreStore::class)) {
            throw new LogicException('To enable the locking feature you must install the symfony/lock component. Try running "composer require symfony/lock".');
        }

        if (null !== $this->lock) {
            throw new LogicException('A lock is already in place.');
        }

        if (null === $this->lockFactory) {
            if (SemaphoreStore::isSupported()) {
                $store = new SemaphoreStore();
            } else {
                $store = new FlockStore();
            }

            $this->lockFactory = new LockFactory($store);
        }

        if (!$name) {
            if ($this instanceof Command) {
                $name = $this->getName();
            } elseif ($attribute = (new \ReflectionClass($this::class))->getAttributes(AsCommand::class)) {
                $name = $attribute[0]->newInstance()->name;
            } else {
                throw new LogicException(\sprintf('Lock name missing: provide it via "%s()", #[AsCommand] attribute, or by extending Command class.', __METHOD__));
            }
        }

        $this->lock = $this->lockFactory->createLock($name);
        if (!$this->lock->acquire($blocking)) {
            $this->lock = null;

            return false;
        }

        return true;
    }

    /**
     * Releases the command lock if there is one.
     */
    private function release(): void
    {
        if ($this->lock) {
            $this->lock->release();
            $this->lock = null;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LazyCommand extends Command
{
    private \Closure|Command $command;

    public function __construct(
        string $name,
        array $aliases,
        string $description,
        bool $isHidden,
        \Closure $commandFactory,
        private ?bool $isEnabled = true,
    ) {
        $this->setName($name)
            ->setAliases($aliases)
            ->setHidden($isHidden)
            ->setDescription($description);

        $this->command = $commandFactory;
    }

    public function ignoreValidationErrors(): void
    {
        $this->getCommand()->ignoreValidationErrors();
    }

    public function setApplication(?Application $application): void
    {
        if ($this->command instanceof parent) {
            $this->command->setApplication($application);
        }

        parent::setApplication($application);
    }

    public function setHelperSet(HelperSet $helperSet): void
    {
        if ($this->command instanceof parent) {
            $this->command->setHelperSet($helperSet);
        }

        parent::setHelperSet($helperSet);
    }

    public function isEnabled(): bool
    {
        return $this->isEnabled ?? $this->getCommand()->isEnabled();
    }

    public function run(InputInterface $input, OutputInterface $output): int
    {
        return $this->getCommand()->run($input, $output);
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $this->getCommand()->complete($input, $suggestions);
    }

    public function setCode(callable $code): static
    {
        $this->getCommand()->setCode($code);

        return $this;
    }

    /**
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = true): void
    {
        $this->getCommand()->mergeApplicationDefinition($mergeArgs);
    }

    public function setDefinition(array|InputDefinition $definition): static
    {
        $this->getCommand()->setDefinition($definition);

        return $this;
    }

    public function getDefinition(): InputDefinition
    {
        return $this->getCommand()->getDefinition();
    }

    public function getNativeDefinition(): InputDefinition
    {
        return $this->getCommand()->getNativeDefinition();
    }

    /**
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     */
    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->getCommand()->addArgument($name, $mode, $description, $default, $suggestedValues);

        return $this;
    }

    /**
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     */
    public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);

        return $this;
    }

    public function setProcessTitle(string $title): static
    {
        $this->getCommand()->setProcessTitle($title);

        return $this;
    }

    public function setHelp(string $help): static
    {
        $this->getCommand()->setHelp($help);

        return $this;
    }

    public function getHelp(): string
    {
        return $this->getCommand()->getHelp();
    }

    public function getProcessedHelp(): string
    {
        return $this->getCommand()->getProcessedHelp();
    }

    public function getSynopsis(bool $short = false): string
    {
        return $this->getCommand()->getSynopsis($short);
    }

    public function addUsage(string $usage): static
    {
        $this->getCommand()->addUsage($usage);

        return $this;
    }

    public function getUsages(): array
    {
        return $this->getCommand()->getUsages();
    }

    public function getHelper(string $name): HelperInterface
    {
        return $this->getCommand()->getHelper($name);
    }

    public function getCommand(): parent
    {
        if (!$this->command instanceof \Closure) {
            return $this->command;
        }

        $command = $this->command = ($this->command)();
        $command->setApplication($this->getApplication());

        if (null !== $this->getHelperSet()) {
            $command->setHelperSet($this->getHelperSet());
        }

        $command->setName($this->getName())
            ->setAliases($this->getAliases())
            ->setHidden($this->isHidden())
            ->setDescription($this->getDescription());

        // Will throw if the command is not correctly initialized.
        $command->getDefinition();

        return $command;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Base class for all commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Command implements SignalableCommandInterface
{
    // see https://tldp.org/LDP/abs/html/exitcodes.html
    public const SUCCESS = 0;
    public const FAILURE = 1;
    public const INVALID = 2;

    private ?Application $application = null;
    private ?string $name = null;
    private ?string $processTitle = null;
    private array $aliases = [];
    private InputDefinition $definition;
    private bool $hidden = false;
    private string $help = '';
    private string $description = '';
    private ?InputDefinition $fullDefinition = null;
    private bool $ignoreValidationErrors = false;
    private ?InvokableCommand $code = null;
    private array $synopsis = [];
    private array $usages = [];
    private ?HelperSet $helperSet = null;

    /**
     * @deprecated since Symfony 7.3, use the #[AsCommand] attribute instead
     */
    public static function getDefaultName(): ?string
    {
        trigger_deprecation('symfony/console', '7.3', 'Method "%s()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', __METHOD__);

        if ($attribute = (new \ReflectionClass(static::class))->getAttributes(AsCommand::class)) {
            return $attribute[0]->newInstance()->name;
        }

        return null;
    }

    /**
     * @deprecated since Symfony 7.3, use the #[AsCommand] attribute instead
     */
    public static function getDefaultDescription(): ?string
    {
        trigger_deprecation('symfony/console', '7.3', 'Method "%s()" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', __METHOD__);

        if ($attribute = (new \ReflectionClass(static::class))->getAttributes(AsCommand::class)) {
            return $attribute[0]->newInstance()->description;
        }

        return null;
    }

    /**
     * @param string|null $name The name of the command; passing null means it must be set in configure()
     *
     * @throws LogicException When the command name is empty
     */
    public function __construct(?string $name = null, ?callable $code = null)
    {
        if (null !== $code) {
            if (!\is_object($code) || $code instanceof \Closure) {
                throw new InvalidArgumentException(\sprintf('The command must be an instance of "%s" or an invokable object.', self::class));
            }
            /** @var AsCommand $attribute */
            $attribute = ((new \ReflectionObject($code))->getAttributes(AsCommand::class)[0] ?? null)?->newInstance()
                ?? throw new LogicException(\sprintf('The command must use the "%s" attribute.', AsCommand::class));
            $this->setCode($code);
        } else {
            $attribute = ((new \ReflectionClass(static::class))->getAttributes(AsCommand::class)[0] ?? null)?->newInstance();
        }

        $this->definition = new InputDefinition();
        if (null === $name) {
            if (self::class !== (new \ReflectionMethod($this, 'getDefaultName'))->class) {
                trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultName()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', static::class);

                $name = static::getDefaultName();
            } else {
                $name = $attribute?->name;
            }
        }

        if (null !== $name) {
            $aliases = explode('|', $name);

            if ('' === $name = array_shift($aliases)) {
                $this->setHidden(true);
                $name = array_shift($aliases);
            }

            // we must not overwrite existing aliases, combine new ones with existing ones
            $aliases = array_unique([
                ...$this->aliases,
                ...$aliases,
            ]);

            $this->setAliases($aliases);
        }

        if (null !== $name) {
            $this->setName($name);
        }

        if ('' === $this->description) {
            if (self::class !== (new \ReflectionMethod($this, 'getDefaultDescription'))->class) {
                trigger_deprecation('symfony/console', '7.3', 'Overriding "Command::getDefaultDescription()" in "%s" is deprecated and will be removed in Symfony 8.0, use the #[AsCommand] attribute instead.', static::class);

                $defaultDescription = static::getDefaultDescription();
            } else {
                $defaultDescription = $attribute?->description;
            }

            $this->setDescription($defaultDescription ?? '');
        }

        if ('' === $this->help) {
            $this->setHelp($attribute?->help ?? '');
        }

        foreach ($attribute?->usages ?? [] as $usage) {
            $this->addUsage($usage);
        }

        if (!$code && \is_callable($this) && self::class === (new \ReflectionMethod($this, 'execute'))->getDeclaringClass()->name) {
            $this->code = new InvokableCommand($this, $this(...));
        }

        $this->configure();
    }

    /**
     * Ignores validation errors.
     *
     * This is mainly useful for the help command.
     */
    public function ignoreValidationErrors(): void
    {
        $this->ignoreValidationErrors = true;
    }

    public function setApplication(?Application $application): void
    {
        $this->application = $application;
        if ($application) {
            $this->setHelperSet($application->getHelperSet());
        } else {
            $this->helperSet = null;
        }

        $this->fullDefinition = null;
    }

    public function setHelperSet(HelperSet $helperSet): void
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Gets the helper set.
     */
    public function getHelperSet(): ?HelperSet
    {
        return $this->helperSet;
    }

    /**
     * Gets the application instance for this command.
     */
    public function getApplication(): ?Application
    {
        return $this->application;
    }

    /**
     * Checks whether the command is enabled or not in the current environment.
     *
     * Override this to check for x or y and return false if the command cannot
     * run properly under the current conditions.
     */
    public function isEnabled(): bool
    {
        return true;
    }

    /**
     * Configures the current command.
     *
     * @return void
     */
    protected function configure()
    {
    }

    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @return int 0 if everything went fine, or an exit code
     *
     * @throws LogicException When this abstract method is not implemented
     *
     * @see setCode()
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        throw new LogicException('You must override the execute() method in the concrete command class.');
    }

    /**
     * Interacts with the user.
     *
     * This method is executed before the InputDefinition is validated.
     * This means that this is the only place where the command can
     * interactively ask for values of missing required arguments.
     *
     * @return void
     */
    protected function interact(InputInterface $input, OutputInterface $output)
    {
    }

    /**
     * Initializes the command after the input has been bound and before the input
     * is validated.
     *
     * This is mainly useful when a lot of commands extends one main command
     * where some things need to be initialized based on the input arguments and options.
     *
     * @see InputInterface::bind()
     * @see InputInterface::validate()
     *
     * @return void
     */
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
    }

    /**
     * Runs the command.
     *
     * The code to execute is either defined directly with the
     * setCode() method or by overriding the execute() method
     * in a sub-class.
     *
     * @return int The command exit code
     *
     * @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}.
     *
     * @see setCode()
     * @see execute()
     */
    public function run(InputInterface $input, OutputInterface $output): int
    {
        // add the application arguments and options
        $this->mergeApplicationDefinition();

        // bind the input against the command specific arguments/options
        try {
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface $e) {
            if (!$this->ignoreValidationErrors) {
                throw $e;
            }
        }

        $this->initialize($input, $output);

        if (null !== $this->processTitle) {
            if (\function_exists('cli_set_process_title')) {
                if (!@cli_set_process_title($this->processTitle)) {
                    if ('Darwin' === \PHP_OS) {
                        $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
                    } else {
                        cli_set_process_title($this->processTitle);
                    }
                }
            } elseif (\function_exists('setproctitle')) {
                setproctitle($this->processTitle);
            } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
                $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
            }
        }

        if ($input->isInteractive()) {
            $this->interact($input, $output);

            if ($this->code?->isInteractive()) {
                $this->code->interact($input, $output);
            }
        }

        // The command name argument is often omitted when a command is executed directly with its run() method.
        // It would fail the validation if we didn't make sure the command argument is present,
        // since it's required by the application.
        if ($input->hasArgument('command') && null === $input->getArgument('command')) {
            $input->setArgument('command', $this->getName());
        }

        $input->validate();

        if ($this->code) {
            return ($this->code)($input, $output);
        }

        return $this->execute($input, $output);
    }

    /**
     * Supplies suggestions when resolving possible completion options for input (e.g. option or argument).
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $definition = $this->getDefinition();
        if (CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType() && $definition->hasOption($input->getCompletionName())) {
            $definition->getOption($input->getCompletionName())->complete($input, $suggestions);
        } elseif (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && $definition->hasArgument($input->getCompletionName())) {
            $definition->getArgument($input->getCompletionName())->complete($input, $suggestions);
        }
    }

    /**
     * Gets the code that is executed by the command.
     *
     * @return ?callable null if the code has not been set with setCode()
     */
    public function getCode(): ?callable
    {
        return $this->code?->getCode();
    }

    /**
     * Sets the code to execute when running this command.
     *
     * If this method is used, it overrides the code defined
     * in the execute() method.
     *
     * @param callable $code A callable(InputInterface $input, OutputInterface $output)
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     *
     * @see execute()
     */
    public function setCode(callable $code): static
    {
        $this->code = new InvokableCommand($this, $code);

        return $this;
    }

    /**
     * Merges the application definition with the command definition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
     *
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = true): void
    {
        if (null === $this->application) {
            return;
        }

        $this->fullDefinition = new InputDefinition();
        $this->fullDefinition->setOptions($this->definition->getOptions());
        $this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());

        if ($mergeArgs) {
            $this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
            $this->fullDefinition->addArguments($this->definition->getArguments());
        } else {
            $this->fullDefinition->setArguments($this->definition->getArguments());
        }
    }

    /**
     * Sets an array of argument and option instances.
     *
     * @return $this
     */
    public function setDefinition(array|InputDefinition $definition): static
    {
        if ($definition instanceof InputDefinition) {
            $this->definition = $definition;
        } else {
            $this->definition->setDefinition($definition);
        }

        $this->fullDefinition = null;

        return $this;
    }

    /**
     * Gets the InputDefinition attached to this Command.
     */
    public function getDefinition(): InputDefinition
    {
        return $this->fullDefinition ?? $this->getNativeDefinition();
    }

    /**
     * Gets the InputDefinition to be used to create representations of this Command.
     *
     * Can be overridden to provide the original command representation when it would otherwise
     * be changed by merging with the application InputDefinition.
     *
     * This method is not part of public API and should not be used directly.
     */
    public function getNativeDefinition(): InputDefinition
    {
        $definition = $this->definition ?? throw new LogicException(\sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));

        if ($this->code && !$definition->getArguments() && !$definition->getOptions()) {
            $this->code->configure($definition);
        }

        return $definition;
    }

    /**
     * Adds an argument.
     *
     * @param                                                                               $mode            The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
     * @param                                                                               $default         The default value (for InputArgument::OPTIONAL mode only)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @return $this
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->definition->addArgument(new InputArgument($name, $mode, $description, $default, $suggestedValues));
        $this->fullDefinition?->addArgument(new InputArgument($name, $mode, $description, $default, $suggestedValues));

        return $this;
    }

    /**
     * Adds an option.
     *
     * @param                                                                               $shortcut        The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param                                                                               $mode            The option mode: One of the InputOption::VALUE_* constants
     * @param                                                                               $default         The default value (must be null for InputOption::VALUE_NONE)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @return $this
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default, $suggestedValues));
        $this->fullDefinition?->addOption(new InputOption($name, $shortcut, $mode, $description, $default, $suggestedValues));

        return $this;
    }

    /**
     * Sets the name of the command.
     *
     * This method can set both the namespace and the name if
     * you separate them by a colon (:)
     *
     *     $command->setName('foo:bar');
     *
     * @return $this
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    public function setName(string $name): static
    {
        $this->validateName($name);

        $this->name = $name;

        return $this;
    }

    /**
     * Sets the process title of the command.
     *
     * This feature should be used only when creating a long process command,
     * like a daemon.
     *
     * @return $this
     */
    public function setProcessTitle(string $title): static
    {
        $this->processTitle = $title;

        return $this;
    }

    /**
     * Returns the command name.
     */
    public function getName(): ?string
    {
        return $this->name;
    }

    /**
     * @param bool $hidden Whether or not the command should be hidden from the list of commands
     *
     * @return $this
     */
    public function setHidden(bool $hidden = true): static
    {
        $this->hidden = $hidden;

        return $this;
    }

    /**
     * @return bool whether the command should be publicly shown or not
     */
    public function isHidden(): bool
    {
        return $this->hidden;
    }

    /**
     * Sets the description for the command.
     *
     * @return $this
     */
    public function setDescription(string $description): static
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Returns the description for the command.
     */
    public function getDescription(): string
    {
        return $this->description;
    }

    /**
     * Sets the help for the command.
     *
     * @return $this
     */
    public function setHelp(string $help): static
    {
        $this->help = $help;

        return $this;
    }

    /**
     * Returns the help for the command.
     */
    public function getHelp(): string
    {
        return $this->help;
    }

    /**
     * Returns the processed help for the command replacing the %command.name% and
     * %command.full_name% patterns with the real values dynamically.
     */
    public function getProcessedHelp(): string
    {
        $name = $this->name;
        $isSingleCommand = $this->application?->isSingleCommand();

        $placeholders = [
            '%command.name%',
            '%command.full_name%',
        ];
        $replacements = [
            $name,
            $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name,
        ];

        return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
    }

    /**
     * Sets the aliases for the command.
     *
     * @param string[] $aliases An array of aliases for the command
     *
     * @return $this
     *
     * @throws InvalidArgumentException When an alias is invalid
     */
    public function setAliases(iterable $aliases): static
    {
        $list = [];

        foreach ($aliases as $alias) {
            $this->validateName($alias);
            $list[] = $alias;
        }

        $this->aliases = \is_array($aliases) ? $aliases : $list;

        return $this;
    }

    /**
     * Returns the aliases for the command.
     */
    public function getAliases(): array
    {
        return $this->aliases;
    }

    /**
     * Returns the synopsis for the command.
     *
     * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
     */
    public function getSynopsis(bool $short = false): string
    {
        $key = $short ? 'short' : 'long';

        if (!isset($this->synopsis[$key])) {
            $this->synopsis[$key] = trim(\sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
        }

        return $this->synopsis[$key];
    }

    /**
     * Add a command usage example, it'll be prefixed with the command name.
     *
     * @return $this
     */
    public function addUsage(string $usage): static
    {
        if (!str_starts_with($usage, $this->name)) {
            $usage = \sprintf('%s %s', $this->name, $usage);
        }

        $this->usages[] = $usage;

        return $this;
    }

    /**
     * Returns alternative usages of the command.
     */
    public function getUsages(): array
    {
        return $this->usages;
    }

    /**
     * Gets a helper instance by name.
     *
     * @throws LogicException           if no HelperSet is defined
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function getHelper(string $name): HelperInterface
    {
        if (null === $this->helperSet) {
            throw new LogicException(\sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
        }

        return $this->helperSet->get($name);
    }

    public function getSubscribedSignals(): array
    {
        return $this->code?->getSubscribedSignals() ?? [];
    }

    public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
    {
        return $this->code?->handleSignal($signal, $previousExitCode) ?? false;
    }

    /**
     * Validates a command name.
     *
     * It must be non-empty and parts can optionally be separated by ":".
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    private function validateName(string $name): void
    {
        if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
            throw new InvalidArgumentException(\sprintf('Command name "%s" is invalid.', $name));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

/**
 * Interface for command reacting to signal.
 *
 * @author Grégoire Pineau <lyrixx@lyrix.info>
 */
interface SignalableCommandInterface
{
    /**
     * Returns the list of signals to subscribe.
     *
     * @return list<\SIG*>
     *
     * @see https://php.net/pcntl.constants for signals
     */
    public function getSubscribedSignals(): array;

    /**
     * The method will be called when the application is signaled.
     *
     * @return int|false The exit code to return or false to continue the normal execution
     */
    public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;

/**
 * Dumps the completion script for the current shell.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
#[AsCommand(name: 'completion', description: 'Dump the shell completion script')]
final class DumpCompletionCommand extends Command
{
    private array $supportedShells;

    protected function configure(): void
    {
        $fullCommand = $_SERVER['PHP_SELF'];
        $commandName = basename($fullCommand);
        $fullCommand = @realpath($fullCommand) ?: $fullCommand;

        $shell = self::guessShell();
        [$rcFile, $completionFile] = match ($shell) {
            'fish' => ['~/.config/fish/config.fish', "/etc/fish/completions/$commandName.fish"],
            'zsh' => ['~/.zshrc', '$fpath[1]/_'.$commandName],
            default => ['~/.bashrc', "/etc/bash_completion.d/$commandName"],
        };

        $supportedShells = implode(', ', $this->getSupportedShells());

        $this
            ->setHelp(<<<EOH
                The <info>%command.name%</> command dumps the shell completion script required
                to use shell autocompletion (currently, {$supportedShells} completion are supported).

                <comment>Static installation
                -------------------</>

                Dump the script to a global completion file and restart your shell:

                    <info>%command.full_name% {$shell} | sudo tee {$completionFile}</>

                Or dump the script to a local file and source it:

                    <info>%command.full_name% {$shell} > completion.sh</>

                    <comment># source the file whenever you use the project</>
                    <info>source completion.sh</>

                    <comment># or add this line at the end of your "{$rcFile}" file:</>
                    <info>source /path/to/completion.sh</>

                <comment>Dynamic installation
                --------------------</>

                Add this to the end of your shell configuration file (e.g. <info>"{$rcFile}"</>):

                    <info>eval "$({$fullCommand} completion {$shell})"</>
                EOH
            )
            ->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given', null, $this->getSupportedShells(...))
            ->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $commandName = basename($_SERVER['argv'][0]);

        if ($input->getOption('debug')) {
            $this->tailDebugLog($commandName, $output);

            return 0;
        }

        $shell = $input->getArgument('shell') ?? self::guessShell();
        $completionFile = __DIR__.'/../Resources/completion.'.$shell;
        if (!file_exists($completionFile)) {
            $supportedShells = $this->getSupportedShells();

            if ($output instanceof ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            if ($shell) {
                $output->writeln(\sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells)));
            } else {
                $output->writeln(\sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells)));
            }

            return 2;
        }

        $output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, CompleteCommand::COMPLETION_API_VERSION], file_get_contents($completionFile)));

        return 0;
    }

    private static function guessShell(): string
    {
        return basename($_SERVER['SHELL'] ?? '');
    }

    private function tailDebugLog(string $commandName, OutputInterface $output): void
    {
        $debugFile = sys_get_temp_dir().'/sf_'.$commandName.'.log';
        if (!file_exists($debugFile)) {
            touch($debugFile);
        }
        $process = new Process(['tail', '-f', $debugFile], null, null, null, 0);
        $process->run(static function (string $type, string $line) use ($output): void {
            $output->write($line);
        });
    }

    /**
     * @return string[]
     */
    private function getSupportedShells(): array
    {
        if (isset($this->supportedShells)) {
            return $this->supportedShells;
        }

        $shells = [];

        foreach (new \DirectoryIterator(__DIR__.'/../Resources/') as $file) {
            if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) {
                $shells[] = $file->getExtension();
            }
        }
        sort($shells);

        return $this->supportedShells = $shells;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Output\BashCompletionOutput;
use Symfony\Component\Console\Completion\Output\CompletionOutputInterface;
use Symfony\Component\Console\Completion\Output\FishCompletionOutput;
use Symfony\Component\Console\Completion\Output\ZshCompletionOutput;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Responsible for providing the values to the shell completion.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
#[AsCommand(name: '|_complete', description: 'Internal command to provide shell completion suggestions')]
final class CompleteCommand extends Command
{
    public const COMPLETION_API_VERSION = '1';

    private array $completionOutputs;
    private bool $isDebug = false;

    /**
     * @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value
     */
    public function __construct(array $completionOutputs = [])
    {
        // must be set before the parent constructor, as the property value is used in configure()
        $this->completionOutputs = $completionOutputs + [
            'bash' => BashCompletionOutput::class,
            'fish' => FishCompletionOutput::class,
            'zsh' => ZshCompletionOutput::class,
        ];

        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")')
            ->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)')
            ->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)')
            ->addOption('api-version', 'a', InputOption::VALUE_REQUIRED, 'The API version of the completion script')
            ->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'deprecated')
        ;
    }

    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        $this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOL);
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        try {
            // "symfony" must be kept for compat with the shell scripts generated by Symfony Console 5.4 - 6.1
            $version = $input->getOption('symfony') ? '1' : $input->getOption('api-version');
            if ($version && version_compare($version, self::COMPLETION_API_VERSION, '<')) {
                $message = \sprintf('Completion script version is not supported ("%s" given, ">=%s" required).', $version, self::COMPLETION_API_VERSION);
                $this->log($message);

                $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.');

                return 126;
            }

            $shell = $input->getOption('shell');
            if (!$shell) {
                throw new \RuntimeException('The "--shell" option must be set.');
            }

            if (!$completionOutput = $this->completionOutputs[$shell] ?? false) {
                throw new \RuntimeException(\sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs))));
            }

            $completionInput = $this->createCompletionInput($input);
            $suggestions = new CompletionSuggestions();

            $this->log([
                '',
                '<comment>'.date('Y-m-d H:i:s').'</>',
                '<info>Input:</> <comment>("|" indicates the cursor position)</>',
                '  '.$completionInput,
                '<info>Command:</>',
                '  '.implode(' ', $_SERVER['argv']),
                '<info>Messages:</>',
            ]);

            if ($command = $this->findCommand($completionInput)) {
                $command->mergeApplicationDefinition();
                $completionInput->bind($command->getDefinition());
            }
            if (null === $command) {
                $this->log('  No command found, completing using the Application class.');

                $this->getApplication()->complete($completionInput, $suggestions);
            } elseif (
                $completionInput->mustSuggestArgumentValuesFor('command')
            ) {
                $this->log('  Command found, completing command name.');

                // expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear")
                $commandNames = array_filter(array_merge([$command->getName()], $command->getAliases()));
                foreach ($commandNames as $name) {
                    if (str_starts_with($name, $completionInput->getCompletionValue())) {
                        $commandNames = [$name];
                        break;
                    }
                }
                $suggestions->suggestValues($commandNames);
            } else {
                if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) {
                    $this->log('  Completing option names for the <comment>'.($command instanceof LazyCommand ? $command->getCommand() : $command)::class.'</> command.');

                    $suggestions->suggestOptions($command->getDefinition()->getOptions());
                } else {
                    $this->log([
                        '  Completing using the <comment>'.($command instanceof LazyCommand ? $command->getCommand() : $command)::class.'</> class.',
                        '  Completing <comment>'.$completionInput->getCompletionType().'</> for <comment>'.$completionInput->getCompletionName().'</>',
                    ]);
                    if (null !== $compval = $completionInput->getCompletionValue()) {
                        $this->log('  Current value: <comment>'.$compval.'</>');
                    }

                    $command->complete($completionInput, $suggestions);
                }
            }

            /** @var CompletionOutputInterface $completionOutput */
            $completionOutput = new $completionOutput();

            $this->log('<info>Suggestions:</>');
            if ($options = $suggestions->getOptionSuggestions()) {
                $this->log('  --'.implode(' --', array_map(static fn ($o) => $o->getName(), $options)));
            } elseif ($values = $suggestions->getValueSuggestions()) {
                $this->log('  '.implode(' ', $values));
            } else {
                $this->log('  <comment>No suggestions were provided</>');
            }

            $completionOutput->write($suggestions, $output);
        } catch (\Throwable $e) {
            $this->log([
                '<error>Error!</error>',
                (string) $e,
            ]);

            if ($output->isDebug()) {
                throw $e;
            }

            return 2;
        }

        return 0;
    }

    private function createCompletionInput(InputInterface $input): CompletionInput
    {
        $currentIndex = $input->getOption('current');
        if (!$currentIndex || !ctype_digit($currentIndex)) {
            throw new \RuntimeException('The "--current" option must be set and it must be an integer.');
        }

        $completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex);

        try {
            $completionInput->bind($this->getApplication()->getDefinition());
        } catch (ExceptionInterface) {
        }

        return $completionInput;
    }

    private function findCommand(CompletionInput $completionInput): ?Command
    {
        try {
            $inputName = $completionInput->getFirstArgument();
            if (null === $inputName) {
                return null;
            }

            return $this->getApplication()->find($inputName);
        } catch (CommandNotFoundException) {
        }

        return null;
    }

    private function log($messages): void
    {
        if (!$this->isDebug) {
            return;
        }

        $commandName = basename($_SERVER['argv'][0]);
        file_put_contents(sys_get_temp_dir().'/sf_'.$commandName.'.log', implode(\PHP_EOL, (array) $messages).\PHP_EOL, \FILE_APPEND);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Attribute\Argument;
use Symfony\Component\Console\Attribute\Interact;
use Symfony\Component\Console\Attribute\MapInput;
use Symfony\Component\Console\Attribute\Option;
use Symfony\Component\Console\Cursor;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Interaction\Interaction;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Represents an invokable command.
 *
 * @author Yonel Ceruto <open@yceruto.dev>
 *
 * @internal
 */
class InvokableCommand implements SignalableCommandInterface
{
    private readonly ?SignalableCommandInterface $signalableCommand;
    private readonly \ReflectionFunction $invokable;
    /**
     * @var list<Interaction>|null
     */
    private ?array $interactions = null;
    private bool $triggerDeprecations = false;
    private $code;

    public function __construct(
        private readonly Command $command,
        callable $code,
    ) {
        $this->code = $code;
        $this->signalableCommand = $code instanceof SignalableCommandInterface ? $code : null;
        $this->invokable = new \ReflectionFunction($this->getClosure($code));
    }

    /**
     * Invokes a callable with parameters generated from the input interface.
     */
    public function __invoke(InputInterface $input, OutputInterface $output): int
    {
        $statusCode = $this->invokable->invoke(...$this->getParameters($this->invokable, $input, $output));

        if (!\is_int($statusCode)) {
            if ($this->triggerDeprecations) {
                trigger_deprecation('symfony/console', '7.3', \sprintf('Returning a non-integer value from the command "%s" is deprecated and will throw an exception in Symfony 8.0.', $this->command->getName()));

                return 0;
            }

            throw new \TypeError(\sprintf('The command "%s" must return an integer value in the "%s" method, but "%s" was returned.', $this->command->getName(), $this->invokable->getName(), get_debug_type($statusCode)));
        }

        return $statusCode;
    }

    /**
     * Configures the input definition from an invokable-defined function.
     *
     * Processes the parameters of the reflection function to extract and
     * add arguments or options to the provided input definition.
     */
    public function configure(InputDefinition $definition): void
    {
        foreach ($this->invokable->getParameters() as $parameter) {
            if ($argument = Argument::tryFrom($parameter)) {
                $definition->addArgument($argument->toInputArgument());
                continue;
            }

            if ($option = Option::tryFrom($parameter)) {
                $definition->addOption($option->toInputOption());
                continue;
            }

            if ($input = MapInput::tryFrom($parameter)) {
                $inputArguments = array_map(static fn (Argument $a) => $a->toInputArgument(), iterator_to_array($input->getArguments(), false));

                // make sure optional arguments are defined after required ones
                usort($inputArguments, static fn (InputArgument $a, InputArgument $b) => (int) $b->isRequired() - (int) $a->isRequired());

                foreach ($inputArguments as $inputArgument) {
                    $definition->addArgument($inputArgument);
                }

                foreach ($input->getOptions() as $option) {
                    $definition->addOption($option->toInputOption());
                }
            }
        }
    }

    public function getCode(): callable
    {
        return $this->code;
    }

    private function getClosure(callable $code): \Closure
    {
        if (!$code instanceof \Closure) {
            return $code(...);
        }

        $this->triggerDeprecations = true;

        if (null !== (new \ReflectionFunction($code))->getClosureThis()) {
            return $code;
        }

        set_error_handler(static function () {});
        try {
            if ($c = \Closure::bind($code, $this->command)) {
                $code = $c;
            }
        } finally {
            restore_error_handler();
        }

        return $code;
    }

    private function getParameters(\ReflectionFunction $function, InputInterface $input, OutputInterface $output): array
    {
        $parameters = [];
        foreach ($function->getParameters() as $parameter) {
            if ($argument = Argument::tryFrom($parameter)) {
                $parameters[] = $argument->resolveValue($input);

                continue;
            }

            if ($option = Option::tryFrom($parameter)) {
                $parameters[] = $option->resolveValue($input);

                continue;
            }

            if ($in = MapInput::tryFrom($parameter)) {
                $parameters[] = $in->resolveValue($input);

                continue;
            }

            $type = $parameter->getType();

            if (!$type instanceof \ReflectionNamedType) {
                if ($this->triggerDeprecations) {
                    trigger_deprecation('symfony/console', '7.3', \sprintf('Omitting the type declaration for the parameter "$%s" is deprecated and will throw an exception in Symfony 8.0.', $parameter->getName()));

                    continue;
                }

                throw new LogicException(\sprintf('The parameter "$%s" must have a named type. Untyped, Union or Intersection types are not supported.', $parameter->getName()));
            }

            $parameters[] = match ($type->getName()) {
                InputInterface::class => $input,
                OutputInterface::class => $output,
                Cursor::class => new Cursor($output),
                SymfonyStyle::class => new SymfonyStyle($input, $output),
                Application::class => $this->command->getApplication(),
                default => throw new RuntimeException(\sprintf('Unsupported type "%s" for parameter "$%s".', $type->getName(), $parameter->getName())),
            };
        }

        return $parameters ?: [$input, $output];
    }

    public function getSubscribedSignals(): array
    {
        return $this->signalableCommand?->getSubscribedSignals() ?? [];
    }

    public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
    {
        return $this->signalableCommand?->handleSignal($signal, $previousExitCode) ?? false;
    }

    public function isInteractive(): bool
    {
        if (null === $this->interactions) {
            $this->collectInteractions();
        }

        return [] !== $this->interactions;
    }

    public function interact(InputInterface $input, OutputInterface $output): void
    {
        if (null === $this->interactions) {
            $this->collectInteractions();
        }

        foreach ($this->interactions as $interaction) {
            $interaction->interact($input, $output, $this->getParameters(...));
        }
    }

    private function collectInteractions(): void
    {
        $invokableThis = $this->invokable->getClosureThis();

        $this->interactions = [];
        foreach ($this->invokable->getParameters() as $parameter) {
            if ($spec = Argument::tryFrom($parameter)) {
                if ($attribute = $spec->getInteractiveAttribute()) {
                    $this->interactions[] = new Interaction($invokableThis, $attribute);
                }

                continue;
            }

            if ($spec = MapInput::tryFrom($parameter)) {
                $this->interactions = [...$this->interactions, ...$spec->getPropertyInteractions(), ...$spec->getMethodInteractions()];
            }
        }

        if (!$class = $this->invokable->getClosureCalledClass()) {
            return;
        }

        foreach ($class->getMethods() as $method) {
            if ($attribute = Interact::tryFrom($method)) {
                $this->interactions[] = new Interaction($invokableThis, $attribute);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Stopwatch\Stopwatch;

/**
 * @internal
 *
 * @author Jules Pietri <jules@heahprod.com>
 */
final class TraceableCommand extends Command
{
    public readonly Command $command;
    public int $exitCode;
    public ?int $interruptedBySignal = null;
    public bool $ignoreValidation;
    public bool $isInteractive = false;
    public string $duration = 'n/a';
    public string $maxMemoryUsage = 'n/a';
    public InputInterface $input;
    public OutputInterface $output;
    /** @var array<string, mixed> */
    public array $arguments;
    /** @var array<string, mixed> */
    public array $options;
    /** @var array<string, mixed> */
    public array $interactiveInputs = [];
    public array $handledSignals = [];
    public ?array $invokableCommandInfo = null;

    public function __construct(
        Command $command,
        private readonly Stopwatch $stopwatch,
    ) {
        if ($command instanceof LazyCommand) {
            $command = $command->getCommand();
        }

        $this->command = $command;

        // prevent call to self::getDefaultDescription()
        $this->setDescription($command->getDescription());

        parent::__construct($command->getName());

        // init below enables calling {@see parent::run()}
        [$code, $processTitle, $ignoreValidationErrors] = \Closure::bind(fn () => [$this->code, $this->processTitle, $this->ignoreValidationErrors], $command, Command::class)();

        if (\is_callable($code)) {
            $this->setCode($code);
        }

        if ($processTitle) {
            parent::setProcessTitle($processTitle);
        }

        if ($ignoreValidationErrors) {
            parent::ignoreValidationErrors();
        }

        $this->ignoreValidation = $ignoreValidationErrors;
    }

    public function __call(string $name, array $arguments): mixed
    {
        return $this->command->{$name}(...$arguments);
    }

    public function getSubscribedSignals(): array
    {
        return $this->command->getSubscribedSignals();
    }

    public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
    {
        $event = $this->stopwatch->start($this->getName().'.handle_signal');

        $exit = $this->command->handleSignal($signal, $previousExitCode);

        $event->stop();

        if (!isset($this->handledSignals[$signal])) {
            $this->handledSignals[$signal] = [
                'handled' => 0,
                'duration' => 0,
                'memory' => 0,
            ];
        }

        ++$this->handledSignals[$signal]['handled'];
        $this->handledSignals[$signal]['duration'] += $event->getDuration();
        $this->handledSignals[$signal]['memory'] = max(
            $this->handledSignals[$signal]['memory'],
            $event->getMemory() >> 20
        );

        return $exit;
    }

    /**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    public function ignoreValidationErrors(): void
    {
        $this->ignoreValidation = true;
        $this->command->ignoreValidationErrors();

        parent::ignoreValidationErrors();
    }

    public function setApplication(?Application $application = null): void
    {
        $this->command->setApplication($application);
    }

    public function getApplication(): ?Application
    {
        return $this->command->getApplication();
    }

    public function setHelperSet(HelperSet $helperSet): void
    {
        $this->command->setHelperSet($helperSet);
    }

    public function getHelperSet(): ?HelperSet
    {
        return $this->command->getHelperSet();
    }

    public function isEnabled(): bool
    {
        return $this->command->isEnabled();
    }

    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $this->command->complete($input, $suggestions);
    }

    /**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    public function setCode(callable $code): static
    {
        if ($code instanceof InvokableCommand) {
            $r = \Closure::bind(fn () => $this->invokable, $code, InvokableCommand::class)();

            $this->invokableCommandInfo = [
                'class' => $r->getClosureScopeClass()->name,
                'file' => $r->getFileName(),
                'line' => $r->getStartLine(),
            ];

            // Pass the original callable to avoid double-wrapping in Command::setCode()
            $this->command->setCode($code->getCode());
        } else {
            $this->command->setCode($code);
        }

        return parent::setCode(function (InputInterface $input, OutputInterface $output) use ($code): int {
            $event = $this->stopwatch->start($this->getName().'.code');

            $this->exitCode = $code($input, $output);

            $event->stop();

            return $this->exitCode;
        });
    }

    /**
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = true): void
    {
        $this->command->mergeApplicationDefinition($mergeArgs);
    }

    public function setDefinition(array|InputDefinition $definition): static
    {
        $this->command->setDefinition($definition);

        return $this;
    }

    public function getDefinition(): InputDefinition
    {
        return $this->command->getDefinition();
    }

    public function getNativeDefinition(): InputDefinition
    {
        return $this->command->getNativeDefinition();
    }

    public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->command->addArgument($name, $mode, $description, $default, $suggestedValues);

        return $this;
    }

    public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
    {
        $this->command->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);

        return $this;
    }

    /**
     * {@inheritdoc}
     *
     * Calling parent method is required to be used in {@see parent::run()}.
     */
    public function setProcessTitle(string $title): static
    {
        $this->command->setProcessTitle($title);

        return parent::setProcessTitle($title);
    }

    public function setHelp(string $help): static
    {
        $this->command->setHelp($help);

        return $this;
    }

    public function getHelp(): string
    {
        return $this->command->getHelp();
    }

    public function getProcessedHelp(): string
    {
        return $this->command->getProcessedHelp();
    }

    public function getSynopsis(bool $short = false): string
    {
        return $this->command->getSynopsis($short);
    }

    public function addUsage(string $usage): static
    {
        $this->command->addUsage($usage);

        return $this;
    }

    public function getUsages(): array
    {
        return $this->command->getUsages();
    }

    public function getHelper(string $name): HelperInterface
    {
        return $this->command->getHelper($name);
    }

    public function run(InputInterface $input, OutputInterface $output): int
    {
        $this->input = $input;
        $this->output = $output;
        $initialArguments = $input->getArguments();
        $initialOptions = $input->getOptions();
        $event = $this->stopwatch->start($this->getName(), 'command');

        try {
            $this->exitCode = $this->command->run($input, $output);
        } finally {
            $event->stop();

            if ($output instanceof ConsoleOutputInterface && $output->isDebug()) {
                $output->getErrorOutput()->writeln((string) $event);
            }

            $this->duration = $event->getDuration().' ms';
            $this->maxMemoryUsage = ($event->getMemory() >> 20).' MiB';

            $this->arguments = $input->getArguments();
            $this->options = $input->getOptions();

            $this->extractInteractiveInputs($initialArguments, $initialOptions);
            $this->isInteractive = $this->isInteractive || $this->interactiveInputs;
        }

        return $this->exitCode;
    }

    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        $event = $this->stopwatch->start($this->getName().'.init', 'command');

        $this->command->initialize($input, $output);

        $event->stop();
    }

    protected function interact(InputInterface $input, OutputInterface $output): void
    {
        if (!$this->isInteractive = Command::class !== (new \ReflectionMethod($this->command, 'interact'))->getDeclaringClass()->getName()) {
            return;
        }

        $event = $this->stopwatch->start($this->getName().'.interact', 'command');

        $this->command->interact($input, $output);

        $event->stop();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $event = $this->stopwatch->start($this->getName().'.execute', 'command');

        $exitCode = $this->command->execute($input, $output);

        $event->stop();

        return $exitCode;
    }

    private function extractInteractiveInputs(array $initialArguments, array $initialOptions): void
    {
        $nativeDefinition = $this->command->getNativeDefinition();

        foreach ($nativeDefinition->getArguments() as $argName => $argument) {
            if (\array_key_exists($argName, $initialArguments) && $initialArguments[$argName] === $this->arguments[$argName]) {
                continue;
            }

            $this->interactiveInputs[$argName] = $this->arguments[$argName];
        }

        foreach ($nativeDefinition->getOptions() as $optName => $option) {
            if (\array_key_exists($optName, $initialOptions) && $initialOptions[$optName] === $this->options[$optName]) {
                continue;
            }

            $this->interactiveInputs['--'.$optName] = $this->options[$optName];
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Descriptor\ApplicationDescription;
use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends Command
{
    protected function configure(): void
    {
        $this
            ->setName('list')
            ->setDefinition([
                new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name', null, fn () => array_keys((new ApplicationDescription($this->getApplication()))->getNamespaces())),
                new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
                new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', static fn () => (new DescriptorHelper())->getFormats()),
                new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments'),
            ])
            ->setDescription('List commands')
            ->setHelp(<<<'EOF'
                The <info>%command.name%</info> command lists all commands:

                  <info>%command.full_name%</info>

                You can also display the commands for a specific namespace:

                  <info>%command.full_name% test</info>

                You can also output the information in other formats by using the <info>--format</info> option:

                  <info>%command.full_name% --format=xml</info>

                It's also possible to get raw list of commands (useful for embedding command runner):

                  <info>%command.full_name% --raw</info>
                EOF
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $helper = new DescriptorHelper();
        $helper->describe($output, $this->getApplication(), [
            'format' => $input->getOption('format'),
            'raw_text' => $input->getOption('raw'),
            'namespace' => $input->getArgument('namespace'),
            'short' => $input->getOption('short'),
        ]);

        return 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;

/**
 * Represents a command line option.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputOption
{
    /**
     * Do not accept input for the option (e.g. --yell). This is the default behavior of options.
     */
    public const VALUE_NONE = 1;

    /**
     * A value must be passed when the option is used (e.g. --iterations=5 or -i5).
     */
    public const VALUE_REQUIRED = 2;

    /**
     * The option may or may not have a value (e.g. --yell or --yell=loud).
     */
    public const VALUE_OPTIONAL = 4;

    /**
     * The option accepts multiple values (e.g. --dir=/foo --dir=/bar).
     */
    public const VALUE_IS_ARRAY = 8;

    /**
     * The option allows passing a negated variant (e.g. --ansi or --no-ansi).
     */
    public const VALUE_NEGATABLE = 16;

    private string $name;
    private ?string $shortcut;
    private int $mode;
    private string|int|bool|array|float|null $default;

    /**
     * @param string|array|null                                                             $shortcut        The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param int-mask-of<InputOption::*>|null                                              $mode            The option mode: One of the VALUE_* constants
     * @param string|bool|int|float|array|null                                              $default         The default value (must be null for self::VALUE_NONE)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function __construct(
        string $name,
        string|array|null $shortcut = null,
        ?int $mode = null,
        private string $description = '',
        string|bool|int|float|array|null $default = null,
        private array|\Closure $suggestedValues = [],
    ) {
        if (str_starts_with($name, '--')) {
            $name = substr($name, 2);
        }

        if (!$name) {
            throw new InvalidArgumentException('An option name cannot be empty.');
        }

        if ('' === $shortcut || [] === $shortcut) {
            $shortcut = null;
        }

        if (null !== $shortcut) {
            if (\is_array($shortcut)) {
                $shortcut = implode('|', $shortcut);
            }
            $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
            $shortcuts = array_filter($shortcuts, 'strlen');
            $shortcut = implode('|', $shortcuts);

            if ('' === $shortcut) {
                throw new InvalidArgumentException('An option shortcut cannot be empty.');
            }
        }

        if (null === $mode) {
            $mode = self::VALUE_NONE;
        } elseif ($mode >= (self::VALUE_NEGATABLE << 1) || $mode < 1) {
            throw new InvalidArgumentException(\sprintf('Option mode "%s" is not valid.', $mode));
        }

        $this->name = $name;
        $this->shortcut = $shortcut;
        $this->mode = $mode;

        if ($suggestedValues && !$this->acceptValue()) {
            throw new LogicException('Cannot set suggested values if the option does not accept a value.');
        }
        if ($this->isArray() && !$this->acceptValue()) {
            throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
        }
        if ($this->isNegatable() && $this->acceptValue()) {
            throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.');
        }

        $this->setDefault($default);
    }

    /**
     * Returns the option shortcut.
     */
    public function getShortcut(): ?string
    {
        return $this->shortcut;
    }

    /**
     * Returns the option name.
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Returns true if the option accepts a value.
     *
     * @return bool true if value mode is not self::VALUE_NONE, false otherwise
     */
    public function acceptValue(): bool
    {
        return $this->isValueRequired() || $this->isValueOptional();
    }

    /**
     * Returns true if the option requires a value.
     *
     * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise
     */
    public function isValueRequired(): bool
    {
        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
    }

    /**
     * Returns true if the option takes an optional value.
     *
     * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise
     */
    public function isValueOptional(): bool
    {
        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
    }

    /**
     * Returns true if the option can take multiple values.
     *
     * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise
     */
    public function isArray(): bool
    {
        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
    }

    /**
     * Returns true if the option allows passing a negated variant.
     *
     * @return bool true if mode is self::VALUE_NEGATABLE, false otherwise
     */
    public function isNegatable(): bool
    {
        return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
    }

    /**
     * Sets the default value.
     */
    public function setDefault(string|bool|int|float|array|null $default): void
    {
        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
            throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = [];
            } elseif (!\is_array($default)) {
                throw new LogicException('A default value for an array option must be an array.');
            }
        }

        $this->default = $this->acceptValue() || $this->isNegatable() ? $default : false;
    }

    /**
     * Returns the default value.
     */
    public function getDefault(): string|bool|int|float|array|null
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     */
    public function getDescription(): string
    {
        return $this->description;
    }

    /**
     * Returns true if the option has values for input completion.
     */
    public function hasCompletion(): bool
    {
        return [] !== $this->suggestedValues;
    }

    /**
     * Supplies suggestions when command resolves possible completion options for input.
     *
     * @see Command::complete()
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $values = $this->suggestedValues;
        if ($values instanceof \Closure && !\is_array($values = $values($input))) {
            throw new LogicException(\sprintf('Closure for option "%s" must return an array. Got "%s".', $this->name, get_debug_type($values)));
        }
        if ($values) {
            $suggestions->suggestValues($values);
        }
    }

    /**
     * Checks whether the given option equals this one.
     */
    public function equals(self $option): bool
    {
        return $option->getName() === $this->getName()
            && $option->getShortcut() === $this->getShortcut()
            && $option->getDefault() === $this->getDefault()
            && $option->isNegatable() === $this->isNegatable()
            && $option->isArray() === $this->isArray()
            && $option->isValueRequired() === $this->isValueRequired()
            && $option->isValueOptional() === $this->isValueOptional()
        ;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;

/**
 * A InputDefinition represents a set of valid command line arguments and options.
 *
 * Usage:
 *
 *     $definition = new InputDefinition([
 *         new InputArgument('name', InputArgument::REQUIRED),
 *         new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
 *     ]);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputDefinition
{
    private array $arguments = [];
    private int $requiredCount = 0;
    private ?InputArgument $lastArrayArgument = null;
    private ?InputArgument $lastOptionalArgument = null;
    private array $options = [];
    private array $negations = [];
    private array $shortcuts = [];

    /**
     * @param array $definition An array of InputArgument and InputOption instance
     */
    public function __construct(array $definition = [])
    {
        $this->setDefinition($definition);
    }

    /**
     * Sets the definition of the input.
     */
    public function setDefinition(array $definition): void
    {
        $arguments = [];
        $options = [];
        foreach ($definition as $item) {
            if ($item instanceof InputOption) {
                $options[] = $item;
            } else {
                $arguments[] = $item;
            }
        }

        $this->setArguments($arguments);
        $this->setOptions($options);
    }

    /**
     * Sets the InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     */
    public function setArguments(array $arguments = []): void
    {
        $this->arguments = [];
        $this->requiredCount = 0;
        $this->lastOptionalArgument = null;
        $this->lastArrayArgument = null;
        $this->addArguments($arguments);
    }

    /**
     * Adds an array of InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     */
    public function addArguments(?array $arguments = []): void
    {
        if (null !== $arguments) {
            foreach ($arguments as $argument) {
                $this->addArgument($argument);
            }
        }
    }

    /**
     * @throws LogicException When incorrect argument is given
     */
    public function addArgument(InputArgument $argument): void
    {
        if (isset($this->arguments[$argument->getName()])) {
            throw new LogicException(\sprintf('An argument with name "%s" already exists.', $argument->getName()));
        }

        if (null !== $this->lastArrayArgument) {
            throw new LogicException(\sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName()));
        }

        if ($argument->isRequired() && null !== $this->lastOptionalArgument) {
            throw new LogicException(\sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName()));
        }

        if ($argument->isArray()) {
            $this->lastArrayArgument = $argument;
        }

        if ($argument->isRequired()) {
            ++$this->requiredCount;
        } else {
            $this->lastOptionalArgument = $argument;
        }

        $this->arguments[$argument->getName()] = $argument;
    }

    /**
     * Returns an InputArgument by name or by position.
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument(string|int $name): InputArgument
    {
        if (!$this->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }

        $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;

        return $arguments[$name];
    }

    /**
     * Returns true if an InputArgument object exists by name or position.
     */
    public function hasArgument(string|int $name): bool
    {
        $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments;

        return isset($arguments[$name]);
    }

    /**
     * Gets the array of InputArgument objects.
     *
     * @return InputArgument[]
     */
    public function getArguments(): array
    {
        return $this->arguments;
    }

    /**
     * Returns the number of InputArguments.
     */
    public function getArgumentCount(): int
    {
        return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments);
    }

    /**
     * Returns the number of required InputArguments.
     */
    public function getArgumentRequiredCount(): int
    {
        return $this->requiredCount;
    }

    /**
     * @return array<string|bool|int|float|array|null>
     */
    public function getArgumentDefaults(): array
    {
        $values = [];
        foreach ($this->arguments as $argument) {
            $values[$argument->getName()] = $argument->getDefault();
        }

        return $values;
    }

    /**
     * Sets the InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     */
    public function setOptions(array $options = []): void
    {
        $this->options = [];
        $this->shortcuts = [];
        $this->negations = [];
        $this->addOptions($options);
    }

    /**
     * Adds an array of InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     */
    public function addOptions(array $options = []): void
    {
        foreach ($options as $option) {
            $this->addOption($option);
        }
    }

    /**
     * @throws LogicException When option given already exist
     */
    public function addOption(InputOption $option): void
    {
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
            throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName()));
        }
        if (isset($this->negations[$option->getName()])) {
            throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName()));
        }

        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
                    throw new LogicException(\sprintf('An option with shortcut "%s" already exists.', $shortcut));
                }
            }
        }

        $this->options[$option->getName()] = $option;
        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                $this->shortcuts[$shortcut] = $option->getName();
            }
        }

        if ($option->isNegatable()) {
            $negatedName = 'no-'.$option->getName();
            if (isset($this->options[$negatedName])) {
                throw new LogicException(\sprintf('An option named "%s" already exists.', $negatedName));
            }
            $this->negations[$negatedName] = $option->getName();
        }
    }

    /**
     * Returns an InputOption by name.
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption(string $name): InputOption
    {
        if (!$this->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $name));
        }

        return $this->options[$name];
    }

    /**
     * Returns true if an InputOption object exists by name.
     *
     * This method can't be used to check if the user included the option when
     * executing the command (use getOption() instead).
     */
    public function hasOption(string $name): bool
    {
        return isset($this->options[$name]);
    }

    /**
     * Gets the array of InputOption objects.
     *
     * @return InputOption[]
     */
    public function getOptions(): array
    {
        return $this->options;
    }

    /**
     * Returns true if an InputOption object exists by shortcut.
     */
    public function hasShortcut(string $name): bool
    {
        return isset($this->shortcuts[$name]);
    }

    /**
     * Returns true if an InputOption object exists by negated name.
     */
    public function hasNegation(string $name): bool
    {
        return isset($this->negations[$name]);
    }

    /**
     * Gets an InputOption by shortcut.
     */
    public function getOptionForShortcut(string $shortcut): InputOption
    {
        return $this->getOption($this->shortcutToName($shortcut));
    }

    /**
     * @return array<string|bool|int|float|array|null>
     */
    public function getOptionDefaults(): array
    {
        $values = [];
        foreach ($this->options as $option) {
            $values[$option->getName()] = $option->getDefault();
        }

        return $values;
    }

    /**
     * Returns the InputOption name given a shortcut.
     *
     * @throws InvalidArgumentException When option given does not exist
     *
     * @internal
     */
    public function shortcutToName(string $shortcut): string
    {
        if (!isset($this->shortcuts[$shortcut])) {
            throw new InvalidArgumentException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }

        return $this->shortcuts[$shortcut];
    }

    /**
     * Returns the InputOption name given a negation.
     *
     * @throws InvalidArgumentException When option given does not exist
     *
     * @internal
     */
    public function negationToName(string $negation): string
    {
        if (!isset($this->negations[$negation])) {
            throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $negation));
        }

        return $this->negations[$negation];
    }

    /**
     * Gets the synopsis.
     */
    public function getSynopsis(bool $short = false): string
    {
        $elements = [];

        if ($short && $this->getOptions()) {
            $elements[] = '[options]';
        } elseif (!$short) {
            foreach ($this->getOptions() as $option) {
                $value = '';
                if ($option->acceptValue()) {
                    $value = \sprintf(
                        ' %s%s%s',
                        $option->isValueOptional() ? '[' : '',
                        strtoupper($option->getName()),
                        $option->isValueOptional() ? ']' : ''
                    );
                }

                $shortcut = $option->getShortcut() ? \sprintf('-%s|', $option->getShortcut()) : '';
                $negation = $option->isNegatable() ? \sprintf('|--no-%s', $option->getName()) : '';
                $elements[] = \sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation);
            }
        }

        if (\count($elements) && $this->getArguments()) {
            $elements[] = '[--]';
        }

        $tail = '';
        foreach ($this->getArguments() as $argument) {
            $element = '<'.$argument->getName().'>';
            if ($argument->isArray()) {
                $element .= '...';
            }

            if (!$argument->isRequired()) {
                $element = '['.$element;
                $tail .= ']';
            }

            $elements[] = $element;
        }

        return implode(' ', $elements).$tail;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\InvalidOptionException;

/**
 * ArrayInput represents an input provided as an array.
 *
 * Usage:
 *
 *     $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ArrayInput extends Input
{
    public function __construct(
        private array $parameters,
        ?InputDefinition $definition = null,
    ) {
        parent::__construct($definition);
    }

    public function getFirstArgument(): ?string
    {
        foreach ($this->parameters as $param => $value) {
            if ($param && \is_string($param) && '-' === $param[0]) {
                continue;
            }

            return $value;
        }

        return null;
    }

    public function hasParameterOption(string|array $values, bool $onlyParams = false): bool
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if (!\is_int($k)) {
                $v = $k;
            }

            if ($onlyParams && '--' === $v) {
                return false;
            }

            if (\in_array($v, $values)) {
                return true;
            }
        }

        return false;
    }

    public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if ($onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))) {
                return $default;
            }

            if (\is_int($k)) {
                if (\in_array($v, $values)) {
                    return true;
                }
            } elseif (\in_array($k, $values)) {
                return $v;
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command.
     */
    public function __toString(): string
    {
        $params = [];
        foreach ($this->parameters as $param => $val) {
            if ($param && \is_string($param) && '-' === $param[0]) {
                $glue = ('-' === $param[1]) ? '=' : ' ';
                if (\is_array($val)) {
                    foreach ($val as $v) {
                        $params[] = $param.('' != $v ? $glue.$this->escapeToken($v) : '');
                    }
                } else {
                    $params[] = $param.('' != $val ? $glue.$this->escapeToken($val) : '');
                }
            } else {
                $params[] = \is_array($val) ? implode(' ', array_map($this->escapeToken(...), $val)) : $this->escapeToken($val);
            }
        }

        return implode(' ', $params);
    }

    protected function parse(): void
    {
        foreach ($this->parameters as $key => $value) {
            if ('--' === $key) {
                return;
            }
            if (str_starts_with($key, '--')) {
                $this->addLongOption(substr($key, 2), $value);
            } elseif (str_starts_with($key, '-')) {
                $this->addShortOption(substr($key, 1), $value);
            } else {
                $this->addArgument($key, $value);
            }
        }
    }

    /**
     * Adds a short option value.
     *
     * @throws InvalidOptionException When option given doesn't exist
     */
    private function addShortOption(string $shortcut, mixed $value): void
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new InvalidOptionException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @throws InvalidOptionException When option given doesn't exist
     * @throws InvalidOptionException When a required value is missing
     */
    private function addLongOption(string $name, mixed $value): void
    {
        if (!$this->definition->hasOption($name)) {
            if (!$this->definition->hasNegation($name)) {
                throw new InvalidOptionException(\sprintf('The "--%s" option does not exist.', $name));
            }

            $optionName = $this->definition->negationToName($name);
            $this->options[$optionName] = false;

            return;
        }

        $option = $this->definition->getOption($name);

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new InvalidOptionException(\sprintf('The "--%s" option requires a value.', $name));
            }

            if (!$option->isValueOptional()) {
                $value = true;
            }
        }

        $this->options[$name] = $value;
    }

    /**
     * Adds an argument value.
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    private function addArgument(string|int $name, mixed $value): void
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;

/**
 * Input is the base class for all concrete Input classes.
 *
 * Three concrete classes are provided by default:
 *
 *  * `ArgvInput`: The input comes from the CLI arguments (argv)
 *  * `StringInput`: The input is provided as a string
 *  * `ArrayInput`: The input is provided as an array
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Input implements InputInterface, StreamableInputInterface
{
    protected InputDefinition $definition;
    /** @var resource */
    protected $stream;
    protected array $options = [];
    protected array $arguments = [];
    protected bool $interactive = true;

    public function __construct(?InputDefinition $definition = null)
    {
        if (null === $definition) {
            $this->definition = new InputDefinition();
        } else {
            $this->bind($definition);
            $this->validate();
        }
    }

    public function bind(InputDefinition $definition): void
    {
        $this->arguments = [];
        $this->options = [];
        $this->definition = $definition;

        $this->parse();
    }

    /**
     * Processes command line arguments.
     */
    abstract protected function parse(): void;

    public function validate(): void
    {
        $definition = $this->definition;
        $givenArguments = $this->arguments;

        $missingArguments = array_filter(array_keys($definition->getArguments()), static fn ($argument) => !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired());

        if (\count($missingArguments) > 0) {
            throw new RuntimeException(\sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
        }
    }

    public function isInteractive(): bool
    {
        return $this->interactive;
    }

    public function setInteractive(bool $interactive): void
    {
        $this->interactive = $interactive;
    }

    public function getArguments(): array
    {
        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
    }

    public function getArgument(string $name): mixed
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }

        return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault();
    }

    public function setArgument(string $name, mixed $value): void
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }

    public function hasArgument(string $name): bool
    {
        return $this->definition->hasArgument($name);
    }

    public function getOptions(): array
    {
        return array_merge($this->definition->getOptionDefaults(), $this->options);
    }

    public function getOption(string $name): mixed
    {
        if ($this->definition->hasNegation($name)) {
            if (null === $value = $this->getOption($this->definition->negationToName($name))) {
                return $value;
            }

            return !$value;
        }

        if (!$this->definition->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name));
        }

        return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
    }

    public function setOption(string $name, mixed $value): void
    {
        if ($this->definition->hasNegation($name)) {
            $this->options[$this->definition->negationToName($name)] = !$value;

            return;
        } elseif (!$this->definition->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name));
        }

        $this->options[$name] = $value;
    }

    public function hasOption(string $name): bool
    {
        return $this->definition->hasOption($name) || $this->definition->hasNegation($name);
    }

    /**
     * Escapes a token through escapeshellarg if it contains unsafe chars.
     */
    public function escapeToken(string $token): string
    {
        return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
    }

    /**
     * @param resource $stream
     */
    public function setStream($stream): void
    {
        $this->stream = $stream;
    }

    /**
     * @return resource
     */
    public function getStream()
    {
        return $this->stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;

/**
 * Represents a command line argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputArgument
{
    /**
     * Providing an argument is required (e.g. just 'app:foo' is not allowed).
     */
    public const REQUIRED = 1;

    /**
     * Providing an argument is optional (e.g. 'app:foo' and 'app:foo bar' are both allowed). This is the default behavior of arguments.
     */
    public const OPTIONAL = 2;

    /**
     * The argument accepts multiple values and turn them into an array (e.g. 'app:foo bar baz' will result in value ['bar', 'baz']).
     */
    public const IS_ARRAY = 4;

    private int $mode;
    private string|int|bool|array|float|null $default;

    /**
     * @param string                                                                        $name            The argument name
     * @param int-mask-of<InputArgument::*>|null                                            $mode            The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY
     * @param string                                                                        $description     A description text
     * @param string|bool|int|float|array|null                                              $default         The default value (for self::OPTIONAL mode only)
     * @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function __construct(
        private string $name,
        ?int $mode = null,
        private string $description = '',
        string|bool|int|float|array|null $default = null,
        private \Closure|array $suggestedValues = [],
    ) {
        if (null === $mode) {
            $mode = self::OPTIONAL;
        } elseif ($mode >= (self::IS_ARRAY << 1) || $mode < 1) {
            throw new InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode));
        }

        $this->mode = $mode;

        $this->setDefault($default);
    }

    /**
     * Returns the argument name.
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Returns true if the argument is required.
     *
     * @return bool true if parameter mode is self::REQUIRED, false otherwise
     */
    public function isRequired(): bool
    {
        return self::REQUIRED === (self::REQUIRED & $this->mode);
    }

    /**
     * Returns true if the argument can take multiple values.
     *
     * @return bool true if mode is self::IS_ARRAY, false otherwise
     */
    public function isArray(): bool
    {
        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     */
    public function setDefault(string|bool|int|float|array|null $default): void
    {
        if ($this->isRequired() && null !== $default) {
            throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = [];
            } elseif (!\is_array($default)) {
                throw new LogicException('A default value for an array argument must be an array.');
            }
        }

        $this->default = $default;
    }

    /**
     * Returns the default value.
     */
    public function getDefault(): string|bool|int|float|array|null
    {
        return $this->default;
    }

    /**
     * Returns true if the argument has values for input completion.
     */
    public function hasCompletion(): bool
    {
        return [] !== $this->suggestedValues;
    }

    /**
     * Supplies suggestions when command resolves possible completion options for input.
     *
     * @see Command::complete()
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
    {
        $values = $this->suggestedValues;
        if ($values instanceof \Closure && !\is_array($values = $values($input))) {
            throw new LogicException(\sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->name, get_debug_type($values)));
        }
        if ($values) {
            $suggestions->suggestValues($values);
        }
    }

    /**
     * Returns the description text.
     */
    public function getDescription(): string
    {
        return $this->description;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * InputAwareInterface should be implemented by classes that depends on the
 * Console Input.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
interface InputAwareInterface
{
    /**
     * Sets the Console Input.
     */
    public function setInput(InputInterface $input): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\RuntimeException;

/**
 * ArgvInput represents an input coming from the CLI arguments.
 *
 * Usage:
 *
 *     $input = new ArgvInput();
 *
 * By default, the `$_SERVER['argv']` array is used for the input values.
 *
 * This can be overridden by explicitly passing the input values in the constructor:
 *
 *     $input = new ArgvInput($_SERVER['argv']);
 *
 * If you pass it yourself, don't forget that the first element of the array
 * is the name of the running application.
 *
 * When passing an argument to the constructor, be sure that it respects
 * the same rules as the argv one. It's almost always better to use the
 * `StringInput` when you want to provide your own input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
 * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 */
class ArgvInput extends Input
{
    /** @var list<string> */
    private array $tokens;
    private array $parsed;

    /** @param list<string>|null $argv */
    public function __construct(?array $argv = null, ?InputDefinition $definition = null)
    {
        $argv ??= $_SERVER['argv'] ?? [];

        foreach ($argv as $arg) {
            if (!\is_scalar($arg) && !$arg instanceof \Stringable) {
                throw new RuntimeException(\sprintf('Argument values expected to be all scalars, got "%s".', get_debug_type($arg)));
            }
        }

        // strip the application name
        array_shift($argv);

        $this->tokens = $argv;

        parent::__construct($definition);
    }

    /** @param list<string> $tokens */
    protected function setTokens(array $tokens): void
    {
        $this->tokens = $tokens;
    }

    protected function parse(): void
    {
        $parseOptions = true;
        $this->parsed = $this->tokens;
        while (null !== $token = array_shift($this->parsed)) {
            $parseOptions = $this->parseToken($token, $parseOptions);
        }
    }

    protected function parseToken(string $token, bool $parseOptions): bool
    {
        if ($parseOptions && '' == $token) {
            $this->parseArgument($token);
        } elseif ($parseOptions && '--' == $token) {
            return false;
        } elseif ($parseOptions && str_starts_with($token, '--')) {
            $this->parseLongOption($token);
        } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
            $this->parseShortOption($token);
        } else {
            $this->parseArgument($token);
        }

        return $parseOptions;
    }

    /**
     * Parses a short option.
     */
    private function parseShortOption(string $token): void
    {
        $name = substr($token, 1);

        if (\strlen($name) > 1) {
            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
                // an option with a value (with no space)
                $this->addShortOption($name[0], substr($name, 1));
            } else {
                $this->parseShortOptionSet($name);
            }
        } else {
            $this->addShortOption($name, null);
        }
    }

    /**
     * Parses a short option set.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function parseShortOptionSet(string $name): void
    {
        $len = \strlen($name);
        for ($i = 0; $i < $len; ++$i) {
            if (!$this->definition->hasShortcut($name[$i])) {
                $encoding = mb_detect_encoding($name, null, true);
                throw new RuntimeException(\sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding)));
            }

            $option = $this->definition->getOptionForShortcut($name[$i]);
            if ($option->acceptValue()) {
                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));

                break;
            }

            $this->addLongOption($option->getName(), null);
        }
    }

    /**
     * Parses a long option.
     */
    private function parseLongOption(string $token): void
    {
        $name = substr($token, 2);

        if (false !== $pos = strpos($name, '=')) {
            if ('' === $value = substr($name, $pos + 1)) {
                array_unshift($this->parsed, $value);
            }
            $this->addLongOption(substr($name, 0, $pos), $value);
        } else {
            $this->addLongOption($name, null);
        }
    }

    /**
     * Parses an argument.
     *
     * @throws RuntimeException When too many arguments are given
     */
    private function parseArgument(string $token): void
    {
        $c = \count($this->arguments);

        // if input is expecting another argument, add it
        if ($this->definition->hasArgument($c)) {
            $arg = $this->definition->getArgument($c);
            $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;

        // if last argument isArray(), append token to last argument
        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
            $arg = $this->definition->getArgument($c - 1);
            $this->arguments[$arg->getName()][] = $token;

        // unexpected argument
        } else {
            $all = $this->definition->getArguments();
            $symfonyCommandName = null;
            if (($inputArgument = $all[$key = array_key_first($all) ?? ''] ?? null) && 'command' === $inputArgument->getName()) {
                $symfonyCommandName = $this->arguments['command'] ?? null;
                unset($all[$key]);
            }

            if (\count($all)) {
                if ($symfonyCommandName) {
                    $message = \sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, implode('" "', array_keys($all)));
                } else {
                    $message = \sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)));
                }
            } elseif ($symfonyCommandName) {
                $message = \sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token);
            } else {
                $message = \sprintf('No arguments expected, got "%s".', $token);
            }

            throw new RuntimeException($message);
        }
    }

    /**
     * Adds a short option value.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addShortOption(string $shortcut, mixed $value): void
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addLongOption(string $name, mixed $value): void
    {
        if (!$this->definition->hasOption($name)) {
            if (!$this->definition->hasNegation($name)) {
                throw new RuntimeException(\sprintf('The "--%s" option does not exist.', $name));
            }

            $optionName = $this->definition->negationToName($name);
            if (null !== $value) {
                throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
            }
            $this->options[$optionName] = false;

            return;
        }

        $option = $this->definition->getOption($name);

        if (null !== $value && !$option->acceptValue()) {
            throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
        }

        if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) {
            // if option accepts an optional or mandatory argument
            // let's see if there is one provided
            $next = array_shift($this->parsed);
            if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) {
                $value = $next;
            } else {
                array_unshift($this->parsed, $next);
            }
        }

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new RuntimeException(\sprintf('The "--%s" option requires a value.', $name));
            }

            if (!$option->isArray() && !$option->isValueOptional()) {
                $value = true;
            }
        }

        if ($option->isArray()) {
            $this->options[$name][] = $value;
        } else {
            $this->options[$name] = $value;
        }
    }

    public function getFirstArgument(): ?string
    {
        $isOption = false;
        foreach ($this->tokens as $i => $token) {
            if ($token && '-' === $token[0]) {
                if (str_contains($token, '=') || !isset($this->tokens[$i + 1])) {
                    continue;
                }

                // If it's a long option, consider that everything after "--" is the option name.
                // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator)
                $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1);
                if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) {
                    // noop
                } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) {
                    $isOption = true;
                }

                continue;
            }

            if ($isOption) {
                $isOption = false;
                continue;
            }

            return $token;
        }

        return null;
    }

    public function hasParameterOption(string|array $values, bool $onlyParams = false): bool
    {
        $values = (array) $values;

        foreach ($this->tokens as $token) {
            if ($onlyParams && '--' === $token) {
                return false;
            }
            foreach ($values as $value) {
                // Options with values:
                //   For long options, test for '--option=' at beginning
                //   For short options, test for '-o' at beginning
                $leading = str_starts_with($value, '--') ? $value.'=' : $value;
                if ($token === $value || '' !== $leading && str_starts_with($token, $leading)) {
                    return true;
                }
            }
        }

        return false;
    }

    public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed
    {
        $values = (array) $values;
        $tokens = $this->tokens;

        while (0 < \count($tokens)) {
            $token = array_shift($tokens);
            if ($onlyParams && '--' === $token) {
                return $default;
            }

            foreach ($values as $value) {
                if ($token === $value) {
                    return array_shift($tokens);
                }
                // Options with values:
                //   For long options, test for '--option=' at beginning
                //   For short options, test for '-o' at beginning
                $leading = str_starts_with($value, '--') ? $value.'=' : $value;
                if ('' !== $leading && str_starts_with($token, $leading)) {
                    return substr($token, \strlen($leading));
                }
            }
        }

        return $default;
    }

    /**
     * Returns un-parsed and not validated tokens.
     *
     * @param bool $strip Whether to return the raw parameters (false) or the values after the command name (true)
     *
     * @return list<string>
     */
    public function getRawTokens(bool $strip = false): array
    {
        if (!$strip) {
            return $this->tokens;
        }

        $parameters = [];
        $keep = false;
        foreach ($this->tokens as $value) {
            if (!$keep && $value === $this->getFirstArgument()) {
                $keep = true;

                continue;
            }
            if ($keep) {
                $parameters[] = $value;
            }
        }

        return $parameters;
    }

    /**
     * Returns a stringified representation of the args passed to the command.
     */
    public function __toString(): string
    {
        $tokens = array_map(function ($token) {
            if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
                return $match[1].$this->escapeToken($match[2]);
            }

            if ($token && '-' !== $token[0]) {
                return $this->escapeToken($token);
            }

            return $token;
        }, $this->tokens);

        return implode(' ', $tokens);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;

/**
 * InputInterface is the interface implemented by all input classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface InputInterface
{
    /**
     * Returns the first argument from the raw parameters (not parsed).
     */
    public function getFirstArgument(): ?string;

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     * Does not necessarily return the correct result for short options
     * when multiple flags are combined in the same option.
     *
     * @param string|array $values     The values to look for in the raw parameters (can be an array)
     * @param bool         $onlyParams Only check real parameters, skip those following an end of options (--) signal
     */
    public function hasParameterOption(string|array $values, bool $onlyParams = false): bool;

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     * Does not necessarily return the correct result for short options
     * when multiple flags are combined in the same option.
     *
     * @param string|array                     $values     The value(s) to look for in the raw parameters (can be an array)
     * @param string|bool|int|float|array|null $default    The default value to return if no result is found
     * @param bool                             $onlyParams Only check real parameters, skip those following an end of options (--) signal
     */
    public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false): mixed;

    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @throws RuntimeException
     */
    public function bind(InputDefinition $definition): void;

    /**
     * Validates the input.
     *
     * @throws RuntimeException When not enough arguments are given
     */
    public function validate(): void;

    /**
     * Returns all the given arguments merged with the default values.
     *
     * @return array<string|bool|int|float|array|null>
     */
    public function getArguments(): array;

    /**
     * Returns the argument value for a given argument name.
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument(string $name): mixed;

    /**
     * Sets an argument value by name.
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument(string $name, mixed $value): void;

    /**
     * Returns true if an InputArgument object exists by name or position.
     */
    public function hasArgument(string $name): bool;

    /**
     * Returns all the given options merged with the default values.
     *
     * @return array<string|bool|int|float|array|null>
     */
    public function getOptions(): array;

    /**
     * Returns the option value for a given option name.
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption(string $name): mixed;

    /**
     * Sets an option value by name.
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function setOption(string $name, mixed $value): void;

    /**
     * Returns true if an InputOption object exists by name.
     */
    public function hasOption(string $name): bool;

    /**
     * Is this input means interactive?
     */
    public function isInteractive(): bool;

    /**
     * Sets the input interactivity.
     */
    public function setInteractive(bool $interactive): void;

    /**
     * Returns a stringified representation of the args passed to the command.
     *
     * InputArguments MUST be escaped as well as the InputOption values passed to the command.
     */
    public function __toString(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * StreamableInputInterface is the interface implemented by all input classes
 * that have an input stream.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface StreamableInputInterface extends InputInterface
{
    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     */
    public function setStream($stream): void;

    /**
     * Returns the input stream.
     *
     * @return resource|null
     */
    public function getStream();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * StringInput represents an input provided as a string.
 *
 * Usage:
 *
 *     $input = new StringInput('foo --bar="foobar"');
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StringInput extends ArgvInput
{
    public const REGEX_UNQUOTED_STRING = '([^\s\\\\]+?)';
    public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';

    /**
     * @param string $input A string representing the parameters from the CLI
     */
    public function __construct(string $input)
    {
        parent::__construct([]);

        $this->setTokens($this->tokenize($input));
    }

    /**
     * Tokenizes a string.
     *
     * @return list<string>
     *
     * @throws InvalidArgumentException When unable to parse input (should never happen)
     */
    private function tokenize(string $input): array
    {
        $tokens = [];
        $length = \strlen($input);
        $cursor = 0;
        $token = null;
        while ($cursor < $length) {
            if ('\\' === $input[$cursor]) {
                $token .= $input[++$cursor] ?? '';
                ++$cursor;
                continue;
            }

            if (preg_match('/\s+/A', $input, $match, 0, $cursor)) {
                if (null !== $token) {
                    $tokens[] = $token;
                    $token = null;
                }
            } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, 0, $cursor)) {
                $token .= $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, -1)));
            } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, 0, $cursor)) {
                $token .= stripcslashes(substr($match[0], 1, -1));
            } elseif (preg_match('/'.self::REGEX_UNQUOTED_STRING.'/A', $input, $match, 0, $cursor)) {
                $token .= $match[1];
            } else {
                // should never happen
                throw new InvalidArgumentException(\sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10)));
            }

            $cursor += \strlen($match[0]);
        }

        if (null !== $token) {
            $tokens[] = $token;
        }

        return $tokens;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Formatter\OutputFormatter;

/**
 * The Formatter class provides helpers to format messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormatterHelper extends Helper
{
    /**
     * Formats a message within a section.
     */
    public function formatSection(string $section, string $message, string $style = 'info'): string
    {
        return \sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
    }

    /**
     * Formats a message as a block of text.
     */
    public function formatBlock(string|array $messages, string $style, bool $large = false): string
    {
        if (!\is_array($messages)) {
            $messages = [$messages];
        }

        $len = 0;
        $lines = [];
        foreach ($messages as $message) {
            $message = OutputFormatter::escape($message);
            $lines[] = \sprintf($large ? '  %s  ' : ' %s ', $message);
            $len = max(self::width($message) + ($large ? 4 : 2), $len);
        }

        $messages = $large ? [str_repeat(' ', $len)] : [];
        for ($i = 0; isset($lines[$i]); ++$i) {
            $messages[] = $lines[$i].str_repeat(' ', $len - self::width($lines[$i]));
        }
        if ($large) {
            $messages[] = str_repeat(' ', $len);
        }

        for ($i = 0; isset($messages[$i]); ++$i) {
            $messages[$i] = \sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
        }

        return implode("\n", $messages);
    }

    /**
     * Truncates a message to the given length.
     */
    public function truncate(string $message, int $length, string $suffix = '...'): string
    {
        $computedLength = $length - self::width($suffix);

        if ($computedLength > self::width($message)) {
            return $message;
        }

        return self::substr($message, 0, $length).$suffix;
    }

    public function getName(): string
    {
        return 'formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;

/**
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
final class Dumper
{
    private \Closure $handler;

    public function __construct(
        private OutputInterface $output,
        private ?CliDumper $dumper = null,
        private ?ClonerInterface $cloner = null,
    ) {
        if (class_exists(CliDumper::class)) {
            $this->handler = function ($var): string {
                $dumper = $this->dumper ??= new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR);
                $dumper->setColors($this->output->isDecorated());

                return rtrim($dumper->dump(($this->cloner ??= new VarCloner())->cloneVar($var)->withRefHandles(false), true));
            };
        } else {
            $this->handler = static fn ($var): string => match (true) {
                null === $var => 'null',
                true === $var => 'true',
                false === $var => 'false',
                \is_string($var) => '"'.$var.'"',
                default => rtrim(print_r($var, true)),
            };
        }
    }

    public function __invoke(mixed $var): string
    {
        return ($this->handler)($var);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * Helps outputting debug information when running an external program from a command.
 *
 * An external program can be a Process, an HTTP request, or anything else.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DebugFormatterHelper extends Helper
{
    private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
    private array $started = [];
    private int $count = -1;

    /**
     * Starts a debug formatting session.
     */
    public function start(string $id, string $message, string $prefix = 'RUN'): string
    {
        $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)];

        return \sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
    }

    /**
     * Adds progress to a formatting session.
     */
    public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR'): string
    {
        $message = '';

        if ($error) {
            if (isset($this->started[$id]['out'])) {
                $message .= "\n";
                unset($this->started[$id]['out']);
            }
            if (!isset($this->started[$id]['err'])) {
                $message .= \sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
                $this->started[$id]['err'] = true;
            }

            $message .= str_replace("\n", \sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
        } else {
            if (isset($this->started[$id]['err'])) {
                $message .= "\n";
                unset($this->started[$id]['err']);
            }
            if (!isset($this->started[$id]['out'])) {
                $message .= \sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
                $this->started[$id]['out'] = true;
            }

            $message .= str_replace("\n", \sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
        }

        return $message;
    }

    /**
     * Stops a formatting session.
     */
    public function stop(string $id, string $message, bool $successful, string $prefix = 'RES'): string
    {
        $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';

        if ($successful) {
            return \sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
        }

        $message = \sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);

        unset($this->started[$id]['out'], $this->started[$id]['err']);

        return $message;
    }

    private function getBorder(string $id): string
    {
        return \sprintf('<bg=%s> </>', self::COLORS[$this->started[$id]['border']]);
    }

    public function getName(): string
    {
        return 'debug_formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class TableCell
{
    private array $options = [
        'rowspan' => 1,
        'colspan' => 1,
        'style' => null,
    ];

    public function __construct(
        private string $value = '',
        array $options = [],
    ) {
        // check option names
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
        }

        if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) {
            throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".');
        }

        $this->options = array_merge($this->options, $options);
    }

    /**
     * Returns the cell value.
     */
    public function __toString(): string
    {
        return $this->value;
    }

    /**
     * Gets number of colspan.
     */
    public function getColspan(): int
    {
        return (int) $this->options['colspan'];
    }

    /**
     * Gets number of rowspan.
     */
    public function getRowspan(): int
    {
        return (int) $this->options['rowspan'];
    }

    public function getStyle(): ?TableCellStyle
    {
        return $this->options['style'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * HelperSet represents a set of helpers to be used with a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, HelperInterface>
 */
class HelperSet implements \IteratorAggregate
{
    /** @var array<string, HelperInterface> */
    private array $helpers = [];

    /**
     * @param HelperInterface[] $helpers
     */
    public function __construct(array $helpers = [])
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, \is_int($alias) ? null : $alias);
        }
    }

    public function set(HelperInterface $helper, ?string $alias = null): void
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }

        $helper->setHelperSet($this);
    }

    /**
     * Returns true if the helper if defined.
     */
    public function has(string $name): bool
    {
        return isset($this->helpers[$name]);
    }

    /**
     * Gets a helper value.
     *
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function get(string $name): HelperInterface
    {
        if (!$this->has($name)) {
            throw new InvalidArgumentException(\sprintf('The helper "%s" is not defined.', $name));
        }

        return $this->helpers[$name];
    }

    public function getIterator(): \Traversable
    {
        return new \ArrayIterator($this->helpers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * Simple output wrapper for "tagged outputs" instead of wordwrap(). This solution is based on a StackOverflow
 * answer: https://stackoverflow.com/a/20434776/1476819 from user557597 (alias SLN).
 *
 *  (?:
 *       # -- Words/Characters
 *       (                       # (1 start)
 *            (?>                     # Atomic Group - Match words with valid breaks
 *                 .{1,16}                 #  1-N characters
 *                                         #  Followed by one of 4 prioritized, non-linebreak whitespace
 *                 (?:                     #  break types:
 *                      (?<= [^\S\r\n] )        # 1. - Behind a non-linebreak whitespace
 *                      [^\S\r\n]?              #      ( optionally accept an extra non-linebreak whitespace )
 *                   |  (?= \r? \n )            # 2. - Ahead a linebreak
 *                   |  $                       # 3. - EOS
 *                   |  [^\S\r\n]               # 4. - Accept an extra non-linebreak whitespace
 *                 )
 *            )                       # End atomic group
 *         |
 *            .{1,16}                 # No valid word breaks, just break on the N'th character
 *       )                       # (1 end)
 *       (?: \r? \n )?           # Optional linebreak after Words/Characters
 *    |
 *       # -- Or, Linebreak
 *       (?: \r? \n | $ )        # Stand alone linebreak or at EOS
 *  )
 *
 * @author Krisztián Ferenczi <ferenczi.krisztian@gmail.com>
 *
 * @see https://stackoverflow.com/a/20434776/1476819
 */
final class OutputWrapper
{
    private const TAG_OPEN_REGEX_SEGMENT = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
    private const TAG_CLOSE_REGEX_SEGMENT = '[a-z][^<>]*+';
    private const URL_PATTERN = 'https?://\S+';

    public function __construct(
        private bool $allowCutUrls = false,
    ) {
    }

    public function wrap(string $text, int $width, string $break = "\n"): string
    {
        if (!$width) {
            return $text;
        }

        $tagPattern = \sprintf('<(?:(?:%s)|/(?:%s)?)>', self::TAG_OPEN_REGEX_SEGMENT, self::TAG_CLOSE_REGEX_SEGMENT);
        $limitPattern = "{1,$width}";
        $patternBlocks = [$tagPattern];
        if (!$this->allowCutUrls) {
            $patternBlocks[] = self::URL_PATTERN;
        }
        $patternBlocks[] = '.';
        $blocks = implode('|', $patternBlocks);
        $rowPattern = "(?:$blocks)$limitPattern";
        $pattern = \sprintf('#(?:((?>(%1$s)((?<=[^\S\r\n])[^\S\r\n]?|(?=\r?\n)|$|[^\S\r\n]))|(%1$s))(?:\r?\n)?|(?:\r?\n|$))#imux', $rowPattern);
        $output = rtrim(preg_replace($pattern, '\\1'.$break, $text), $break);

        return str_replace(' '.$break, $break, $output);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Cursor;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Terminal;

/**
 * The ProgressBar provides helpers to display progress output.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Chris Jones <leeked@gmail.com>
 */
final class ProgressBar
{
    public const FORMAT_VERBOSE = 'verbose';
    public const FORMAT_VERY_VERBOSE = 'very_verbose';
    public const FORMAT_DEBUG = 'debug';
    public const FORMAT_NORMAL = 'normal';

    private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax';
    private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax';
    private const FORMAT_DEBUG_NOMAX = 'debug_nomax';
    private const FORMAT_NORMAL_NOMAX = 'normal_nomax';

    private int $barWidth = 28;
    private string $barChar;
    private string $emptyBarChar = '-';
    private string $progressChar = '>';
    private ?string $format = null;
    private ?string $internalFormat = null;
    private ?int $redrawFreq = 1;
    private int $writeCount = 0;
    private float $lastWriteTime = 0;
    private float $minSecondsBetweenRedraws = 0;
    private float $maxSecondsBetweenRedraws = 1;
    private OutputInterface $output;
    private int $step = 0;
    private int $startingStep = 0;
    private ?int $max = null;
    private int $startTime;
    private int $stepWidth;
    private float $percent = 0.0;
    private array $messages = [];
    private bool $overwrite = true;
    private Terminal $terminal;
    private ?string $previousMessage = null;
    private Cursor $cursor;
    private array $placeholders = [];

    private static array $formatters;
    private static array $formats;

    /**
     * @param int $max Maximum steps (0 if unknown)
     */
    public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        $this->output = $output;
        $this->setMaxSteps($max);
        $this->terminal = new Terminal();

        if (0 < $minSecondsBetweenRedraws) {
            $this->redrawFreq = null;
            $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws;
        }

        if (!$this->output->isDecorated()) {
            // disable overwrite when output does not support ANSI codes.
            $this->overwrite = false;

            // set a reasonable redraw frequency so output isn't flooded
            $this->redrawFreq = null;
        }

        $this->startTime = time();
        $this->cursor = new Cursor($output);
    }

    /**
     * Sets a placeholder formatter for a given name, globally for all instances of ProgressBar.
     *
     * This method also allow you to override an existing placeholder.
     *
     * @param string                       $name     The placeholder name (including the delimiter char like %)
     * @param callable(ProgressBar):string $callable A PHP callable
     */
    public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void
    {
        self::$formatters ??= self::initPlaceholderFormatters();

        self::$formatters[$name] = $callable;
    }

    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     */
    public static function getPlaceholderFormatterDefinition(string $name): ?callable
    {
        self::$formatters ??= self::initPlaceholderFormatters();

        return self::$formatters[$name] ?? null;
    }

    /**
     * Sets a placeholder formatter for a given name, for this instance only.
     *
     * @param callable(ProgressBar):string $callable A PHP callable
     */
    public function setPlaceholderFormatter(string $name, callable $callable): void
    {
        $this->placeholders[$name] = $callable;
    }

    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     */
    public function getPlaceholderFormatter(string $name): ?callable
    {
        return $this->placeholders[$name] ?? $this::getPlaceholderFormatterDefinition($name);
    }

    /**
     * Sets a format for a given name.
     *
     * This method also allow you to override an existing format.
     *
     * @param string $name   The format name
     * @param string $format A format string
     */
    public static function setFormatDefinition(string $name, string $format): void
    {
        self::$formats ??= self::initFormats();

        self::$formats[$name] = $format;
    }

    /**
     * Gets the format for a given name.
     *
     * @param string $name The format name
     */
    public static function getFormatDefinition(string $name): ?string
    {
        self::$formats ??= self::initFormats();

        return self::$formats[$name] ?? null;
    }

    /**
     * Associates a text with a named placeholder.
     *
     * The text is displayed when the progress bar is rendered but only
     * when the corresponding placeholder is part of the custom format line
     * (by wrapping the name with %).
     *
     * @param string $message The text to associate with the placeholder
     * @param string $name    The name of the placeholder
     */
    public function setMessage(string $message, string $name = 'message'): void
    {
        $this->messages[$name] = $message;
    }

    public function getMessage(string $name = 'message'): ?string
    {
        return $this->messages[$name] ?? null;
    }

    public function getStartTime(): int
    {
        return $this->startTime;
    }

    public function getMaxSteps(): int
    {
        return $this->max ?? 0;
    }

    public function getProgress(): int
    {
        return $this->step;
    }

    private function getStepWidth(): int
    {
        return $this->stepWidth;
    }

    public function getProgressPercent(): float
    {
        return $this->percent;
    }

    public function getBarOffset(): float
    {
        return floor(null !== $this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
    }

    public function getEstimated(): float
    {
        if (0 === $this->step || $this->step === $this->startingStep) {
            return 0;
        }

        return round((time() - $this->startTime) / ($this->step - $this->startingStep) * $this->max);
    }

    public function getRemaining(): float
    {
        if (0 === $this->step || $this->step === $this->startingStep) {
            return 0;
        }

        return round((time() - $this->startTime) / ($this->step - $this->startingStep) * ($this->max - $this->step));
    }

    public function setBarWidth(int $size): void
    {
        $this->barWidth = max(1, $size);
    }

    public function getBarWidth(): int
    {
        return $this->barWidth;
    }

    public function setBarCharacter(string $char): void
    {
        $this->barChar = $char;
    }

    public function getBarCharacter(): string
    {
        return $this->barChar ?? (null !== $this->max ? '=' : $this->emptyBarChar);
    }

    public function setEmptyBarCharacter(string $char): void
    {
        $this->emptyBarChar = $char;
    }

    public function getEmptyBarCharacter(): string
    {
        return $this->emptyBarChar;
    }

    public function setProgressCharacter(string $char): void
    {
        $this->progressChar = $char;
    }

    public function getProgressCharacter(): string
    {
        return $this->progressChar;
    }

    public function setFormat(string $format): void
    {
        $this->format = null;
        $this->internalFormat = $format;
    }

    /**
     * Sets the redraw frequency.
     *
     * @param int|null $freq The frequency in steps
     */
    public function setRedrawFrequency(?int $freq): void
    {
        $this->redrawFreq = null !== $freq ? max(1, $freq) : null;
    }

    public function minSecondsBetweenRedraws(float $seconds): void
    {
        $this->minSecondsBetweenRedraws = $seconds;
    }

    public function maxSecondsBetweenRedraws(float $seconds): void
    {
        $this->maxSecondsBetweenRedraws = $seconds;
    }

    /**
     * Returns an iterator that will automatically update the progress bar when iterated.
     *
     * @template TKey
     * @template TValue
     *
     * @param iterable<TKey, TValue> $iterable
     * @param int|null               $max      Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
     *
     * @return iterable<TKey, TValue>
     */
    public function iterate(iterable $iterable, ?int $max = null): iterable
    {
        if (0 === $max) {
            $max = null;
        }

        $max ??= is_countable($iterable) ? \count($iterable) : null;

        if (0 === $max) {
            $this->max = 0;
            $this->stepWidth = 2;
            $this->finish();

            return;
        }

        $this->start($max);

        foreach ($iterable as $key => $value) {
            yield $key => $value;

            $this->advance();
        }

        $this->finish();
    }

    /**
     * Starts the progress output.
     *
     * @param int|null $max     Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
     * @param int      $startAt The starting point of the bar (useful e.g. when resuming a previously started bar)
     */
    public function start(?int $max = null, int $startAt = 0): void
    {
        $this->startTime = time();
        $this->step = $startAt;
        $this->startingStep = $startAt;

        $startAt > 0 ? $this->setProgress($startAt) : $this->percent = 0.0;

        if (null !== $max) {
            $this->setMaxSteps($max);
        }

        $this->display();
    }

    /**
     * Advances the progress output X steps.
     *
     * @param int $step Number of steps to advance
     */
    public function advance(int $step = 1): void
    {
        $this->setProgress($this->step + $step);
    }

    /**
     * Sets whether to overwrite the progressbar, false for new line.
     */
    public function setOverwrite(bool $overwrite): void
    {
        $this->overwrite = $overwrite;
    }

    public function setProgress(int $step): void
    {
        if ($this->max && $step > $this->max) {
            $this->max = $step;
        } elseif ($step < 0) {
            $step = 0;
        }

        $redrawFreq = $this->redrawFreq ?? (($this->max ?? 10) / 10);
        $prevPeriod = $redrawFreq ? (int) ($this->step / $redrawFreq) : 0;
        $currPeriod = $redrawFreq ? (int) ($step / $redrawFreq) : 0;
        $this->step = $step;
        $this->percent = match ($this->max) {
            null => 0,
            0 => 1,
            default => (float) $this->step / $this->max,
        };
        $timeInterval = microtime(true) - $this->lastWriteTime;

        // Draw regardless of other limits
        if ($this->max === $step) {
            $this->display();

            return;
        }

        // Throttling
        if ($timeInterval < $this->minSecondsBetweenRedraws) {
            return;
        }

        // Draw each step period, but not too late
        if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) {
            $this->display();
        }
    }

    public function setMaxSteps(?int $max): void
    {
        if (0 === $max) {
            $max = null;
        }

        $this->format = null;
        if (null === $max) {
            $this->max = null;
            $this->stepWidth = 4;
        } else {
            $this->max = max(0, $max);
            $this->stepWidth = Helper::width((string) $this->max);
        }
    }

    /**
     * Finishes the progress output.
     */
    public function finish(): void
    {
        if (null === $this->max) {
            $this->max = $this->step;
        }

        if (($this->step === $this->max || null === $this->max) && !$this->overwrite) {
            // prevent double 100% output
            return;
        }

        $this->setProgress($this->max ?? $this->step);
    }

    /**
     * Outputs the current progress string.
     */
    public function display(): void
    {
        if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }

        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }

        $this->overwrite($this->buildLine());
    }

    /**
     * Removes the progress bar from the current line.
     *
     * This is useful if you wish to write some output
     * while a progress bar is running.
     * Call display() to show the progress bar again.
     */
    public function clear(): void
    {
        if (!$this->overwrite) {
            return;
        }

        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }

        $this->overwrite('');
    }

    private function setRealFormat(string $format): void
    {
        // try to use the _nomax variant if available
        if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
            $this->format = self::getFormatDefinition($format.'_nomax');
        } elseif (null !== self::getFormatDefinition($format)) {
            $this->format = self::getFormatDefinition($format);
        } else {
            $this->format = $format;
        }
    }

    /**
     * Overwrites a previous message to the output.
     */
    private function overwrite(string $message): void
    {
        if ($this->previousMessage === $message) {
            return;
        }

        $originalMessage = $message;

        if ($this->overwrite) {
            if (null !== $this->previousMessage) {
                if ($this->output instanceof ConsoleSectionOutput) {
                    $messageLines = explode("\n", $this->previousMessage);
                    $lineCount = \count($messageLines);

                    $lastLineWithoutDecoration = Helper::removeDecoration($this->output->getFormatter(), end($messageLines) ?? '');

                    // When the last previous line is empty (without formatting) it is already cleared by the section output, so we don't need to clear it again
                    if ('' === $lastLineWithoutDecoration) {
                        --$lineCount;
                    }

                    foreach ($messageLines as $messageLine) {
                        $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine));
                        if ($messageLineLength > $this->terminal->getWidth()) {
                            $lineCount += floor($messageLineLength / $this->terminal->getWidth());
                        }
                    }

                    $this->output->clear($lineCount);
                } else {
                    $lineCount = substr_count($this->previousMessage, "\n");
                    for ($i = 0; $i < $lineCount; ++$i) {
                        $this->cursor->moveToColumn(1);
                        $this->cursor->clearLine();
                        $this->cursor->moveUp();
                    }

                    $this->cursor->moveToColumn(1);
                    $this->cursor->clearLine();
                }
            }
        } elseif ($this->step > 0) {
            $message = \PHP_EOL.$message;
        }

        $this->previousMessage = $originalMessage;
        $this->lastWriteTime = microtime(true);

        $this->output->write($message);
        ++$this->writeCount;
    }

    private function determineBestFormat(): string
    {
        return match ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            OutputInterface::VERBOSITY_VERBOSE => $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX,
            OutputInterface::VERBOSITY_VERY_VERBOSE => $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX,
            OutputInterface::VERBOSITY_DEBUG => $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX,
            default => $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX,
        };
    }

    private static function initPlaceholderFormatters(): array
    {
        return [
            'bar' => static function (self $bar, OutputInterface $output) {
                $completeBars = $bar->getBarOffset();
                $display = str_repeat($bar->getBarCharacter(), $completeBars);
                if ($completeBars < $bar->getBarWidth()) {
                    $emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter()));
                    $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
                }

                return $display;
            },
            'elapsed' => static fn (self $bar) => Helper::formatTime(time() - $bar->getStartTime(), 2),
            'remaining' => static function (self $bar) {
                if (null === $bar->max) {
                    throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
                }

                return Helper::formatTime($bar->getRemaining(), 2);
            },
            'estimated' => static function (self $bar) {
                if (null === $bar->max) {
                    throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
                }

                return Helper::formatTime($bar->getEstimated(), 2);
            },
            'memory' => static fn (self $bar) => Helper::formatMemory(memory_get_usage(true)),
            'current' => static fn (self $bar) => str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT),
            'max' => static fn (self $bar) => $bar->getMaxSteps(),
            'percent' => static fn (self $bar) => floor($bar->getProgressPercent() * 100),
        ];
    }

    private static function initFormats(): array
    {
        return [
            self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%',
            self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]',

            self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
            self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%',

            self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
            self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%',

            self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
            self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
        ];
    }

    private function buildLine(): string
    {
        \assert(null !== $this->format);

        $regex = '{%([a-z\-_]+)(?:\:([^%]+))?%}i';
        $callback = function ($matches) {
            if ($formatter = $this->getPlaceholderFormatter($matches[1])) {
                $text = $formatter($this, $this->output);
            } elseif (isset($this->messages[$matches[1]])) {
                $text = $this->messages[$matches[1]];
            } else {
                return $matches[0];
            }

            if (isset($matches[2])) {
                $text = \sprintf('%'.$matches[2], $text);
            }

            return $text;
        };
        $line = preg_replace_callback($regex, $callback, $this->format);

        // gets string length for each sub line with multiline format
        $linesLength = array_map(fn ($subLine) => Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r"))), explode("\n", $line));

        $linesWidth = max($linesLength);

        $terminalWidth = $this->terminal->getWidth();
        if ($linesWidth <= $terminalWidth) {
            return $line;
        }

        $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth);

        return preg_replace_callback($regex, $callback, $this->format);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * @implements \IteratorAggregate<TreeNode>
 *
 * @author Simon André <smn.andre@gmail.com>
 */
final class TreeNode implements \Countable, \IteratorAggregate
{
    /**
     * @var array<TreeNode|callable(): \Generator>
     */
    private array $children = [];

    public function __construct(
        private readonly string $value = '',
        iterable $children = [],
    ) {
        foreach ($children as $child) {
            $this->addChild($child);
        }
    }

    public static function fromValues(iterable $nodes, ?self $node = null): self
    {
        $node ??= new self();
        foreach ($nodes as $key => $value) {
            if (is_iterable($value)) {
                $child = new self($key);
                self::fromValues($value, $child);
                $node->addChild($child);
            } elseif ($value instanceof self) {
                $node->addChild($value);
            } else {
                $node->addChild(new self($value));
            }
        }

        return $node;
    }

    public function getValue(): string
    {
        return $this->value;
    }

    public function addChild(self|string|callable $node): self
    {
        if (\is_string($node)) {
            $node = new self($node);
        }

        $this->children[] = $node;

        return $this;
    }

    /**
     * @return \Traversable<int, TreeNode>
     */
    public function getChildren(): \Traversable
    {
        foreach ($this->children as $child) {
            if (\is_callable($child)) {
                yield from $child();
            } elseif ($child instanceof self) {
                yield $child;
            }
        }
    }

    /**
     * @return \Traversable<int, TreeNode>
     */
    public function getIterator(): \Traversable
    {
        return $this->getChildren();
    }

    public function count(): int
    {
        $count = 0;
        foreach ($this->getChildren() as $child) {
            ++$count;
        }

        return $count;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * @author Yewhen Khoptynskyi <khoptynskyi@gmail.com>
 */
class TableCellStyle
{
    public const DEFAULT_ALIGN = 'left';

    private const TAG_OPTIONS = [
        'fg',
        'bg',
        'options',
    ];

    private const ALIGN_MAP = [
        'left' => \STR_PAD_RIGHT,
        'center' => \STR_PAD_BOTH,
        'right' => \STR_PAD_LEFT,
    ];

    private array $options = [
        'fg' => 'default',
        'bg' => 'default',
        'options' => null,
        'align' => self::DEFAULT_ALIGN,
        'cellFormat' => null,
    ];

    public function __construct(array $options = [])
    {
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The TableCellStyle does not support the following options: \'%s\'.', implode('\', \'', $diff)));
        }

        if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) {
            throw new InvalidArgumentException(\sprintf('Wrong align value. Value must be following: \'%s\'.', implode('\', \'', array_keys(self::ALIGN_MAP))));
        }

        $this->options = array_merge($this->options, $options);
    }

    public function getOptions(): array
    {
        return $this->options;
    }

    /**
     * Gets options we need for tag for example fg, bg.
     *
     * @return string[]
     */
    public function getTagOptions(): array
    {
        return array_filter(
            $this->getOptions(),
            fn ($key) => \in_array($key, self::TAG_OPTIONS, true) && isset($this->options[$key]),
            \ARRAY_FILTER_USE_KEY
        );
    }

    public function getPadByAlign(): int
    {
        return self::ALIGN_MAP[$this->getOptions()['align']];
    }

    public function getCellFormat(): ?string
    {
        return $this->getOptions()['cellFormat'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Symfony Style Guide compliant question helper.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyQuestionHelper extends QuestionHelper
{
    protected function writePrompt(OutputInterface $output, Question $question): void
    {
        $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
        $default = $question->getDefault();

        if ($question->isMultiline()) {
            $text .= \sprintf(' (press %s to continue)', $this->getEofShortcut($output));
        }

        switch (true) {
            case null === $default:
                $text = \sprintf(' <info>%s</info>:', $text);

                break;

            case $question instanceof ConfirmationQuestion:
                $text = \sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');

                break;

            case $question instanceof ChoiceQuestion && $question->isMultiselect():
                $choices = $question->getChoices();
                $default = explode(',', $default);

                foreach ($default as $key => $value) {
                    $default[$key] = $choices[trim($value)];
                }

                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));

                break;

            case $question instanceof ChoiceQuestion:
                $choices = $question->getChoices();
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default] ?? $default));

                break;

            default:
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
        }

        $output->writeln($text);

        $prompt = ' > ';

        if ($question instanceof ChoiceQuestion) {
            $output->writeln($this->formatChoiceQuestionChoices($question, 'comment'));

            $prompt = $question->getPrompt();
        }

        $output->write($prompt);
    }

    protected function writeError(OutputInterface $output, \Exception $error): void
    {
        if ($output instanceof SymfonyStyle) {
            $output->newLine();
            $output->error($error->getMessage());

            return;
        }

        parent::writeError($output, $error);
    }

    private function getEofShortcut(OutputInterface $output): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR && !$output->isDecorated()) {
            return '<comment>Ctrl+Z</comment> then <comment>Enter</comment>';
        }

        return '<comment>Ctrl+D</comment>';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * TerminalInputHelper stops Ctrl-C and similar signals from leaving the terminal in
 * an unusable state if its settings have been modified when reading user input.
 * This can be an issue on non-Windows platforms.
 *
 * Usage:
 *
 *     $inputHelper = new TerminalInputHelper($inputStream);
 *
 *     ...change terminal settings
 *
 *     // Wait for input before all input reads
 *     $inputHelper->waitForInput();
 *
 *     ...read input
 *
 *     // Call finish to restore terminal settings and signal handlers
 *     $inputHelper->finish()
 *
 * @internal
 */
final class TerminalInputHelper
{
    /** @var resource */
    private $inputStream;
    private bool $isStdin;
    private string $initialState = '';
    private int $signalToKill = 0;
    private array $signalHandlers = [];
    private array $targetSignals = [];
    private bool $withStty;

    /**
     * @param resource $inputStream
     *
     * @throws \RuntimeException If unable to read terminal settings
     */
    public function __construct($inputStream, bool $withStty = true)
    {
        $this->inputStream = $inputStream;
        $this->isStdin = 'php://stdin' === stream_get_meta_data($inputStream)['uri'];
        $this->withStty = $withStty;

        if ($withStty) {
            if (!\is_string($state = shell_exec('stty -g'))) {
                throw new \RuntimeException('Unable to read the terminal settings.');
            }

            $this->initialState = $state;

            $this->createSignalHandlers();
        }
    }

    /**
     * Waits for input.
     */
    public function waitForInput(): void
    {
        if ($this->isStdin) {
            $r = [$this->inputStream];
            $w = [];

            // Allow signal handlers to run
            while (0 === @stream_select($r, $w, $w, 0, 100)) {
                $r = [$this->inputStream];
            }
        }

        if ($this->withStty) {
            $this->checkForKillSignal();
        }
    }

    /**
     * Restores terminal state and signal handlers.
     */
    public function finish(): void
    {
        if (!$this->withStty) {
            return;
        }

        // Safeguard in case an unhandled kill signal exists
        $this->checkForKillSignal();
        shell_exec('stty '.$this->initialState);
        $this->signalToKill = 0;

        foreach ($this->signalHandlers as $signal => $originalHandler) {
            pcntl_signal($signal, $originalHandler);
        }
        $this->signalHandlers = [];
        $this->targetSignals = [];
    }

    private function createSignalHandlers(): void
    {
        if (!\function_exists('pcntl_async_signals') || !\function_exists('pcntl_signal')) {
            return;
        }

        pcntl_async_signals(true);
        $this->targetSignals = [\SIGINT, \SIGQUIT, \SIGTERM];

        foreach ($this->targetSignals as $signal) {
            $this->signalHandlers[$signal] = pcntl_signal_get_handler($signal);

            pcntl_signal($signal, function ($signal) {
                // Save current state, then restore to initial state
                $currentState = shell_exec('stty -g');
                shell_exec('stty '.$this->initialState);
                $originalHandler = $this->signalHandlers[$signal];

                if (\is_callable($originalHandler)) {
                    $originalHandler($signal);
                    // Handler did not exit, so restore to current state
                    shell_exec('stty '.$currentState);

                    return;
                }

                // Not a callable, so SIG_DFL or SIG_IGN
                if (\SIG_DFL === $originalHandler) {
                    $this->signalToKill = $signal;
                }
            });
        }
    }

    private function checkForKillSignal(): void
    {
        if (\in_array($this->signalToKill, $this->targetSignals, true)) {
            // Try posix_kill
            if (\function_exists('posix_kill')) {
                pcntl_signal($this->signalToKill, \SIG_DFL);
                posix_kill(getmypid(), $this->signalToKill);
            }

            // Best attempt fallback
            exit(128 + $this->signalToKill);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface HelperInterface
{
    /**
     * Sets the helper set associated with this helper.
     */
    public function setHelperSet(?HelperSet $helperSet): void;

    /**
     * Gets the helper set associated with this helper.
     */
    public function getHelperSet(): ?HelperSet;

    /**
     * Returns the canonical name of this helper.
     */
    public function getName(): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Cursor;
use Symfony\Component\Console\Exception\MissingInputException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Terminal;

use function Symfony\Component\String\s;

/**
 * The QuestionHelper class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class QuestionHelper extends Helper
{
    private static bool $stty = true;
    private static bool $stdinIsInteractive;

    /**
     * Asks a question to the user.
     *
     * @return mixed The user answer
     *
     * @throws RuntimeException If there is no data to read in the input stream
     */
    public function ask(InputInterface $input, OutputInterface $output, Question $question): mixed
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        if (!$input->isInteractive()) {
            return $this->getDefaultAnswer($question);
        }

        $inputStream = $input instanceof StreamableInputInterface ? $input->getStream() : null;
        $inputStream ??= \STDIN;

        try {
            if (!$question->getValidator()) {
                return $this->doAsk($inputStream, $output, $question);
            }

            $interviewer = fn () => $this->doAsk($inputStream, $output, $question);

            return $this->validateAttempts($interviewer, $output, $question);
        } catch (MissingInputException $exception) {
            $input->setInteractive(false);

            if (null === $fallbackOutput = $this->getDefaultAnswer($question)) {
                throw $exception;
            }

            return $fallbackOutput;
        }
    }

    public function getName(): string
    {
        return 'question';
    }

    /**
     * Prevents usage of stty.
     */
    public static function disableStty(): void
    {
        self::$stty = false;
    }

    /**
     * Asks the question to the user.
     *
     * @param resource $inputStream
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function doAsk($inputStream, OutputInterface $output, Question $question): mixed
    {
        $this->writePrompt($output, $question);

        $autocomplete = $question->getAutocompleterCallback();

        if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
            $ret = false;
            if ($question->isHidden()) {
                try {
                    $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable());
                    $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse;
                } catch (RuntimeException $e) {
                    if (!$question->isHiddenFallback()) {
                        throw $e;
                    }
                }
            }

            if (false === $ret) {
                $isBlocked = stream_get_meta_data($inputStream)['blocked'] ?? true;

                if (!$isBlocked) {
                    stream_set_blocking($inputStream, true);
                }

                $ret = $this->readInput($inputStream, $question);

                if (!$isBlocked) {
                    stream_set_blocking($inputStream, false);
                }

                if (false === $ret) {
                    throw new MissingInputException('Aborted.');
                }
                if ($question->isTrimmable()) {
                    $ret = trim($ret);
                }
            }
        } else {
            $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete);
            $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete;
        }

        if ($output instanceof ConsoleSectionOutput) {
            $output->addContent(''); // add EOL to the question
            $output->addContent($ret);
        }

        $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();

        if ($normalizer = $question->getNormalizer()) {
            return $normalizer($ret);
        }

        return $ret;
    }

    private function getDefaultAnswer(Question $question): mixed
    {
        $default = $question->getDefault();

        if (null === $default) {
            return $default;
        }

        if ($validator = $question->getValidator()) {
            return \call_user_func($validator, $default);
        } elseif ($question instanceof ChoiceQuestion) {
            $choices = $question->getChoices();

            if (!$question->isMultiselect()) {
                return $choices[$default] ?? $default;
            }

            $default = explode(',', $default);
            foreach ($default as $k => $v) {
                $v = $question->isTrimmable() ? trim($v) : $v;
                $default[$k] = $choices[$v] ?? $v;
            }
        }

        return $default;
    }

    /**
     * Outputs the question prompt.
     */
    protected function writePrompt(OutputInterface $output, Question $question): void
    {
        $message = $question->getQuestion();

        if ($question instanceof ChoiceQuestion) {
            $output->writeln(array_merge([
                $question->getQuestion(),
            ], $this->formatChoiceQuestionChoices($question, 'info')));

            $message = $question->getPrompt();
        }

        $output->write($message);
    }

    /**
     * @return string[]
     */
    protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag): array
    {
        $messages = [];

        $maxWidth = max(array_map([__CLASS__, 'width'], array_keys($choices = $question->getChoices())));

        foreach ($choices as $key => $value) {
            $padding = str_repeat(' ', $maxWidth - self::width($key));

            $messages[] = \sprintf("  [<$tag>%s$padding</$tag>] %s", $key, $value);
        }

        return $messages;
    }

    /**
     * Outputs an error message.
     */
    protected function writeError(OutputInterface $output, \Exception $error): void
    {
        if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
            $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
        } else {
            $message = '<error>'.$error->getMessage().'</error>';
        }

        $output->writeln($message);
    }

    /**
     * Autocompletes a question.
     *
     * @param resource                  $inputStream
     * @param callable(string):string[] $autocomplete
     */
    private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string
    {
        $cursor = new Cursor($output, $inputStream);

        $fullChoice = '';
        $ret = '';

        $i = 0;
        $ofs = -1;
        $matches = $autocomplete($ret);
        $numMatches = \count($matches);
        $inputHelper = new TerminalInputHelper($inputStream);

        // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
        shell_exec('stty -icanon -echo');

        // Add highlighted text style
        $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));

        // Read a keypress
        while (!feof($inputStream)) {
            $inputHelper->waitForInput();
            $c = fread($inputStream, 1);

            // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
            if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) {
                // Restore the terminal so it behaves normally again
                $inputHelper->finish();
                throw new MissingInputException('Aborted while asking: '.$question->getQuestion());
            } elseif ("\177" === $c) { // Backspace Character
                if (0 === $numMatches && 0 !== $i) {
                    --$i;
                    $cursor->moveLeft(s($fullChoice)->slice(-1)->width(false));

                    $fullChoice = self::substr($fullChoice, 0, $i);
                }

                if (0 === $i) {
                    $ofs = -1;
                    $matches = $autocomplete($ret);
                    $numMatches = \count($matches);
                } else {
                    $numMatches = 0;
                }

                // Pop the last character off the end of our string
                $ret = self::substr($ret, 0, $i);
            } elseif ("\033" === $c) {
                // Did we read an escape sequence?
                $c .= fread($inputStream, 2);

                // A = Up Arrow. B = Down Arrow
                if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
                    if ('A' === $c[2] && -1 === $ofs) {
                        $ofs = 0;
                    }

                    if (0 === $numMatches) {
                        continue;
                    }

                    $ofs += ('A' === $c[2]) ? -1 : 1;
                    $ofs = ($numMatches + $ofs) % $numMatches;
                }
            } elseif ('' === $c || \ord($c) < 32) {
                if ("\t" === $c || "\n" === $c) {
                    if ($numMatches > 0 && -1 !== $ofs) {
                        $ret = (string) $matches[$ofs];
                        // Echo out remaining chars for current match
                        $remainingCharacters = substr($ret, \strlen($this->mostRecentlyEnteredValue($fullChoice)));
                        $output->write($remainingCharacters);
                        $fullChoice .= $remainingCharacters;
                        $i = (false === $encoding = mb_detect_encoding($fullChoice, null, true)) ? \strlen($fullChoice) : mb_strlen($fullChoice, $encoding);

                        $matches = array_filter(
                            $autocomplete($ret),
                            static fn ($match) => '' === $ret || str_starts_with($match, $ret)
                        );
                        $numMatches = \count($matches);
                        $ofs = -1;
                    }

                    if ("\n" === $c) {
                        $output->write($c);
                        break;
                    }

                    $numMatches = 0;
                }

                continue;
            } else {
                if ("\x80" <= $c) {
                    $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]);
                }

                $output->write($c);
                $ret .= $c;
                $fullChoice .= $c;
                ++$i;

                $tempRet = $ret;

                if ($question instanceof ChoiceQuestion && $question->isMultiselect()) {
                    $tempRet = $this->mostRecentlyEnteredValue($fullChoice);
                }

                $numMatches = 0;
                $ofs = 0;

                foreach ($autocomplete($ret) as $value) {
                    // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                    if (str_starts_with($value, $tempRet)) {
                        $matches[$numMatches++] = $value;
                    }
                }
            }

            $cursor->clearLineAfter();

            if ($numMatches > 0 && -1 !== $ofs) {
                $cursor->savePosition();
                // Write highlighted text, complete the partially entered response
                $charactersEntered = \strlen($this->mostRecentlyEnteredValue($fullChoice));
                $output->write('<hl>'.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).'</hl>');
                $cursor->restorePosition();
            }
        }

        // Restore the terminal so it behaves normally again
        $inputHelper->finish();

        return $fullChoice;
    }

    private function mostRecentlyEnteredValue(string $entered): string
    {
        // Determine the most recent value that the user entered
        if (!str_contains($entered, ',')) {
            return $entered;
        }

        if (false === $lastCommaPos = strrpos($entered, ',')) {
            return $entered;
        }

        $lastChoice = trim(substr($entered, $lastCommaPos + 1));

        return '' !== $lastChoice ? $lastChoice : $entered;
    }

    /**
     * Gets a hidden response from user.
     *
     * @param resource $inputStream The handler resource
     * @param bool     $trimmable   Is the answer trimmable
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';

            // handle code running from a phar
            if (str_starts_with(__FILE__, 'phar:')) {
                $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
                copy($exe, $tmpExe);
                $exe = $tmpExe;
            }

            $sExec = shell_exec('"'.$exe.'"');
            $value = $trimmable ? rtrim($sExec) : $sExec;
            $output->writeln('');

            if (isset($tmpExe)) {
                unlink($tmpExe);
            }

            return $value;
        }

        $inputHelper = null;

        if (self::$stty && Terminal::hasSttyAvailable()) {
            $inputHelper = new TerminalInputHelper($inputStream);
            shell_exec('stty -echo');
        } elseif ($this->isInteractiveInput($inputStream)) {
            throw new RuntimeException('Unable to hide the response.');
        }

        $value = $this->doReadInput($inputStream, helper: $inputHelper);

        if (4095 === \strlen($value)) {
            $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output;
            $errOutput->warning('The value was possibly truncated by your shell or terminal emulator');
        }

        // Restore the terminal so it behaves normally again
        $inputHelper?->finish();

        if ($trimmable) {
            $value = trim($value);
        }
        $output->writeln('');

        return $value;
    }

    /**
     * Validates an attempt.
     *
     * @param callable $interviewer A callable that will ask for a question and return the result
     *
     * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question): mixed
    {
        $error = null;
        $attempts = $question->getMaxAttempts();

        while (null === $attempts || $attempts--) {
            if (null !== $error) {
                $this->writeError($output, $error);
            }

            try {
                return $question->getValidator()($interviewer());
            } catch (MissingInputException $e) {
                throw $error ?? $e;
            } catch (RuntimeException $e) {
                throw $e;
            } catch (\Exception $error) {
            }
        }

        throw $error;
    }

    private function isInteractiveInput($inputStream): bool
    {
        if ('php://stdin' !== (stream_get_meta_data($inputStream)['uri'] ?? null)) {
            return false;
        }

        if (isset(self::$stdinIsInteractive)) {
            return self::$stdinIsInteractive;
        }

        return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r'));
    }

    /**
     * Reads one or more lines of input and returns what is read.
     *
     * @param resource $inputStream The handler resource
     * @param Question $question    The question being asked
     */
    private function readInput($inputStream, Question $question): string|false
    {
        if (null !== $question->getTimeout() && $this->isInteractiveInput($inputStream)) {
            $read = [$inputStream];
            $write = null;
            $except = null;
            $timeoutSeconds = $question->getTimeout();
            $changedStreams = stream_select($read, $write, $except, $timeoutSeconds);

            if (0 === $changedStreams) {
                throw new MissingInputException(\sprintf('Timed out after waiting for input for %d second%s.', $timeoutSeconds, 1 === $timeoutSeconds ? '' : 's'));
            }
        }

        if (!$question->isMultiline()) {
            $cp = $this->setIOCodepage();
            $ret = $this->doReadInput($inputStream);

            return $this->resetIOCodepage($cp, $ret);
        }

        $multiLineStreamReader = $this->cloneInputStream($inputStream);
        if (null === $multiLineStreamReader) {
            return false;
        }

        $cp = $this->setIOCodepage();
        $ret = $this->doReadInput($multiLineStreamReader, "\x4");

        if (stream_get_meta_data($inputStream)['seekable']) {
            fseek($inputStream, ftell($multiLineStreamReader));
        }

        return $this->resetIOCodepage($cp, $ret);
    }

    private function setIOCodepage(): int
    {
        if (\function_exists('sapi_windows_cp_set')) {
            $cp = sapi_windows_cp_get();
            sapi_windows_cp_set(sapi_windows_cp_get('oem'));

            return $cp;
        }

        return 0;
    }

    /**
     * Sets console I/O to the specified code page and converts the user input.
     */
    private function resetIOCodepage(int $cp, string|false $input): string|false
    {
        if (0 !== $cp) {
            sapi_windows_cp_set($cp);

            if (false !== $input && '' !== $input) {
                $input = sapi_windows_cp_conv(sapi_windows_cp_get('oem'), $cp, $input);
            }
        }

        return $input;
    }

    /**
     * Clones an input stream in order to act on one instance of the same
     * stream without affecting the other instance.
     *
     * @param resource $inputStream The handler resource
     *
     * @return resource|null The cloned resource, null in case it could not be cloned
     */
    private function cloneInputStream($inputStream)
    {
        $streamMetaData = stream_get_meta_data($inputStream);
        $seekable = $streamMetaData['seekable'] ?? false;
        $mode = $streamMetaData['mode'] ?? 'rb';
        $uri = $streamMetaData['uri'] ?? null;

        if (null === $uri) {
            return null;
        }

        $cloneStream = fopen($uri, $mode);

        // For seekable and writable streams, add all the same data to the
        // cloned stream and then seek to the same offset.
        if (true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'], true)) {
            $offset = ftell($inputStream);
            rewind($inputStream);
            stream_copy_to_stream($inputStream, $cloneStream);
            fseek($inputStream, $offset);
            fseek($cloneStream, $offset);
        }

        return $cloneStream;
    }

    /**
     * @param resource $inputStream
     */
    private function doReadInput($inputStream, ?string $exitChar = null, ?TerminalInputHelper $helper = null): string
    {
        $ret = '';
        $helper ??= new TerminalInputHelper($inputStream, false);

        while (!feof($inputStream)) {
            $helper->waitForInput();
            $char = fread($inputStream, 1);

            // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
            if (false === $char || ('' === $ret && '' === $char)) {
                throw new MissingInputException('Aborted.');
            }

            if (\PHP_EOL === "{$ret}{$char}" || $exitChar === $char) {
                break;
            }

            $ret .= $char;

            if (null === $exitChar && "\n" === $char) {
                break;
            }
        }

        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;

/**
 * Defines the styles for a Table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Саша Стаменковић <umpirsky@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class TableStyle
{
    private string $paddingChar = ' ';
    private string $horizontalOutsideBorderChar = '-';
    private string $horizontalInsideBorderChar = '-';
    private string $verticalOutsideBorderChar = '|';
    private string $verticalInsideBorderChar = '|';
    private string $crossingChar = '+';
    private string $crossingTopRightChar = '+';
    private string $crossingTopMidChar = '+';
    private string $crossingTopLeftChar = '+';
    private string $crossingMidRightChar = '+';
    private string $crossingBottomRightChar = '+';
    private string $crossingBottomMidChar = '+';
    private string $crossingBottomLeftChar = '+';
    private string $crossingMidLeftChar = '+';
    private string $crossingTopLeftBottomChar = '+';
    private string $crossingTopMidBottomChar = '+';
    private string $crossingTopRightBottomChar = '+';
    private string $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
    private string $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
    private string $cellHeaderFormat = '<info>%s</info>';
    private string $cellRowFormat = '%s';
    private string $cellRowContentFormat = ' %s ';
    private string $borderFormat = '%s';
    private bool $displayOutsideBorder = true;
    private int $padType = \STR_PAD_RIGHT;

    /**
     * Sets padding character, used for cell padding.
     *
     * @return $this
     */
    public function setPaddingChar(string $paddingChar): static
    {
        if (!$paddingChar) {
            throw new LogicException('The padding char must not be empty.');
        }

        $this->paddingChar = $paddingChar;

        return $this;
    }

    /**
     * Gets padding character, used for cell padding.
     */
    public function getPaddingChar(): string
    {
        return $this->paddingChar;
    }

    /**
     * Sets horizontal border characters.
     *
     * <code>
     * ╔═══════════════╤══════════════════════════╤══════════════════╗
     * ║ ISBN          │ Title                    │ Author           ║
     * ╠═══════1═══════╪══════════════════════════╪══════════════════╣
     * ║ 99921-58-10-7 │ Divine Comedy            │ Dante Alighieri  ║
     * ║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
     * ╟───────2───────┼──────────────────────────┼──────────────────╢
     * ║ 960-425-059-0 │ The Lord of the Rings    │ J. R. R. Tolkien ║
     * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie  ║
     * ╚═══════════════╧══════════════════════════╧══════════════════╝
     * </code>
     *
     * @return $this
     */
    public function setHorizontalBorderChars(string $outside, ?string $inside = null): static
    {
        $this->horizontalOutsideBorderChar = $outside;
        $this->horizontalInsideBorderChar = $inside ?? $outside;

        return $this;
    }

    /**
     * Sets vertical border characters.
     *
     * <code>
     * ╔═══════════════╤══════════════════════════╤══════════════════╗
     * 1 ISBN          2 Title                    │ Author           ║
     * ╠═══════════════╪══════════════════════════╪══════════════════╣
     * ║ 99921-58-10-7 │ Divine Comedy            │ Dante Alighieri  ║
     * ║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
     * ║ 960-425-059-0 │ The Lord of the Rings    │ J. R. R. Tolkien ║
     * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie  ║
     * ╚═══════════════╧══════════════════════════╧══════════════════╝
     * </code>
     *
     * @return $this
     */
    public function setVerticalBorderChars(string $outside, ?string $inside = null): static
    {
        $this->verticalOutsideBorderChar = $outside;
        $this->verticalInsideBorderChar = $inside ?? $outside;

        return $this;
    }

    /**
     * Gets border characters.
     *
     * @internal
     */
    public function getBorderChars(): array
    {
        return [
            $this->horizontalOutsideBorderChar,
            $this->verticalOutsideBorderChar,
            $this->horizontalInsideBorderChar,
            $this->verticalInsideBorderChar,
        ];
    }

    /**
     * Sets crossing characters.
     *
     * Example:
     * <code>
     * 1═══════════════2══════════════════════════2══════════════════3
     * ║ ISBN          │ Title                    │ Author           ║
     * 8'══════════════0'═════════════════════════0'═════════════════4'
     * ║ 99921-58-10-7 │ Divine Comedy            │ Dante Alighieri  ║
     * ║ 9971-5-0210-0 │ A Tale of Two Cities     │ Charles Dickens  ║
     * 8───────────────0──────────────────────────0──────────────────4
     * ║ 960-425-059-0 │ The Lord of the Rings    │ J. R. R. Tolkien ║
     * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie  ║
     * 7═══════════════6══════════════════════════6══════════════════5
     * </code>
     *
     * @param string      $cross          Crossing char (see #0 of example)
     * @param string      $topLeft        Top left char (see #1 of example)
     * @param string      $topMid         Top mid char (see #2 of example)
     * @param string      $topRight       Top right char (see #3 of example)
     * @param string      $midRight       Mid right char (see #4 of example)
     * @param string      $bottomRight    Bottom right char (see #5 of example)
     * @param string      $bottomMid      Bottom mid char (see #6 of example)
     * @param string      $bottomLeft     Bottom left char (see #7 of example)
     * @param string      $midLeft        Mid left char (see #8 of example)
     * @param string|null $topLeftBottom  Top left bottom char (see #8' of example), equals to $midLeft if null
     * @param string|null $topMidBottom   Top mid bottom char (see #0' of example), equals to $cross if null
     * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null
     *
     * @return $this
     */
    public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, ?string $topLeftBottom = null, ?string $topMidBottom = null, ?string $topRightBottom = null): static
    {
        $this->crossingChar = $cross;
        $this->crossingTopLeftChar = $topLeft;
        $this->crossingTopMidChar = $topMid;
        $this->crossingTopRightChar = $topRight;
        $this->crossingMidRightChar = $midRight;
        $this->crossingBottomRightChar = $bottomRight;
        $this->crossingBottomMidChar = $bottomMid;
        $this->crossingBottomLeftChar = $bottomLeft;
        $this->crossingMidLeftChar = $midLeft;
        $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft;
        $this->crossingTopMidBottomChar = $topMidBottom ?? $cross;
        $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight;

        return $this;
    }

    /**
     * Sets default crossing character used for each cross.
     *
     * @see {@link setCrossingChars()} for setting each crossing individually.
     */
    public function setDefaultCrossingChar(string $char): self
    {
        return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char);
    }

    /**
     * Gets crossing character.
     */
    public function getCrossingChar(): string
    {
        return $this->crossingChar;
    }

    /**
     * Gets crossing characters.
     *
     * @internal
     */
    public function getCrossingChars(): array
    {
        return [
            $this->crossingChar,
            $this->crossingTopLeftChar,
            $this->crossingTopMidChar,
            $this->crossingTopRightChar,
            $this->crossingMidRightChar,
            $this->crossingBottomRightChar,
            $this->crossingBottomMidChar,
            $this->crossingBottomLeftChar,
            $this->crossingMidLeftChar,
            $this->crossingTopLeftBottomChar,
            $this->crossingTopMidBottomChar,
            $this->crossingTopRightBottomChar,
        ];
    }

    /**
     * Sets header cell format.
     *
     * @return $this
     */
    public function setCellHeaderFormat(string $cellHeaderFormat): static
    {
        $this->cellHeaderFormat = $cellHeaderFormat;

        return $this;
    }

    /**
     * Gets header cell format.
     */
    public function getCellHeaderFormat(): string
    {
        return $this->cellHeaderFormat;
    }

    /**
     * Sets row cell format.
     *
     * @return $this
     */
    public function setCellRowFormat(string $cellRowFormat): static
    {
        $this->cellRowFormat = $cellRowFormat;

        return $this;
    }

    /**
     * Gets row cell format.
     */
    public function getCellRowFormat(): string
    {
        return $this->cellRowFormat;
    }

    /**
     * Sets row cell content format.
     *
     * @return $this
     */
    public function setCellRowContentFormat(string $cellRowContentFormat): static
    {
        $this->cellRowContentFormat = $cellRowContentFormat;

        return $this;
    }

    /**
     * Gets row cell content format.
     */
    public function getCellRowContentFormat(): string
    {
        return $this->cellRowContentFormat;
    }

    /**
     * Sets table border format.
     *
     * @return $this
     */
    public function setBorderFormat(string $borderFormat): static
    {
        $this->borderFormat = $borderFormat;

        return $this;
    }

    /**
     * Gets table border format.
     */
    public function getBorderFormat(): string
    {
        return $this->borderFormat;
    }

    /**
     * Sets cell padding type.
     *
     * @return $this
     */
    public function setPadType(int $padType): static
    {
        if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) {
            throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
        }

        $this->padType = $padType;

        return $this;
    }

    /**
     * Gets cell padding type.
     */
    public function getPadType(): int
    {
        return $this->padType;
    }

    public function getHeaderTitleFormat(): string
    {
        return $this->headerTitleFormat;
    }

    /**
     * @return $this
     */
    public function setHeaderTitleFormat(string $format): static
    {
        $this->headerTitleFormat = $format;

        return $this;
    }

    public function getFooterTitleFormat(): string
    {
        return $this->footerTitleFormat;
    }

    /**
     * @return $this
     */
    public function setFooterTitleFormat(string $format): static
    {
        $this->footerTitleFormat = $format;

        return $this;
    }

    public function setDisplayOutsideBorder($displayOutSideBorder): static
    {
        $this->displayOutsideBorder = $displayOutSideBorder;

        return $this;
    }

    public function displayOutsideBorder(): bool
    {
        return $this->displayOutsideBorder;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * Marks a row as being a separator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TableSeparator extends TableCell
{
    public function __construct(array $options = [])
    {
        parent::__construct('', $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\String\UnicodeString;

/**
 * Helper is the base class for all helper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Helper implements HelperInterface
{
    protected ?HelperSet $helperSet = null;

    public function setHelperSet(?HelperSet $helperSet): void
    {
        $this->helperSet = $helperSet;
    }

    public function getHelperSet(): ?HelperSet
    {
        return $this->helperSet;
    }

    /**
     * Returns the width of a string, using mb_strwidth if it is available.
     * The width is how many characters positions the string will use.
     */
    public static function width(?string $string): int
    {
        $string ??= '';

        if (preg_match('//u', $string)) {
            $string = preg_replace('/[\p{Cc}\x7F]++/u', '', $string, -1, $count);

            return (new UnicodeString($string))->width(false) + $count;
        }

        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return \strlen($string);
        }

        return mb_strwidth($string, $encoding);
    }

    /**
     * Returns the length of a string, using mb_strlen if it is available.
     * The length is related to how many bytes the string will use.
     */
    public static function length(?string $string): int
    {
        $string ??= '';

        if (preg_match('//u', $string)) {
            return (new UnicodeString($string))->length();
        }

        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return \strlen($string);
        }

        return mb_strlen($string, $encoding);
    }

    /**
     * Returns the subset of a string, using mb_substr if it is available.
     */
    public static function substr(?string $string, int $from, ?int $length = null): string
    {
        $string ??= '';

        if (preg_match('//u', $string)) {
            return (new UnicodeString($string))->slice($from, $length);
        }

        if (false === $encoding = mb_detect_encoding($string, null, true)) {
            return substr($string, $from, $length);
        }

        return mb_substr($string, $from, $length, $encoding);
    }

    public static function formatTime(int|float $secs, int $precision = 1): string
    {
        $ms = (int) ($secs * 1000);
        $secs = (int) floor($secs);

        if (0 === $ms) {
            return '< 1 ms';
        }

        static $timeFormats = [
            [1, 'ms'],
            [1000, 's'],
            [60000, 'min'],
            [3600000, 'h'],
            [86_400_000, 'd'],
        ];

        $times = [];
        foreach ($timeFormats as $index => $format) {
            $milliSeconds = isset($timeFormats[$index + 1]) ? $ms % $timeFormats[$index + 1][0] : $ms;

            if (isset($times[$index - $precision])) {
                unset($times[$index - $precision]);
            }

            if (0 === $milliSeconds) {
                continue;
            }

            $unitCount = ($milliSeconds / $format[0]);
            $times[$index] = $unitCount.' '.$format[1];

            if ($ms === $milliSeconds) {
                break;
            }

            $ms -= $milliSeconds;
        }

        return implode(', ', array_reverse($times));
    }

    public static function formatMemory(int $memory): string
    {
        if ($memory >= 1024 * 1024 * 1024) {
            return \sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
        }

        if ($memory >= 1024 * 1024) {
            return \sprintf('%.1f MiB', $memory / 1024 / 1024);
        }

        if ($memory >= 1024) {
            return \sprintf('%d KiB', $memory / 1024);
        }

        return \sprintf('%d B', $memory);
    }

    public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string): string
    {
        $isDecorated = $formatter->isDecorated();
        $formatter->setDecorated(false);
        // remove <...> formatting
        $string = $formatter->format($string ?? '');
        // remove already formatted characters
        $string = preg_replace("/\033\[[^m]*m/", '', $string ?? '');
        // remove terminal hyperlinks
        $string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string ?? '');
        $formatter->setDecorated($isDecorated);

        return $string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * The TreeHelper class provides methods to display tree-like structures.
 *
 * @author Simon André <smn.andre@gmail.com>
 *
 * @implements \RecursiveIterator<int, TreeNode>
 */
final class TreeHelper implements \RecursiveIterator
{
    /**
     * @var \Iterator<int, TreeNode>
     */
    private \Iterator $children;

    private function __construct(
        private readonly OutputInterface $output,
        private readonly TreeNode $node,
        private readonly TreeStyle $style,
    ) {
        $this->children = new \IteratorIterator($this->node->getChildren());
        $this->children->rewind();
    }

    public static function createTree(OutputInterface $output, string|TreeNode|null $root = null, iterable $values = [], ?TreeStyle $style = null): self
    {
        $node = $root instanceof TreeNode ? $root : new TreeNode($root ?? '');

        return new self($output, TreeNode::fromValues($values, $node), $style ?? TreeStyle::default());
    }

    public function current(): TreeNode
    {
        return $this->children->current();
    }

    public function key(): int
    {
        return $this->children->key();
    }

    public function next(): void
    {
        $this->children->next();
    }

    public function rewind(): void
    {
        $this->children->rewind();
    }

    public function valid(): bool
    {
        return $this->children->valid();
    }

    public function hasChildren(): bool
    {
        if (null === $current = $this->current()) {
            return false;
        }

        foreach ($current->getChildren() as $child) {
            return true;
        }

        return false;
    }

    public function getChildren(): \RecursiveIterator
    {
        return new self($this->output, $this->current(), $this->style);
    }

    /**
     * Recursively renders the tree to the output, applying the tree style.
     */
    public function render(): void
    {
        $treeIterator = new \RecursiveTreeIterator($this);

        $this->style->applyPrefixes($treeIterator);

        $this->output->writeln($this->node->getValue());

        $visited = new \SplObjectStorage();
        foreach ($treeIterator as $node) {
            $currentNode = $node instanceof TreeNode ? $node : $treeIterator->getInnerIterator()->current();
            if (isset($visited[$currentNode])) {
                throw new \LogicException(\sprintf('Cycle detected at node: "%s".', $currentNode->getValue()));
            }
            $visited[$currentNode] = true;

            $this->output->writeln($node);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * Configures the output of the Tree helper.
 *
 * @author Simon André <smn.andre@gmail.com>
 */
final class TreeStyle
{
    public function __construct(
        private readonly string $prefixEndHasNext,
        private readonly string $prefixEndLast,
        private readonly string $prefixLeft,
        private readonly string $prefixMidHasNext,
        private readonly string $prefixMidLast,
        private readonly string $prefixRight,
    ) {
    }

    public static function box(): self
    {
        return new self('┃╸ ', '┗╸ ', '', '┃  ', '   ', '');
    }

    public static function boxDouble(): self
    {
        return new self('╠═ ', '╚═ ', '', '║  ', '  ', '');
    }

    public static function compact(): self
    {
        return new self('├ ', '└ ', '', '│ ', '  ', '');
    }

    public static function default(): self
    {
        return new self('├── ', '└── ', '', '│   ', '   ', '');
    }

    public static function light(): self
    {
        return new self('|-- ', '`-- ', '', '|   ', '    ', '');
    }

    public static function minimal(): self
    {
        return new self('. ', '. ', '', '. ', '  ', '');
    }

    public static function rounded(): self
    {
        return new self('├─ ', '╰─ ', '', '│  ', '   ', '');
    }

    /**
     * @internal
     */
    public function applyPrefixes(\RecursiveTreeIterator $iterator): void
    {
        $iterator->setPrefixPart(\RecursiveTreeIterator::PREFIX_LEFT, $this->prefixLeft);
        $iterator->setPrefixPart(\RecursiveTreeIterator::PREFIX_MID_HAS_NEXT, $this->prefixMidHasNext);
        $iterator->setPrefixPart(\RecursiveTreeIterator::PREFIX_MID_LAST, $this->prefixMidLast);
        $iterator->setPrefixPart(\RecursiveTreeIterator::PREFIX_END_HAS_NEXT, $this->prefixEndHasNext);
        $iterator->setPrefixPart(\RecursiveTreeIterator::PREFIX_END_LAST, $this->prefixEndLast);
        $iterator->setPrefixPart(\RecursiveTreeIterator::PREFIX_RIGHT, $this->prefixRight);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class ProgressIndicator
{
    private const FORMATS = [
        'normal' => ' %indicator% %message%',
        'normal_no_ansi' => ' %message%',

        'verbose' => ' %indicator% %message% (%elapsed:6s%)',
        'verbose_no_ansi' => ' %message% (%elapsed:6s%)',

        'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
        'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
    ];

    private int $startTime;
    private ?string $format = null;
    private ?string $message = null;
    private array $indicatorValues;
    private int $indicatorCurrent;
    private string $finishedIndicatorValue;
    private float $indicatorUpdateTime;
    private bool $started = false;
    private bool $finished = false;

    /**
     * @var array<string, callable>
     */
    private static array $formatters;

    /**
     * @param int        $indicatorChangeInterval Change interval in milliseconds
     * @param array|null $indicatorValues         Animated indicator characters
     */
    public function __construct(
        private OutputInterface $output,
        ?string $format = null,
        private int $indicatorChangeInterval = 100,
        ?array $indicatorValues = null,
        ?string $finishedIndicatorValue = null,
    ) {
        $format ??= $this->determineBestFormat();
        $indicatorValues ??= ['-', '\\', '|', '/'];
        $indicatorValues = array_values($indicatorValues);
        $finishedIndicatorValue ??= '✔';

        if (2 > \count($indicatorValues)) {
            throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
        }

        $this->format = self::getFormatDefinition($format);
        $this->indicatorValues = $indicatorValues;
        $this->finishedIndicatorValue = $finishedIndicatorValue;
        $this->startTime = time();
    }

    /**
     * Sets the current indicator message.
     */
    public function setMessage(?string $message): void
    {
        $this->message = $message;

        $this->display();
    }

    /**
     * Starts the indicator output.
     */
    public function start(string $message): void
    {
        if ($this->started) {
            throw new LogicException('Progress indicator already started.');
        }

        $this->message = $message;
        $this->started = true;
        $this->finished = false;
        $this->startTime = time();
        $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
        $this->indicatorCurrent = 0;

        $this->display();
    }

    /**
     * Advances the indicator.
     */
    public function advance(): void
    {
        if (!$this->started) {
            throw new LogicException('Progress indicator has not yet been started.');
        }

        if (!$this->output->isDecorated()) {
            return;
        }

        $currentTime = $this->getCurrentTimeInMilliseconds();

        if ($currentTime < $this->indicatorUpdateTime) {
            return;
        }

        $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
        ++$this->indicatorCurrent;

        $this->display();
    }

    /**
     * Finish the indicator with message.
     *
     * @param ?string $finishedIndicator
     */
    public function finish(string $message/* , ?string $finishedIndicator = null */): void
    {
        $finishedIndicator = 1 < \func_num_args() ? func_get_arg(1) : null;
        if (null !== $finishedIndicator && !\is_string($finishedIndicator)) {
            throw new \TypeError(\sprintf('Argument 2 passed to "%s()" must be of the type string or null, "%s" given.', __METHOD__, get_debug_type($finishedIndicator)));
        }

        if (!$this->started) {
            throw new LogicException('Progress indicator has not yet been started.');
        }

        if (null !== $finishedIndicator) {
            $this->finishedIndicatorValue = $finishedIndicator;
        }

        $this->finished = true;
        $this->message = $message;
        $this->display();
        if (!$this->output instanceof ConsoleSectionOutput) {
            $this->output->writeln('');
        }
        $this->started = false;
    }

    /**
     * Gets the format for a given name.
     */
    public static function getFormatDefinition(string $name): ?string
    {
        return self::FORMATS[$name] ?? null;
    }

    /**
     * Sets a placeholder formatter for a given name.
     *
     * This method also allow you to override an existing placeholder.
     */
    public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void
    {
        self::$formatters ??= self::initPlaceholderFormatters();

        self::$formatters[$name] = $callable;
    }

    /**
     * Gets the placeholder formatter for a given name (including the delimiter char like %).
     */
    public static function getPlaceholderFormatterDefinition(string $name): ?callable
    {
        self::$formatters ??= self::initPlaceholderFormatters();

        return self::$formatters[$name] ?? null;
    }

    private function display(): void
    {
        if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }

        $this->overwrite(preg_replace_callback('{%([a-z\-_]+)(?:\:([^%]+))?%}i', function ($matches) {
            if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) {
                return $formatter($this);
            }

            return $matches[0];
        }, $this->format ?? ''));
    }

    private function determineBestFormat(): string
    {
        return match ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            OutputInterface::VERBOSITY_VERBOSE => $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi',
            OutputInterface::VERBOSITY_VERY_VERBOSE,
            OutputInterface::VERBOSITY_DEBUG => $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi',
            default => $this->output->isDecorated() ? 'normal' : 'normal_no_ansi',
        };
    }

    /**
     * Overwrites a previous message to the output.
     */
    private function overwrite(string $message): void
    {
        if ($this->output instanceof ConsoleSectionOutput) {
            $this->output->overwrite($message);
        } elseif ($this->output->isDecorated()) {
            $this->output->write("\x0D\x1B[2K");
            $this->output->write($message);
        } else {
            $this->output->writeln($message);
        }
    }

    private function getCurrentTimeInMilliseconds(): float
    {
        return round(microtime(true) * 1000);
    }

    /**
     * @return array<string, \Closure>
     */
    private static function initPlaceholderFormatters(): array
    {
        return [
            'indicator' => static fn (self $indicator) => $indicator->finished ? $indicator->finishedIndicatorValue : $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)],
            'message' => static fn (self $indicator) => $indicator->message,
            'elapsed' => static fn (self $indicator) => Helper::formatTime(time() - $indicator->startTime, 2),
            'memory' => static fn () => Helper::formatMemory(memory_get_usage(true)),
        ];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * @internal
 */
class TableRows implements \IteratorAggregate
{
    public function __construct(
        private \Closure $generator,
    ) {
    }

    public function getIterator(): \Traversable
    {
        return ($this->generator)();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Descriptor\DescriptorInterface;
use Symfony\Component\Console\Descriptor\JsonDescriptor;
use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use Symfony\Component\Console\Descriptor\ReStructuredTextDescriptor;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * This class adds helper method to describe objects in various formats.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DescriptorHelper extends Helper
{
    /**
     * @var DescriptorInterface[]
     */
    private array $descriptors = [];

    public function __construct()
    {
        $this
            ->register('txt', new TextDescriptor())
            ->register('xml', new XmlDescriptor())
            ->register('json', new JsonDescriptor())
            ->register('md', new MarkdownDescriptor())
            ->register('rst', new ReStructuredTextDescriptor())
        ;
    }

    /**
     * Describes an object if supported.
     *
     * Available options are:
     * * format: string, the output format name
     * * raw_text: boolean, sets output type as raw
     *
     * @throws InvalidArgumentException when the given format is not supported
     */
    public function describe(OutputInterface $output, ?object $object, array $options = []): void
    {
        $options = array_merge([
            'raw_text' => false,
            'format' => 'txt',
        ], $options);

        if (!isset($this->descriptors[$options['format']])) {
            throw new InvalidArgumentException(\sprintf('Unsupported format "%s".', $options['format']));
        }

        $descriptor = $this->descriptors[$options['format']];
        $descriptor->describe($output, $object, $options);
    }

    /**
     * Registers a descriptor.
     *
     * @return $this
     */
    public function register(string $format, DescriptorInterface $descriptor): static
    {
        $this->descriptors[$format] = $descriptor;

        return $this;
    }

    public function getName(): string
    {
        return 'descriptor';
    }

    public function getFormats(): array
    {
        return array_keys($this->descriptors);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface;
use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Provides helpers to display a table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Саша Стаменковић <umpirsky@gmail.com>
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 * @author Max Grigorian <maxakawizard@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class Table
{
    private const SEPARATOR_TOP = 0;
    private const SEPARATOR_TOP_BOTTOM = 1;
    private const SEPARATOR_MID = 2;
    private const SEPARATOR_BOTTOM = 3;
    private const BORDER_OUTSIDE = 0;
    private const BORDER_INSIDE = 1;
    private const DISPLAY_ORIENTATION_DEFAULT = 'default';
    private const DISPLAY_ORIENTATION_HORIZONTAL = 'horizontal';
    private const DISPLAY_ORIENTATION_VERTICAL = 'vertical';

    private ?string $headerTitle = null;
    private ?string $footerTitle = null;
    private array $headers = [];
    private array $rows = [];
    private array $effectiveColumnWidths = [];
    private int $numberOfColumns;
    private TableStyle $style;
    private array $columnStyles = [];
    private array $columnWidths = [];
    private array $columnMaxWidths = [];
    private bool $rendered = false;
    private string $displayOrientation = self::DISPLAY_ORIENTATION_DEFAULT;

    private static array $styles;

    public function __construct(
        private OutputInterface $output,
    ) {
        self::$styles ??= self::initStyles();

        $this->setStyle('default');
    }

    /**
     * Sets a style definition.
     */
    public static function setStyleDefinition(string $name, TableStyle $style): void
    {
        self::$styles ??= self::initStyles();

        self::$styles[$name] = $style;
    }

    /**
     * Gets a style definition by name.
     */
    public static function getStyleDefinition(string $name): TableStyle
    {
        self::$styles ??= self::initStyles();

        return self::$styles[$name] ?? throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
    }

    /**
     * Sets table style.
     *
     * @return $this
     */
    public function setStyle(TableStyle|string $name): static
    {
        $this->style = $this->resolveStyle($name);

        return $this;
    }

    /**
     * Gets the current table style.
     */
    public function getStyle(): TableStyle
    {
        return $this->style;
    }

    /**
     * Sets table column style.
     *
     * @param TableStyle|string $name The style name or a TableStyle instance
     *
     * @return $this
     */
    public function setColumnStyle(int $columnIndex, TableStyle|string $name): static
    {
        $this->columnStyles[$columnIndex] = $this->resolveStyle($name);

        return $this;
    }

    /**
     * Gets the current style for a column.
     *
     * If style was not set, it returns the global table style.
     */
    public function getColumnStyle(int $columnIndex): TableStyle
    {
        return $this->columnStyles[$columnIndex] ?? $this->getStyle();
    }

    /**
     * Sets the minimum width of a column.
     *
     * @return $this
     */
    public function setColumnWidth(int $columnIndex, int $width): static
    {
        $this->columnWidths[$columnIndex] = $width;

        return $this;
    }

    /**
     * Sets the minimum width of all columns.
     *
     * @return $this
     */
    public function setColumnWidths(array $widths): static
    {
        $this->columnWidths = [];
        foreach ($widths as $index => $width) {
            $this->setColumnWidth($index, $width);
        }

        return $this;
    }

    /**
     * Sets the maximum width of a column.
     *
     * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while
     * formatted strings are preserved.
     *
     * @return $this
     */
    public function setColumnMaxWidth(int $columnIndex, int $width): static
    {
        if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) {
            throw new \LogicException(\sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, get_debug_type($this->output->getFormatter())));
        }

        $this->columnMaxWidths[$columnIndex] = $width;

        return $this;
    }

    /**
     * @return $this
     */
    public function setHeaders(array $headers): static
    {
        $headers = array_values($headers);
        if ($headers && !\is_array($headers[0])) {
            $headers = [$headers];
        }

        $this->headers = $headers;

        return $this;
    }

    /**
     * @return $this
     */
    public function setRows(array $rows): static
    {
        $this->rows = [];

        return $this->addRows($rows);
    }

    /**
     * @return $this
     */
    public function addRows(array $rows): static
    {
        foreach ($rows as $row) {
            $this->addRow($row);
        }

        return $this;
    }

    /**
     * @return $this
     */
    public function addRow(TableSeparator|array $row): static
    {
        if ($row instanceof TableSeparator) {
            $this->rows[] = $row;

            return $this;
        }

        $this->rows[] = array_values($row);

        return $this;
    }

    /**
     * Adds a row to the table, and re-renders the table.
     *
     * @return $this
     */
    public function appendRow(TableSeparator|array $row): static
    {
        if (!$this->output instanceof ConsoleSectionOutput) {
            throw new RuntimeException(\sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__));
        }

        if ($this->rendered) {
            $this->output->clear($this->calculateRowCount());
        }

        $this->addRow($row);
        $this->render();

        return $this;
    }

    /**
     * @return $this
     */
    public function setRow(int|string $column, array $row): static
    {
        $this->rows[$column] = $row;

        return $this;
    }

    /**
     * @return $this
     */
    public function setHeaderTitle(?string $title): static
    {
        $this->headerTitle = $title;

        return $this;
    }

    /**
     * @return $this
     */
    public function setFooterTitle(?string $title): static
    {
        $this->footerTitle = $title;

        return $this;
    }

    /**
     * @return $this
     */
    public function setHorizontal(bool $horizontal = true): static
    {
        $this->displayOrientation = $horizontal ? self::DISPLAY_ORIENTATION_HORIZONTAL : self::DISPLAY_ORIENTATION_DEFAULT;

        return $this;
    }

    /**
     * @return $this
     */
    public function setVertical(bool $vertical = true): static
    {
        $this->displayOrientation = $vertical ? self::DISPLAY_ORIENTATION_VERTICAL : self::DISPLAY_ORIENTATION_DEFAULT;

        return $this;
    }

    /**
     * Renders table to output.
     *
     * Example:
     *
     *     +---------------+-----------------------+------------------+
     *     | ISBN          | Title                 | Author           |
     *     +---------------+-----------------------+------------------+
     *     | 99921-58-10-7 | Divine Comedy         | Dante Alighieri  |
     *     | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     *     | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
     *     +---------------+-----------------------+------------------+
     */
    public function render(): void
    {
        $divider = new TableSeparator();
        $isCellWithColspan = static fn ($cell) => $cell instanceof TableCell && $cell->getColspan() >= 2;

        $horizontal = self::DISPLAY_ORIENTATION_HORIZONTAL === $this->displayOrientation;
        $vertical = self::DISPLAY_ORIENTATION_VERTICAL === $this->displayOrientation;

        $rows = [];
        if ($horizontal) {
            foreach ($this->headers[0] ?? [] as $i => $header) {
                $rows[$i] = [$header];
                foreach ($this->rows as $row) {
                    if ($row instanceof TableSeparator) {
                        continue;
                    }
                    if (isset($row[$i])) {
                        $rows[$i][] = $row[$i];
                    } elseif ($isCellWithColspan($rows[$i][0])) {
                        // Noop, there is a "title"
                    } else {
                        $rows[$i][] = null;
                    }
                }
            }
        } elseif ($vertical) {
            $formatter = $this->output->getFormatter();
            $maxHeaderLength = array_reduce($this->headers[0] ?? [], static fn ($max, $header) => max($max, Helper::width(Helper::removeDecoration($formatter, $header))), 0);

            foreach ($this->rows as $row) {
                if ($row instanceof TableSeparator) {
                    continue;
                }

                if ($rows) {
                    $rows[] = [$divider];
                }

                $containsColspan = false;
                foreach ($row as $cell) {
                    if ($containsColspan = $isCellWithColspan($cell)) {
                        break;
                    }
                }

                $headers = $this->headers[0] ?? [];
                $maxRows = max(\count($headers), \count($row));
                for ($i = 0; $i < $maxRows; ++$i) {
                    $cell = (string) ($row[$i] ?? '');

                    $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n";
                    $parts = explode($eol, $cell);
                    foreach ($parts as $idx => $part) {
                        if ($headers && !$containsColspan) {
                            if (0 === $idx) {
                                $rows[] = [\sprintf(
                                    '<comment>%s%s</>: %s',
                                    str_repeat(' ', $maxHeaderLength - Helper::width(Helper::removeDecoration($formatter, $headers[$i] ?? ''))),
                                    $headers[$i] ?? '',
                                    $part
                                )];
                            } else {
                                $rows[] = [\sprintf(
                                    '%s  %s',
                                    str_pad('', $maxHeaderLength, ' ', \STR_PAD_LEFT),
                                    $part
                                )];
                            }
                        } elseif ('' !== $cell) {
                            $rows[] = [$part];
                        }
                    }
                }
            }
        } else {
            $rows = array_merge($this->headers, [$divider], $this->rows);
        }

        $this->calculateNumberOfColumns($rows);

        $rowGroups = $this->buildTableRows($rows);
        $this->calculateColumnsWidth($rowGroups);

        $isHeader = !$horizontal;
        $isFirstRow = $horizontal;
        $hasTitle = (bool) $this->headerTitle;

        foreach ($rowGroups as $rowGroup) {
            $isHeaderSeparatorRendered = false;

            foreach ($rowGroup as $row) {
                if ($divider === $row) {
                    $isHeader = false;
                    $isFirstRow = true;

                    continue;
                }

                if ($row instanceof TableSeparator) {
                    $this->renderRowSeparator();

                    continue;
                }

                if (!$row) {
                    continue;
                }

                if ($isHeader && !$isHeaderSeparatorRendered && $this->style->displayOutsideBorder()) {
                    $this->renderRowSeparator(
                        self::SEPARATOR_TOP,
                        $hasTitle ? $this->headerTitle : null,
                        $hasTitle ? $this->style->getHeaderTitleFormat() : null
                    );
                    $hasTitle = false;
                    $isHeaderSeparatorRendered = true;
                }

                if ($isFirstRow) {
                    $this->renderRowSeparator(
                        $horizontal ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM,
                        $hasTitle ? $this->headerTitle : null,
                        $hasTitle ? $this->style->getHeaderTitleFormat() : null
                    );
                    $isFirstRow = false;
                    $hasTitle = false;
                }

                if ($vertical) {
                    $isHeader = false;
                    $isFirstRow = false;
                }

                if ($horizontal) {
                    $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat());
                } else {
                    $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
                }
            }
        }

        if ($this->getStyle()->displayOutsideBorder()) {
            $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat());
        }

        $this->cleanup();
        $this->rendered = true;
    }

    /**
     * Renders horizontal header separator.
     *
     * Example:
     *
     *     +-----+-----------+-------+
     */
    private function renderRowSeparator(int $type = self::SEPARATOR_MID, ?string $title = null, ?string $titleFormat = null): void
    {
        if (!$count = $this->numberOfColumns) {
            return;
        }

        $borders = $this->style->getBorderChars();
        if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) {
            return;
        }

        $crossings = $this->style->getCrossingChars();
        if (self::SEPARATOR_MID === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]];
        } elseif (self::SEPARATOR_TOP === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]];
        } elseif (self::SEPARATOR_TOP_BOTTOM === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]];
        } else {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]];
        }

        $markup = $leftChar;
        for ($column = 0; $column < $count; ++$column) {
            $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]);
            $markup .= $column === $count - 1 ? $rightChar : $midChar;
        }

        if (null !== $title) {
            $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = \sprintf($titleFormat, $title)));
            $markupLength = Helper::width($markup);
            if ($titleLength > $limit = $markupLength - 4) {
                $titleLength = $limit;
                $formatLength = Helper::width(Helper::removeDecoration($formatter, \sprintf($titleFormat, '')));
                $formattedTitle = \sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...');
            }

            $titleStart = intdiv($markupLength - $titleLength, 2);
            if (false === mb_detect_encoding($markup, null, true)) {
                $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength);
            } else {
                $markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength);
            }
        }

        $this->output->writeln(\sprintf($this->style->getBorderFormat(), $markup));
    }

    /**
     * Renders vertical column separator.
     */
    private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string
    {
        $borders = $this->style->getBorderChars();

        return \sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]);
    }

    /**
     * Renders table row.
     *
     * Example:
     *
     *     | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     */
    private function renderRow(array $row, string $cellFormat, ?string $firstCellFormat = null): void
    {
        $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE);
        $columns = $this->getRowColumns($row);
        $last = \count($columns) - 1;
        foreach ($columns as $i => $column) {
            if ($firstCellFormat && 0 === $i) {
                $rowContent .= $this->renderCell($row, $column, $firstCellFormat);
            } else {
                $rowContent .= $this->renderCell($row, $column, $cellFormat);
            }
            $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE);
        }
        $this->output->writeln($rowContent);
    }

    /**
     * Renders table cell with padding.
     */
    private function renderCell(array $row, int $column, string $cellFormat): string
    {
        $cell = $row[$column] ?? '';
        $width = $this->effectiveColumnWidths[$column];
        if ($cell instanceof TableCell && $cell->getColspan() > 1) {
            // add the width of the following columns(numbers of colspan).
            foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
                $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
            }
        }

        // str_pad won't work properly with multi-byte strings, we need to fix the padding
        $width += \strlen($cell) - Helper::width($cell) - substr_count($cell, "\0");
        $style = $this->getColumnStyle($column);

        if ($cell instanceof TableSeparator) {
            return \sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width));
        }

        $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell));
        $content = \sprintf($style->getCellRowContentFormat(), $cell);

        $padType = $style->getPadType();
        if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
            $isNotStyledByTag = !preg_match('/^<(\w+|(\w+=[\w,]+;?)*)>.+<\/(\w+|(\w+=\w+;?)*)?>$/', $cell);
            if ($isNotStyledByTag) {
                $cellFormat = $cell->getStyle()->getCellFormat();
                if (!\is_string($cellFormat)) {
                    $tag = http_build_query($cell->getStyle()->getTagOptions(), '', ';');
                    $cellFormat = '<'.$tag.'>%s</>';
                }

                if (str_contains($content, '</>')) {
                    $content = str_replace('</>', '', $content);
                    $width -= 3;
                }
                if (str_contains($content, '<fg=default;bg=default>')) {
                    $content = str_replace('<fg=default;bg=default>', '', $content);
                    $width -= \strlen('<fg=default;bg=default>');
                }
            }

            $padType = $cell->getStyle()->getPadByAlign();
        }

        return \sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $padType));
    }

    /**
     * Calculate number of columns for this table.
     */
    private function calculateNumberOfColumns(array $rows): void
    {
        $columns = [0];
        foreach ($rows as $row) {
            if ($row instanceof TableSeparator) {
                continue;
            }

            $columns[] = $this->getNumberOfColumns($row);
        }

        $this->numberOfColumns = max($columns);
    }

    private function buildTableRows(array $rows): TableRows
    {
        /** @var WrappableOutputFormatterInterface $formatter */
        $formatter = $this->output->getFormatter();
        $unmergedRows = [];
        for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
            $rows = $this->fillNextRows($rows, $rowKey);

            // Remove any new line breaks and replace it with a new line
            foreach ($rows[$rowKey] as $column => $cell) {
                $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1;

                $minWrappedWidth = 0;
                $widthApplied = [];
                $lengthColumnBorder = $this->getColumnSeparatorWidth() + Helper::width($this->style->getCellRowContentFormat()) - 2;
                for ($i = $column; $i < ($column + $colspan); ++$i) {
                    if (isset($this->columnMaxWidths[$i])) {
                        $minWrappedWidth += $this->columnMaxWidths[$i];
                        $widthApplied[] = ['type' => 'max', 'column' => $i];
                    } elseif (($this->columnWidths[$i] ?? 0) > 0 && $colspan > 1) {
                        $minWrappedWidth += $this->columnWidths[$i];
                        $widthApplied[] = ['type' => 'min', 'column' => $i];
                    }
                }
                if (1 === \count($widthApplied)) {
                    if ($colspan > 1) {
                        $minWrappedWidth *= $colspan;  // previous logic
                    }
                } elseif (\count($widthApplied) > 1) {
                    $minWrappedWidth += (\count($widthApplied) - 1) * $lengthColumnBorder;
                }

                $cellWidth = Helper::width(Helper::removeDecoration($formatter, $cell));
                if ($minWrappedWidth && $cellWidth > $minWrappedWidth) {
                    $cell = $formatter->formatAndWrap($cell, $minWrappedWidth);
                }
                // update minimal columnWidths for spanned columns
                if ($colspan > 1 && $minWrappedWidth > 0) {
                    $columnsMinWidthProcessed = [];
                    $cellWidth = min($cellWidth, $minWrappedWidth);
                    foreach ($widthApplied as $item) {
                        if ('max' === $item['type'] && $cellWidth >= $this->columnMaxWidths[$item['column']]) {
                            $minWidthColumn = $this->columnMaxWidths[$item['column']];
                            $this->columnWidths[$item['column']] = $minWidthColumn;
                            $columnsMinWidthProcessed[$item['column']] = true;
                            $cellWidth -= $minWidthColumn + $lengthColumnBorder;
                        }
                    }
                    for ($i = $column; $i < ($column + $colspan); ++$i) {
                        if (isset($columnsMinWidthProcessed[$i])) {
                            continue;
                        }
                        $this->columnWidths[$i] = $cellWidth + $lengthColumnBorder;
                    }
                }
                if (!str_contains($cell ?? '', "\n")) {
                    continue;
                }
                $eol = str_contains($cell ?? '', "\r\n") ? "\r\n" : "\n";
                $escaped = implode($eol, array_map(OutputFormatter::escapeTrailingBackslash(...), explode($eol, $cell)));
                $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped;
                $lines = explode($eol, str_replace($eol, '<fg=default;bg=default></>'.$eol, $cell));
                foreach ($lines as $lineKey => $line) {
                    if ($colspan > 1) {
                        $line = new TableCell($line, ['colspan' => $colspan]);
                    }
                    if (0 === $lineKey) {
                        $rows[$rowKey][$column] = $line;
                    } else {
                        if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) {
                            $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey);
                        }
                        $unmergedRows[$rowKey][$lineKey][$column] = $line;
                    }
                }
            }
        }

        return new TableRows(function () use ($rows, $unmergedRows): \Traversable {
            foreach ($rows as $rowKey => $row) {
                $rowGroup = [$row instanceof TableSeparator ? $row : $this->fillCells($row)];

                if (isset($unmergedRows[$rowKey])) {
                    foreach ($unmergedRows[$rowKey] as $row) {
                        $rowGroup[] = $row instanceof TableSeparator ? $row : $this->fillCells($row);
                    }
                }
                yield $rowGroup;
            }
        });
    }

    private function calculateRowCount(): int
    {
        $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows))));

        if ($this->headers) {
            ++$numberOfRows; // Add row for header separator
        }

        if ($this->rows) {
            ++$numberOfRows; // Add row for footer separator
        }

        return $numberOfRows;
    }

    /**
     * fill rows that contains rowspan > 1.
     *
     * @throws InvalidArgumentException
     */
    private function fillNextRows(array $rows, int $line): array
    {
        $unmergedRows = [];
        foreach ($rows[$line] as $column => $cell) {
            if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !$cell instanceof \Stringable) {
                throw new InvalidArgumentException(\sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', get_debug_type($cell)));
            }
            if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
                $nbLines = $cell->getRowspan() - 1;
                $lines = [$cell];
                if (str_contains($cell, "\n")) {
                    $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n";
                    $lines = explode($eol, str_replace($eol, '<fg=default;bg=default>'.$eol.'</>', $cell));
                    $nbLines = \count($lines) > $nbLines ? substr_count($cell, $eol) : $nbLines;

                    $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
                    unset($lines[0]);
                }

                // create a two dimensional array (rowspan x colspan)
                $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows);
                foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
                    $value = $lines[$unmergedRowKey - $line] ?? '';
                    $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
                    if ($nbLines === $unmergedRowKey - $line) {
                        break;
                    }
                }
            }
        }

        foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
            // we need to know if $unmergedRow will be merged or inserted into $rows
            if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRow) <= $this->numberOfColumns)) {
                foreach ($unmergedRow as $cellKey => $cell) {
                    // insert cell into row at cellKey position
                    array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]);
                }
            } else {
                $row = $this->copyRow($rows, $unmergedRowKey - 1);
                foreach ($unmergedRow as $column => $cell) {
                    if ($cell) {
                        $row[$column] = $cell;
                    }
                }
                array_splice($rows, $unmergedRowKey, 0, [$row]);
            }
        }

        return $rows;
    }

    /**
     * fill cells for a row that contains colspan > 1.
     */
    private function fillCells(iterable $row): iterable
    {
        $newRow = [];

        foreach ($row as $column => $cell) {
            $newRow[] = $cell;
            if ($cell instanceof TableCell && $cell->getColspan() > 1) {
                foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
                    // insert empty value at column position
                    $newRow[] = '';
                }
            }
        }

        return $newRow ?: $row;
    }

    private function copyRow(array $rows, int $line): array
    {
        $row = $rows[$line];
        foreach ($row as $cellKey => $cellValue) {
            $row[$cellKey] = '';
            if ($cellValue instanceof TableCell) {
                $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]);
            }
        }

        return $row;
    }

    /**
     * Gets number of columns by row.
     */
    private function getNumberOfColumns(array $row): int
    {
        $columns = \count($row);
        foreach ($row as $column) {
            $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
        }

        return $columns;
    }

    /**
     * Gets list of columns for the given row.
     */
    private function getRowColumns(array $row): array
    {
        $columns = range(0, $this->numberOfColumns - 1);
        foreach ($row as $cellKey => $cell) {
            if ($cell instanceof TableCell && $cell->getColspan() > 1) {
                // exclude grouped columns.
                $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
            }
        }

        return $columns;
    }

    /**
     * Calculates columns widths.
     */
    private function calculateColumnsWidth(iterable $groups): void
    {
        for ($column = 0; $column < $this->numberOfColumns; ++$column) {
            $lengths = [];
            foreach ($groups as $group) {
                foreach ($group as $row) {
                    if ($row instanceof TableSeparator) {
                        continue;
                    }

                    foreach ($row as $i => $cell) {
                        if ($cell instanceof TableCell) {
                            $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
                            $textLength = Helper::width($textContent);
                            if ($textLength > 0) {
                                $contentColumns = mb_str_split($textContent, ceil($textLength / $cell->getColspan()));
                                foreach ($contentColumns as $position => $content) {
                                    $row[$i + $position] = $content;
                                }
                            }
                        }
                    }

                    $lengths[] = $this->getCellWidth($row, $column);
                }
            }

            $this->effectiveColumnWidths[$column] = max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2;
        }
    }

    private function getColumnSeparatorWidth(): int
    {
        return Helper::width(\sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
    }

    private function getCellWidth(array $row, int $column): int
    {
        $cellWidth = 0;

        if (isset($row[$column])) {
            $cell = $row[$column];
            $cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell));
        }

        $columnWidth = $this->columnWidths[$column] ?? 0;
        $cellWidth = max($cellWidth, $columnWidth);

        return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth;
    }

    /**
     * Called after rendering to cleanup cache data.
     */
    private function cleanup(): void
    {
        $this->effectiveColumnWidths = [];
        unset($this->numberOfColumns);
    }

    /**
     * @return array<string, TableStyle>
     */
    private static function initStyles(): array
    {
        $markdown = new TableStyle();
        $markdown
            ->setDefaultCrossingChar('|')
            ->setDisplayOutsideBorder(false)
        ;

        $borderless = new TableStyle();
        $borderless
            ->setHorizontalBorderChars('=')
            ->setVerticalBorderChars(' ')
            ->setDefaultCrossingChar(' ')
        ;

        $compact = new TableStyle();
        $compact
            ->setHorizontalBorderChars('')
            ->setVerticalBorderChars('')
            ->setDefaultCrossingChar('')
            ->setCellRowContentFormat('%s ')
        ;

        $styleGuide = new TableStyle();
        $styleGuide
            ->setHorizontalBorderChars('-')
            ->setVerticalBorderChars(' ')
            ->setDefaultCrossingChar(' ')
            ->setCellHeaderFormat('%s')
        ;

        $box = (new TableStyle())
            ->setHorizontalBorderChars('─')
            ->setVerticalBorderChars('│')
            ->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├')
        ;

        $boxDouble = (new TableStyle())
            ->setHorizontalBorderChars('═', '─')
            ->setVerticalBorderChars('║', '│')
            ->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣')
        ;

        return [
            'default' => new TableStyle(),
            'markdown' => $markdown,
            'borderless' => $borderless,
            'compact' => $compact,
            'symfony-style-guide' => $styleGuide,
            'box' => $box,
            'box-double' => $boxDouble,
        ];
    }

    private function resolveStyle(TableStyle|string $name): TableStyle
    {
        if ($name instanceof TableStyle) {
            return $name;
        }

        return self::$styles[$name] ?? throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;

/**
 * The ProcessHelper class provides helpers to run external processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ProcessHelper extends Helper
{
    /**
     * Runs an external process.
     *
     * @param array|Process $cmd      An instance of Process or an array of the command and arguments
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     */
    public function run(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process
    {
        if (!class_exists(Process::class)) {
            throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".');
        }

        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        $formatter = $this->getHelperSet()->get('debug_formatter');

        if ($cmd instanceof Process) {
            $cmd = [$cmd];
        }

        if (\is_string($cmd[0] ?? null)) {
            $process = new Process($cmd);
            $cmd = [];
        } elseif (($cmd[0] ?? null) instanceof Process) {
            $process = $cmd[0];
            unset($cmd[0]);
        } else {
            throw new \InvalidArgumentException(\sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__));
        }

        if ($verbosity <= $output->getVerbosity()) {
            $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
        }

        if ($output->isDebug()) {
            $callback = $this->wrapCallback($output, $process, $callback);
        }

        $process->run($callback, $cmd);

        if ($verbosity <= $output->getVerbosity()) {
            $message = $process->isSuccessful() ? 'Command ran successfully' : \sprintf('%s Command did not run successfully', $process->getExitCode());
            $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
        }

        if (!$process->isSuccessful() && null !== $error) {
            $output->writeln(\sprintf('<error>%s</error>', $this->escapeString($error)));
        }

        return $process;
    }

    /**
     * Runs the process.
     *
     * This is identical to run() except that an exception is thrown if the process
     * exits with a non-zero exit code.
     *
     * @param array|Process $cmd      An instance of Process or a command to run
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @throws ProcessFailedException
     *
     * @see run()
     */
    public function mustRun(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process
    {
        $process = $this->run($output, $cmd, $error, $callback, $verbosity);

        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }

        return $process;
    }

    /**
     * Wraps a Process callback to add debugging output.
     */
    public function wrapCallback(OutputInterface $output, Process $process, ?callable $callback = null): callable
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }

        $formatter = $this->getHelperSet()->get('debug_formatter');

        return function ($type, $buffer) use ($output, $process, $callback, $formatter) {
            $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type));

            if (null !== $callback) {
                $callback($type, $buffer);
            }
        };
    }

    private function escapeString(string $str): string
    {
        return str_replace('<', '\\<', $str);
    }

    public function getName(): string
    {
        return 'process';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Input\InputAwareInterface;
use Symfony\Component\Console\Input\InputInterface;

/**
 * An implementation of InputAwareInterface for Helpers.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
abstract class InputAwareHelper extends Helper implements InputAwareInterface
{
    protected InputInterface $input;

    public function setInput(InputInterface $input): void
    {
        $this->input = $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Grégoire Pineau <lyrixx@lyrixx.info>
 */
class SingleCommandApplication extends Command
{
    private string $version = 'UNKNOWN';
    private bool $autoExit = true;
    private bool $running = false;

    /**
     * @return $this
     */
    public function setVersion(string $version): static
    {
        $this->version = $version;

        return $this;
    }

    /**
     * @final
     *
     * @return $this
     */
    public function setAutoExit(bool $autoExit): static
    {
        $this->autoExit = $autoExit;

        return $this;
    }

    public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
    {
        if ($this->running) {
            return parent::run($input, $output);
        }

        // We use the command name as the application name
        $application = new Application($this->getName() ?: 'UNKNOWN', $this->version);
        $application->setAutoExit($this->autoExit);
        // Fix the usage of the command displayed with "--help"
        $this->setName($_SERVER['argv'][0]);
        $application->addCommand($this);
        $application->setDefaultCommand($this->getName(), true);

        $this->running = true;
        try {
            $ret = $application->run($input, $output);
        } finally {
            $this->running = false;
        }

        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Allows to manipulate the exit code of a command after its execution.
 *
 * @author Francesco Levorato <git@flevour.net>
 * @author Jules Pietri <jules@heahprod.com>
 */
final class ConsoleTerminateEvent extends ConsoleEvent
{
    public function __construct(
        Command $command,
        InputInterface $input,
        OutputInterface $output,
        private int $exitCode,
        private readonly ?int $interruptingSignal = null,
    ) {
        parent::__construct($command, $input, $output);
    }

    public function setExitCode(int $exitCode): void
    {
        $this->exitCode = $exitCode;
    }

    public function getExitCode(): int
    {
        return $this->exitCode;
    }

    public function getInterruptingSignal(): ?int
    {
        return $this->interruptingSignal;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

/**
 * Allows to do things before the command is executed, like skipping the command or executing code before the command is
 * going to be executed.
 *
 * Changing the input arguments will have no effect.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class ConsoleCommandEvent extends ConsoleEvent
{
    /**
     * The return code for skipped commands, this will also be passed into the terminate event.
     */
    public const RETURN_CODE_DISABLED = 113;

    /**
     * Indicates if the command should be run or skipped.
     */
    private bool $commandShouldRun = true;

    /**
     * Disables the command, so it won't be run.
     */
    public function disableCommand(): bool
    {
        return $this->commandShouldRun = false;
    }

    public function enableCommand(): bool
    {
        return $this->commandShouldRun = true;
    }

    /**
     * Returns true if the command is runnable, false otherwise.
     */
    public function commandShouldRun(): bool
    {
        return $this->commandShouldRun;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Contracts\EventDispatcher\Event;

/**
 * Allows to inspect input and output of a command.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleEvent extends Event
{
    public function __construct(
        protected ?Command $command,
        private InputInterface $input,
        private OutputInterface $output,
    ) {
    }

    /**
     * Gets the command that is executed.
     */
    public function getCommand(): ?Command
    {
        return $this->command;
    }

    /**
     * Gets the input instance.
     */
    public function getInput(): InputInterface
    {
        return $this->input;
    }

    /**
     * Gets the output instance.
     */
    public function getOutput(): OutputInterface
    {
        return $this->output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

final class ConsoleAlarmEvent extends ConsoleEvent
{
    public function __construct(
        Command $command,
        InputInterface $input,
        OutputInterface $output,
        private int|false $exitCode = 0,
    ) {
        parent::__construct($command, $input, $output);
    }

    public function setExitCode(int $exitCode): void
    {
        if ($exitCode < 0 || $exitCode > 255) {
            throw new \InvalidArgumentException('Exit code must be between 0 and 255.');
        }

        $this->exitCode = $exitCode;
    }

    public function abortExit(): void
    {
        $this->exitCode = false;
    }

    public function getExitCode(): int|false
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author marie <marie@users.noreply.github.com>
 */
final class ConsoleSignalEvent extends ConsoleEvent
{
    public function __construct(
        Command $command,
        InputInterface $input,
        OutputInterface $output,
        private int $handlingSignal,
        private int|false $exitCode = 0,
    ) {
        parent::__construct($command, $input, $output);
    }

    public function getHandlingSignal(): int
    {
        return $this->handlingSignal;
    }

    public function setExitCode(int $exitCode): void
    {
        if ($exitCode < 0 || $exitCode > 255) {
            throw new \InvalidArgumentException('Exit code must be between 0 and 255.');
        }

        $this->exitCode = $exitCode;
    }

    public function abortExit(): void
    {
        $this->exitCode = false;
    }

    public function getExitCode(): int|false
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Allows to handle throwables thrown while running a command.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class ConsoleErrorEvent extends ConsoleEvent
{
    private int $exitCode;

    public function __construct(
        InputInterface $input,
        OutputInterface $output,
        private \Throwable $error,
        ?Command $command = null,
    ) {
        parent::__construct($command, $input, $output);
    }

    public function getError(): \Throwable
    {
        return $this->error;
    }

    public function setError(\Throwable $error): void
    {
        $this->error = $error;
    }

    public function setExitCode(int $exitCode): void
    {
        $this->exitCode = $exitCode;

        $r = new \ReflectionProperty($this->error, 'code');
        $r->setValue($this->error, $this->exitCode);
    }

    public function getExitCode(): int
    {
        return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\EventListener;

use Psr\Log\LoggerInterface;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * @author James Halsall <james.t.halsall@googlemail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ErrorListener implements EventSubscriberInterface
{
    public function __construct(
        private ?LoggerInterface $logger = null,
    ) {
    }

    public function onConsoleError(ConsoleErrorEvent $event): void
    {
        if (null === $this->logger) {
            return;
        }

        $error = $event->getError();

        if (!$inputString = self::getInputString($event)) {
            $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]);

            return;
        }

        $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]);
    }

    public function onConsoleTerminate(ConsoleTerminateEvent $event): void
    {
        if (null === $this->logger) {
            return;
        }

        $exitCode = $event->getExitCode();

        if (0 === $exitCode) {
            return;
        }

        if (!$inputString = self::getInputString($event)) {
            $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]);

            return;
        }

        $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]);
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ConsoleEvents::ERROR => ['onConsoleError', -128],
            ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128],
        ];
    }

    private static function getInputString(ConsoleEvent $event): string
    {
        $commandName = $event->getCommand()?->getName();
        $inputString = (string) $event->getInput();

        if ($commandName) {
            return str_replace(["'$commandName'", "\"$commandName\""], $commandName, $inputString);
        }

        return $inputString;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Question;

/**
 * Represents a yes/no question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfirmationQuestion extends Question
{
    /**
     * @param string $question        The question to ask to the user
     * @param bool   $default         The default answer to return, true or false
     * @param string $trueAnswerRegex A regex to match the "yes" answer
     */
    public function __construct(
        string $question,
        bool $default = true,
        private string $trueAnswerRegex = '/^y/i',
    ) {
        parent::__construct($question, $default);

        $this->setNormalizer($this->getDefaultNormalizer());
    }

    /**
     * Returns the default answer normalizer.
     */
    private function getDefaultNormalizer(): callable
    {
        $default = $this->getDefault();
        $regex = $this->trueAnswerRegex;

        return static function ($answer) use ($default, $regex) {
            if (\is_bool($answer)) {
                return $answer;
            }

            $answerIsTrue = (bool) preg_match($regex, $answer);
            if (false === $default) {
                return $answer && $answerIsTrue;
            }

            return '' === $answer || $answerIsTrue;
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Question;

use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;

/**
 * Represents a Question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Question
{
    private ?int $attempts = null;
    private bool $hidden = false;
    private bool $hiddenFallback = true;
    /**
     * @var (\Closure(string):string[])|null
     */
    private ?\Closure $autocompleterCallback = null;
    /**
     * @var (\Closure(mixed):mixed)|null
     */
    private ?\Closure $validator = null;
    /**
     * @var (\Closure(mixed):mixed)|null
     */
    private ?\Closure $normalizer = null;
    private bool $trimmable = true;
    private bool $multiline = false;
    private ?int $timeout = null;

    /**
     * @param string                     $question The question to ask to the user
     * @param string|bool|int|float|null $default  The default answer to return if the user enters nothing
     */
    public function __construct(
        private string $question,
        private string|bool|int|float|null $default = null,
    ) {
    }

    /**
     * Returns the question.
     */
    public function getQuestion(): string
    {
        return $this->question;
    }

    /**
     * Returns the default answer.
     */
    public function getDefault(): string|bool|int|float|null
    {
        return $this->default;
    }

    /**
     * Returns whether the user response accepts newline characters.
     */
    public function isMultiline(): bool
    {
        return $this->multiline;
    }

    /**
     * Sets whether the user response should accept newline characters.
     *
     * @return $this
     */
    public function setMultiline(bool $multiline): static
    {
        $this->multiline = $multiline;

        return $this;
    }

    /**
     * Returns the timeout in seconds.
     */
    public function getTimeout(): ?int
    {
        return $this->timeout;
    }

    /**
     * Sets the maximum time the user has to answer the question.
     * If the user does not answer within this time, an exception will be thrown.
     *
     * @return $this
     */
    public function setTimeout(?int $seconds): static
    {
        $this->timeout = $seconds;

        return $this;
    }

    /**
     * Returns whether the user response must be hidden.
     */
    public function isHidden(): bool
    {
        return $this->hidden;
    }

    /**
     * Sets whether the user response must be hidden or not.
     *
     * @return $this
     *
     * @throws LogicException In case the autocompleter is also used
     */
    public function setHidden(bool $hidden): static
    {
        if ($this->autocompleterCallback) {
            throw new LogicException('A hidden question cannot use the autocompleter.');
        }

        $this->hidden = $hidden;

        return $this;
    }

    /**
     * In case the response cannot be hidden, whether to fallback on non-hidden question or not.
     */
    public function isHiddenFallback(): bool
    {
        return $this->hiddenFallback;
    }

    /**
     * Sets whether to fallback on non-hidden question if the response cannot be hidden.
     *
     * @return $this
     */
    public function setHiddenFallback(bool $fallback): static
    {
        $this->hiddenFallback = $fallback;

        return $this;
    }

    /**
     * Gets values for the autocompleter.
     */
    public function getAutocompleterValues(): ?iterable
    {
        $callback = $this->getAutocompleterCallback();

        return $callback ? $callback('') : null;
    }

    /**
     * Sets values for the autocompleter.
     *
     * @return $this
     *
     * @throws LogicException
     */
    public function setAutocompleterValues(?iterable $values): static
    {
        if (\is_array($values)) {
            $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);

            $callback = static fn () => $values;
        } elseif ($values instanceof \Traversable) {
            $callback = static function () use ($values) {
                static $valueCache;

                return $valueCache ??= iterator_to_array($values, false);
            };
        } else {
            $callback = null;
        }

        return $this->setAutocompleterCallback($callback);
    }

    /**
     * Gets the callback function used for the autocompleter.
     *
     * @return (callable(string):string[])|null
     */
    public function getAutocompleterCallback(): ?callable
    {
        return $this->autocompleterCallback;
    }

    /**
     * Sets the callback function used for the autocompleter.
     *
     * The callback is passed the user input as argument and should return an iterable of corresponding suggestions.
     *
     * @param (callable(string):string[])|null $callback
     *
     * @return $this
     */
    public function setAutocompleterCallback(?callable $callback): static
    {
        if ($this->hidden && null !== $callback) {
            throw new LogicException('A hidden question cannot use the autocompleter.');
        }

        $this->autocompleterCallback = null === $callback ? null : $callback(...);

        return $this;
    }

    /**
     * Sets a validator for the question.
     *
     * @param (callable(mixed):mixed)|null $validator
     *
     * @return $this
     */
    public function setValidator(?callable $validator): static
    {
        $this->validator = null === $validator ? null : $validator(...);

        return $this;
    }

    /**
     * Gets the validator for the question.
     *
     * @return (callable(mixed):mixed)|null
     */
    public function getValidator(): ?callable
    {
        return $this->validator;
    }

    /**
     * Sets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     *
     * @return $this
     *
     * @throws InvalidArgumentException in case the number of attempts is invalid
     */
    public function setMaxAttempts(?int $attempts): static
    {
        if (null !== $attempts && $attempts < 1) {
            throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
        }

        $this->attempts = $attempts;

        return $this;
    }

    /**
     * Gets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     */
    public function getMaxAttempts(): ?int
    {
        return $this->attempts;
    }

    /**
     * Sets a normalizer for the response.
     *
     * @param callable(mixed):mixed $normalizer
     *
     * @return $this
     */
    public function setNormalizer(callable $normalizer): static
    {
        $this->normalizer = $normalizer(...);

        return $this;
    }

    /**
     * Gets the normalizer for the response.
     *
     * @return (callable(mixed):mixed)|null
     */
    public function getNormalizer(): ?callable
    {
        return $this->normalizer;
    }

    protected function isAssoc(array $array): bool
    {
        return (bool) \count(array_filter(array_keys($array), 'is_string'));
    }

    public function isTrimmable(): bool
    {
        return $this->trimmable;
    }

    /**
     * @return $this
     */
    public function setTrimmable(bool $trimmable): static
    {
        $this->trimmable = $trimmable;

        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Question;

use Symfony\Component\Console\Exception\InvalidArgumentException;

/**
 * Represents a choice question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChoiceQuestion extends Question
{
    private bool $multiselect = false;
    private string $prompt = ' > ';
    private string $errorMessage = 'Value "%s" is invalid';

    /**
     * @param string                                   $question The question to ask to the user
     * @param array<string|bool|int|float|\Stringable> $choices  The list of available choices
     * @param string|bool|int|float|null               $default  The default answer to return
     */
    public function __construct(
        string $question,
        private array $choices,
        string|bool|int|float|null $default = null,
    ) {
        if (!$choices) {
            throw new \LogicException('Choice question must have at least 1 choice available.');
        }

        parent::__construct($question, $default);

        $this->setValidator($this->getDefaultValidator());
        $this->setAutocompleterValues($choices);
    }

    /**
     * @return array<string|bool|int|float|\Stringable>
     */
    public function getChoices(): array
    {
        return $this->choices;
    }

    /**
     * Sets multiselect option.
     *
     * When multiselect is set to true, multiple choices can be answered.
     *
     * @return $this
     */
    public function setMultiselect(bool $multiselect): static
    {
        $this->multiselect = $multiselect;
        $this->setValidator($this->getDefaultValidator());

        return $this;
    }

    /**
     * Returns whether the choices are multiselect.
     */
    public function isMultiselect(): bool
    {
        return $this->multiselect;
    }

    /**
     * Gets the prompt for choices.
     */
    public function getPrompt(): string
    {
        return $this->prompt;
    }

    /**
     * Sets the prompt for choices.
     *
     * @return $this
     */
    public function setPrompt(string $prompt): static
    {
        $this->prompt = $prompt;

        return $this;
    }

    /**
     * Sets the error message for invalid values.
     *
     * The error message has a string placeholder (%s) for the invalid value.
     *
     * @return $this
     */
    public function setErrorMessage(string $errorMessage): static
    {
        $this->errorMessage = $errorMessage;
        $this->setValidator($this->getDefaultValidator());

        return $this;
    }

    private function getDefaultValidator(): callable
    {
        $choices = $this->choices;
        $errorMessage = $this->errorMessage;
        $multiselect = $this->multiselect;
        $isAssoc = $this->isAssoc($choices);

        return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
            if ($multiselect) {
                // Check for a separated comma values
                if (!preg_match('/^[^,]+(?:,[^,]+)*$/', (string) $selected, $matches)) {
                    throw new InvalidArgumentException(\sprintf($errorMessage, $selected));
                }

                $selectedChoices = explode(',', (string) $selected);
            } else {
                $selectedChoices = [$selected];
            }

            if ($this->isTrimmable()) {
                foreach ($selectedChoices as $k => $v) {
                    $selectedChoices[$k] = trim((string) $v);
                }
            }

            $multiselectChoices = [];
            foreach ($selectedChoices as $value) {
                $results = [];
                foreach ($choices as $key => $choice) {
                    if ($choice === $value) {
                        $results[] = $key;
                    }
                }

                if (\count($results) > 1) {
                    throw new InvalidArgumentException(\sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results)));
                }

                $result = array_search($value, $choices);

                if (!$isAssoc) {
                    if (false !== $result) {
                        $result = $choices[$result];
                    } elseif (isset($choices[$value])) {
                        $result = $choices[$value];
                    }
                } elseif (false === $result && isset($choices[$value])) {
                    $result = $value;
                }

                if (false === $result) {
                    throw new InvalidArgumentException(\sprintf($errorMessage, $value));
                }

                // For associative choices, consistently return the key as string:
                $multiselectChoices[] = $isAssoc ? (string) $result : $result;
            }

            if ($multiselect) {
                return $multiselectChoices;
            }

            return current($multiselectChoices);
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\String\UnicodeString;

class ReStructuredTextDescriptor extends Descriptor
{
    // <h1>
    private string $partChar = '=';
    // <h2>
    private string $chapterChar = '-';
    // <h3>
    private string $sectionChar = '~';
    // <h4>
    private string $subsectionChar = '.';
    // <h5>
    private string $subsubsectionChar = '^';
    // <h6>
    private string $paragraphsChar = '"';

    private array $visibleNamespaces = [];

    public function describe(OutputInterface $output, object $object, array $options = []): void
    {
        $decorated = $output->isDecorated();
        $output->setDecorated(false);

        parent::describe($output, $object, $options);

        $output->setDecorated($decorated);
    }

    /**
     * Override parent method to set $decorated = true.
     */
    protected function write(string $content, bool $decorated = true): void
    {
        parent::write($content, $decorated);
    }

    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->write(
            $argument->getName() ?: '<none>'."\n".str_repeat($this->paragraphsChar, Helper::width($argument->getName()))."\n\n"
                .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '')
                .'- **Is required**: '.($argument->isRequired() ? 'yes' : 'no')."\n"
                .'- **Is array**: '.($argument->isArray() ? 'yes' : 'no')."\n"
                .'- **Default**: ``'.str_replace("\n", '', var_export($argument->getDefault(), true)).'``'
        );
    }

    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $name = '\-\-'.$option->getName();
        if ($option->isNegatable()) {
            $name .= '|\-\-no-'.$option->getName();
        }
        if ($option->getShortcut()) {
            $name .= '|-'.str_replace('|', '|-', $option->getShortcut());
        }

        $optionDescription = $option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n\n", $option->getDescription())."\n\n" : '';
        $optionDescription = (new UnicodeString($optionDescription))->ascii();
        $this->write(
            $name."\n".str_repeat($this->paragraphsChar, Helper::width($name))."\n\n"
            .$optionDescription
            .'- **Accept value**: '.($option->acceptValue() ? 'yes' : 'no')."\n"
            .'- **Is value required**: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
            .'- **Is multiple**: '.($option->isArray() ? 'yes' : 'no')."\n"
            .'- **Is negatable**: '.($option->isNegatable() ? 'yes' : 'no')."\n"
            .'- **Default**: ``'.str_replace("\n", '', var_export($option->getDefault(), true)).'``'."\n"
        );
    }

    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        if ($showArguments = ((bool) $definition->getArguments())) {
            $this->write("Arguments\n".str_repeat($this->subsubsectionChar, 9));
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->describeInputArgument($argument);
            }
        }

        if ($nonDefaultOptions = $this->getNonDefaultOptions($definition)) {
            if ($showArguments) {
                $this->write("\n\n");
            }

            $this->write("Options\n".str_repeat($this->subsubsectionChar, 7)."\n\n");
            foreach ($nonDefaultOptions as $option) {
                $this->describeInputOption($option);
                $this->write("\n");
            }
        }
    }

    protected function describeCommand(Command $command, array $options = []): void
    {
        if ($options['short'] ?? false) {
            $this->write(
                '``'.$command->getName()."``\n"
                .str_repeat($this->subsectionChar, Helper::width($command->getName()))."\n\n"
                .($command->getDescription() ? $command->getDescription()."\n\n" : '')
                ."Usage\n".str_repeat($this->paragraphsChar, 5)."\n\n"
                .array_reduce($command->getAliases(), static fn ($carry, $usage) => $carry.'- ``'.$usage.'``'."\n")
            );

            return;
        }

        $command->mergeApplicationDefinition(false);

        foreach ($command->getAliases() as $alias) {
            $this->write('.. _'.$alias.":\n\n");
        }
        $this->write(
            $command->getName()."\n"
            .str_repeat($this->subsectionChar, Helper::width($command->getName()))."\n\n"
            .($command->getDescription() ? $command->getDescription()."\n\n" : '')
            ."Usage\n".str_repeat($this->subsubsectionChar, 5)."\n\n"
            .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), static fn ($carry, $usage) => $carry.'- ``'.$usage.'``'."\n")
        );

        if ($help = $command->getProcessedHelp()) {
            $this->write("\n");
            $this->write($help);
        }

        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->write("\n\n");
            $this->describeInputDefinition($definition);
        }
    }

    protected function describeApplication(Application $application, array $options = []): void
    {
        $description = new ApplicationDescription($application, $options['namespace'] ?? null);
        $title = $this->getApplicationTitle($application);

        $this->write($title."\n".str_repeat($this->partChar, Helper::width($title)));
        $this->createTableOfContents($description, $application);
        $this->describeCommands($application, $options);
    }

    private function getApplicationTitle(Application $application): string
    {
        if ('UNKNOWN' === $application->getName()) {
            return 'Console Tool';
        }
        if ('UNKNOWN' !== $application->getVersion()) {
            return \sprintf('%s %s', $application->getName(), $application->getVersion());
        }

        return $application->getName();
    }

    private function describeCommands($application, array $options): void
    {
        $title = 'Commands';
        $this->write("\n\n$title\n".str_repeat($this->chapterChar, Helper::width($title))."\n\n");
        foreach ($this->visibleNamespaces as $namespace) {
            if ('_global' === $namespace) {
                $commands = $application->all('');
                $this->write('Global'."\n".str_repeat($this->sectionChar, Helper::width('Global'))."\n\n");
            } else {
                $commands = $application->all($namespace);
                $this->write($namespace."\n".str_repeat($this->sectionChar, Helper::width($namespace))."\n\n");
            }

            foreach ($this->removeAliasesAndHiddenCommands($commands) as $command) {
                $this->describeCommand($command, $options);
                $this->write("\n\n");
            }
        }
    }

    private function createTableOfContents(ApplicationDescription $description, Application $application): void
    {
        $this->setVisibleNamespaces($description);
        $chapterTitle = 'Table of Contents';
        $this->write("\n\n$chapterTitle\n".str_repeat($this->chapterChar, Helper::width($chapterTitle))."\n\n");
        foreach ($this->visibleNamespaces as $namespace) {
            if ('_global' === $namespace) {
                $commands = $application->all('');
            } else {
                $commands = $application->all($namespace);
                $this->write("\n\n");
                $this->write($namespace."\n".str_repeat($this->sectionChar, Helper::width($namespace))."\n\n");
            }
            $commands = $this->removeAliasesAndHiddenCommands($commands);

            $this->write("\n\n");
            $this->write(implode("\n", array_map(static fn ($commandName) => \sprintf('- `%s`_', $commandName), array_keys($commands))));
        }
    }

    private function getNonDefaultOptions(InputDefinition $definition): array
    {
        $globalOptions = [
            'help',
            'silent',
            'quiet',
            'verbose',
            'version',
            'ansi',
            'no-interaction',
        ];
        $nonDefaultOptions = [];
        foreach ($definition->getOptions() as $option) {
            // Skip global options.
            if (!\in_array($option->getName(), $globalOptions, true)) {
                $nonDefaultOptions[] = $option;
            }
        }

        return $nonDefaultOptions;
    }

    private function setVisibleNamespaces(ApplicationDescription $description): void
    {
        $commands = $description->getCommands();
        foreach ($description->getNamespaces() as $namespace) {
            try {
                $namespaceCommands = $namespace['commands'];
                foreach ($namespaceCommands as $key => $commandName) {
                    if (!\array_key_exists($commandName, $commands)) {
                        // If the array key does not exist, then this is an alias.
                        unset($namespaceCommands[$key]);
                    } elseif ($commands[$commandName]->isHidden()) {
                        unset($namespaceCommands[$key]);
                    }
                }
                if (!$namespaceCommands) {
                    // If the namespace contained only aliases or hidden commands, skip the namespace.
                    continue;
                }
            } catch (\Exception) {
            }
            $this->visibleNamespaces[] = $namespace['id'];
        }
    }

    private function removeAliasesAndHiddenCommands(array $commands): array
    {
        foreach ($commands as $key => $command) {
            if ($command->isHidden() || \in_array($key, $command->getAliases(), true)) {
                unset($commands[$key]);
            }
        }
        unset($commands['completion']);

        return $commands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
abstract class Descriptor implements DescriptorInterface
{
    protected OutputInterface $output;

    public function describe(OutputInterface $output, object $object, array $options = []): void
    {
        $this->output = $output;

        match (true) {
            $object instanceof InputArgument => $this->describeInputArgument($object, $options),
            $object instanceof InputOption => $this->describeInputOption($object, $options),
            $object instanceof InputDefinition => $this->describeInputDefinition($object, $options),
            $object instanceof Command => $this->describeCommand($object, $options),
            $object instanceof Application => $this->describeApplication($object, $options),
            default => throw new InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', get_debug_type($object))),
        };
    }

    protected function write(string $content, bool $decorated = false): void
    {
        $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
    }

    /**
     * Describes an InputArgument instance.
     */
    abstract protected function describeInputArgument(InputArgument $argument, array $options = []): void;

    /**
     * Describes an InputOption instance.
     */
    abstract protected function describeInputOption(InputOption $option, array $options = []): void;

    /**
     * Describes an InputDefinition instance.
     */
    abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []): void;

    /**
     * Describes a Command instance.
     */
    abstract protected function describeCommand(Command $command, array $options = []): void;

    /**
     * Describes an Application instance.
     */
    abstract protected function describeApplication(Application $application, array $options = []): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * XML descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class XmlDescriptor extends Descriptor
{
    public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($definitionXML = $dom->createElement('definition'));

        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
        foreach ($definition->getArguments() as $argument) {
            $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
        }

        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
        foreach ($definition->getOptions() as $option) {
            $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
        }

        return $dom;
    }

    public function getCommandDocument(Command $command, bool $short = false): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($commandXML = $dom->createElement('command'));

        $commandXML->setAttribute('id', $command->getName());
        $commandXML->setAttribute('name', $command->getName());
        $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0);

        $commandXML->appendChild($usagesXML = $dom->createElement('usages'));

        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));

        if ($short) {
            foreach ($command->getAliases() as $usage) {
                $usagesXML->appendChild($dom->createElement('usage', $usage));
            }
        } else {
            $command->mergeApplicationDefinition(false);

            foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) {
                $usagesXML->appendChild($dom->createElement('usage', $usage));
            }

            $commandXML->appendChild($helpXML = $dom->createElement('help'));
            $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));

            $definitionXML = $this->getInputDefinitionDocument($command->getDefinition());
            $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
        }

        return $dom;
    }

    public function getApplicationDocument(Application $application, ?string $namespace = null, bool $short = false): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($rootXml = $dom->createElement('symfony'));

        if ('UNKNOWN' !== $application->getName()) {
            $rootXml->setAttribute('name', $application->getName());
            if ('UNKNOWN' !== $application->getVersion()) {
                $rootXml->setAttribute('version', $application->getVersion());
            }
        }

        $rootXml->appendChild($commandsXML = $dom->createElement('commands'));

        $description = new ApplicationDescription($application, $namespace, true);

        if ($namespace) {
            $commandsXML->setAttribute('namespace', $namespace);
        }

        foreach ($description->getCommands() as $command) {
            $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short));
        }

        if (!$namespace) {
            $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));

            foreach ($description->getNamespaces() as $namespaceDescription) {
                $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
                $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);

                foreach ($namespaceDescription['commands'] as $name) {
                    $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
                    $commandXML->appendChild($dom->createTextNode($name));
                }
            }
        }

        return $dom;
    }

    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->writeDocument($this->getInputArgumentDocument($argument));
    }

    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $this->writeDocument($this->getInputOptionDocument($option));
    }

    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        $this->writeDocument($this->getInputDefinitionDocument($definition));
    }

    protected function describeCommand(Command $command, array $options = []): void
    {
        $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? false));
    }

    protected function describeApplication(Application $application, array $options = []): void
    {
        $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? false));
    }

    /**
     * Appends document children to parent node.
     */
    private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent): void
    {
        foreach ($importedParent->childNodes as $childNode) {
            $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
        }
    }

    /**
     * Writes DOM document.
     */
    private function writeDocument(\DOMDocument $dom): void
    {
        $dom->formatOutput = true;
        $this->write($dom->saveXML());
    }

    private function getInputArgumentDocument(InputArgument $argument): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('argument'));
        $objectXML->setAttribute('name', $argument->getName());
        $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
        $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));

        $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
        $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : []));
        foreach ($defaults as $default) {
            $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
            $defaultXML->appendChild($dom->createTextNode($default));
        }

        return $dom;
    }

    private function getInputOptionDocument(InputOption $option): \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('option'));
        $objectXML->setAttribute('name', '--'.$option->getName());
        $pos = strpos($option->getShortcut() ?? '', '|');
        if (false !== $pos) {
            $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
            $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut()));
        } else {
            $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
        }
        $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
        $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
        $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));

        if ($option->acceptValue()) {
            $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : []));
            $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));

            foreach ($defaults as $default) {
                $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                $defaultXML->appendChild($dom->createTextNode($default));
            }
        }

        if ($option->isNegatable()) {
            $dom->appendChild($objectXML = $dom->createElement('option'));
            $objectXML->setAttribute('name', '--no-'.$option->getName());
            $objectXML->setAttribute('shortcut', '');
            $objectXML->setAttribute('accept_value', 0);
            $objectXML->setAttribute('is_value_required', 0);
            $objectXML->setAttribute('is_multiple', 0);
            $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
            $descriptionXML->appendChild($dom->createTextNode('Negate the "--'.$option->getName().'" option'));
        }

        return $dom;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * Descriptor interface.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface DescriptorInterface
{
    public function describe(OutputInterface $output, object $object, array $options = []): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class ApplicationDescription
{
    public const GLOBAL_NAMESPACE = '_global';

    private array $namespaces;

    /**
     * @var array<string, Command>
     */
    private array $commands;

    /**
     * @var array<string, Command>
     */
    private array $aliases = [];

    public function __construct(
        private Application $application,
        private ?string $namespace = null,
        private bool $showHidden = false,
    ) {
    }

    public function getNamespaces(): array
    {
        if (!isset($this->namespaces)) {
            $this->inspectApplication();
        }

        return $this->namespaces;
    }

    /**
     * @return Command[]
     */
    public function getCommands(): array
    {
        if (!isset($this->commands)) {
            $this->inspectApplication();
        }

        return $this->commands;
    }

    /**
     * @throws CommandNotFoundException
     */
    public function getCommand(string $name): Command
    {
        if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }

        return $this->commands[$name] ?? $this->aliases[$name];
    }

    private function inspectApplication(): void
    {
        $this->commands = [];
        $this->namespaces = [];

        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
        foreach ($this->sortCommands($all) as $namespace => $commands) {
            $names = [];

            foreach ($commands as $name => $command) {
                if (!$command->getName() || (!$this->showHidden && $command->isHidden())) {
                    continue;
                }

                if ($command->getName() === $name) {
                    $this->commands[$name] = $command;
                } else {
                    $this->aliases[$name] = $command;
                }

                $names[] = $name;
            }

            $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
        }
    }

    /**
     * @return array<string, array<string, Command>>
     */
    private function sortCommands(array $commands): array
    {
        $namespacedCommands = [];
        $globalCommands = [];
        $sortedCommands = [];
        foreach ($commands as $name => $command) {
            $key = $this->application->extractNamespace($name, 1);
            if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) {
                $globalCommands[$name] = $command;
            } else {
                $namespacedCommands[$key][$name] = $command;
            }
        }

        if ($globalCommands) {
            ksort($globalCommands);
            $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands;
        }

        if ($namespacedCommands) {
            ksort($namespacedCommands, \SORT_STRING);
            foreach ($namespacedCommands as $key => $commandsSet) {
                ksort($commandsSet);
                $sortedCommands[$key] = $commandsSet;
            }
        }

        return $sortedCommands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Markdown descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class MarkdownDescriptor extends Descriptor
{
    public function describe(OutputInterface $output, object $object, array $options = []): void
    {
        $decorated = $output->isDecorated();
        $output->setDecorated(false);

        parent::describe($output, $object, $options);

        $output->setDecorated($decorated);
    }

    protected function write(string $content, bool $decorated = true): void
    {
        parent::write($content, $decorated);
    }

    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->write(
            '#### `'.($argument->getName() ?: '<none>')."`\n\n"
            .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '')
            .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
            .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
        );
    }

    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $name = '--'.$option->getName();
        if ($option->isNegatable()) {
            $name .= '|--no-'.$option->getName();
        }
        if ($option->getShortcut()) {
            $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).'';
        }

        $this->write(
            '#### `'.$name.'`'."\n\n"
            .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '')
            .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
            .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
            .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
            .'* Is negatable: '.($option->isNegatable() ? 'yes' : 'no')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
        );
    }

    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        if ($showArguments = \count($definition->getArguments()) > 0) {
            $this->write('### Arguments');
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->describeInputArgument($argument);
            }
        }

        if (\count($definition->getOptions()) > 0) {
            if ($showArguments) {
                $this->write("\n\n");
            }

            $this->write('### Options');
            foreach ($definition->getOptions() as $option) {
                $this->write("\n\n");
                $this->describeInputOption($option);
            }
        }
    }

    protected function describeCommand(Command $command, array $options = []): void
    {
        if ($options['short'] ?? false) {
            $this->write(
                '`'.$command->getName()."`\n"
                .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n"
                .($command->getDescription() ? $command->getDescription()."\n\n" : '')
                .'### Usage'."\n\n"
                .array_reduce($command->getAliases(), static fn ($carry, $usage) => $carry.'* `'.$usage.'`'."\n")
            );

            return;
        }

        $command->mergeApplicationDefinition(false);

        $this->write(
            '`'.$command->getName()."`\n"
            .str_repeat('-', Helper::width($command->getName()) + 2)."\n\n"
            .($command->getDescription() ? $command->getDescription()."\n\n" : '')
            .'### Usage'."\n\n"
            .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), static fn ($carry, $usage) => $carry.'* `'.$usage.'`'."\n")
        );

        if ($help = $command->getProcessedHelp()) {
            $this->write("\n");
            $this->write($help);
        }

        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->write("\n\n");
            $this->describeInputDefinition($definition);
        }
    }

    protected function describeApplication(Application $application, array $options = []): void
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace);
        $title = $this->getApplicationTitle($application);

        $this->write($title."\n".str_repeat('=', Helper::width($title)));

        foreach ($description->getNamespaces() as $namespace) {
            if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                $this->write("\n\n");
                $this->write('**'.$namespace['id'].':**');
            }

            $this->write("\n\n");
            $this->write(implode("\n", array_map(static fn ($commandName) => \sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())), $namespace['commands'])));
        }

        foreach ($description->getCommands() as $command) {
            $this->write("\n\n");
            $this->describeCommand($command, $options);
        }
    }

    private function getApplicationTitle(Application $application): string
    {
        if ('UNKNOWN' !== $application->getName()) {
            if ('UNKNOWN' !== $application->getVersion()) {
                return \sprintf('%s %s', $application->getName(), $application->getVersion());
            }

            return $application->getName();
        }

        return 'Console Tool';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * JSON descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class JsonDescriptor extends Descriptor
{
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        $this->writeData($this->getInputArgumentData($argument), $options);
    }

    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        $this->writeData($this->getInputOptionData($option), $options);
        if ($option->isNegatable()) {
            $this->writeData($this->getInputOptionData($option, true), $options);
        }
    }

    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        $this->writeData($this->getInputDefinitionData($definition), $options);
    }

    protected function describeCommand(Command $command, array $options = []): void
    {
        $this->writeData($this->getCommandData($command, $options['short'] ?? false), $options);
    }

    protected function describeApplication(Application $application, array $options = []): void
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace, true);
        $commands = [];

        foreach ($description->getCommands() as $command) {
            $commands[] = $this->getCommandData($command, $options['short'] ?? false);
        }

        $data = [];
        if ('UNKNOWN' !== $application->getName()) {
            $data['application']['name'] = $application->getName();
            if ('UNKNOWN' !== $application->getVersion()) {
                $data['application']['version'] = $application->getVersion();
            }
        }

        $data['commands'] = $commands;

        if ($describedNamespace) {
            $data['namespace'] = $describedNamespace;
        } else {
            $data['namespaces'] = array_values($description->getNamespaces());
        }

        $this->writeData($data, $options);
    }

    /**
     * Writes data as json.
     */
    private function writeData(array $data, array $options): void
    {
        $flags = $options['json_encoding'] ?? 0;

        $this->write(json_encode($data, $flags));
    }

    private function getInputArgumentData(InputArgument $argument): array
    {
        return [
            'name' => $argument->getName(),
            'is_required' => $argument->isRequired(),
            'is_array' => $argument->isArray(),
            'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
            'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
        ];
    }

    private function getInputOptionData(InputOption $option, bool $negated = false): array
    {
        return $negated ? [
            'name' => '--no-'.$option->getName(),
            'shortcut' => '',
            'accept_value' => false,
            'is_value_required' => false,
            'is_multiple' => false,
            'description' => 'Negate the "--'.$option->getName().'" option',
            'default' => null === $option->getDefault() ? null : !$option->getDefault(),
        ] : [
            'name' => '--'.$option->getName(),
            'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '',
            'accept_value' => $option->acceptValue(),
            'is_value_required' => $option->isValueRequired(),
            'is_multiple' => $option->isArray(),
            'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
            'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(),
        ];
    }

    private function getInputDefinitionData(InputDefinition $definition): array
    {
        $inputArguments = [];
        foreach ($definition->getArguments() as $name => $argument) {
            $inputArguments[$name] = $this->getInputArgumentData($argument);
        }

        $inputOptions = [];
        foreach ($definition->getOptions() as $name => $option) {
            $inputOptions[$name] = $this->getInputOptionData($option);
            if ($option->isNegatable()) {
                $inputOptions['no-'.$name] = $this->getInputOptionData($option, true);
            }
        }

        return ['arguments' => $inputArguments, 'options' => $inputOptions];
    }

    private function getCommandData(Command $command, bool $short = false): array
    {
        $data = [
            'name' => $command->getName(),
            'description' => $command->getDescription(),
        ];

        if ($short) {
            $data += [
                'usage' => $command->getAliases(),
            ];
        } else {
            $command->mergeApplicationDefinition(false);

            $data += [
                'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()),
                'help' => $command->getProcessedHelp(),
                'definition' => $this->getInputDefinitionData($command->getDefinition()),
            ];
        }

        $data['hidden'] = $command->isHidden();

        return $data;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * Text descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class TextDescriptor extends Descriptor
{
    protected function describeInputArgument(InputArgument $argument, array $options = []): void
    {
        if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
            $default = \sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
        } else {
            $default = '';
        }

        $totalWidth = $options['total_width'] ?? Helper::width($argument->getName());
        $spacingWidth = $totalWidth - \strlen($argument->getName());

        $this->writeText(\sprintf('  <info>%s</info>  %s%s%s',
            $argument->getName(),
            str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
            $default
        ), $options);
    }

    protected function describeInputOption(InputOption $option, array $options = []): void
    {
        if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
            $default = \sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
        } else {
            $default = '';
        }

        $value = '';
        if ($option->acceptValue()) {
            $value = '='.strtoupper($option->getName());

            if ($option->isValueOptional()) {
                $value = '['.$value.']';
            }
        }

        $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]);
        $synopsis = \sprintf('%s%s',
            $option->getShortcut() ? \sprintf('-%s, ', $option->getShortcut()) : '    ',
            \sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value)
        );

        $spacingWidth = $totalWidth - Helper::width($synopsis);

        $this->writeText(\sprintf('  <info>%s</info>  %s%s%s%s',
            $synopsis,
            str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
            $default,
            $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
        ), $options);
    }

    protected function describeInputDefinition(InputDefinition $definition, array $options = []): void
    {
        $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
        foreach ($definition->getArguments() as $argument) {
            $totalWidth = max($totalWidth, Helper::width($argument->getName()));
        }

        if ($definition->getArguments()) {
            $this->writeText('<comment>Arguments:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getArguments() as $argument) {
                $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth]));
                $this->writeText("\n");
            }
        }

        if ($definition->getArguments() && $definition->getOptions()) {
            $this->writeText("\n");
        }

        if ($definition->getOptions()) {
            $laterOptions = [];

            $this->writeText('<comment>Options:</comment>', $options);
            foreach ($definition->getOptions() as $option) {
                if (\strlen($option->getShortcut() ?? '') > 1) {
                    $laterOptions[] = $option;
                    continue;
                }
                $this->writeText("\n");
                $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
            }
            foreach ($laterOptions as $option) {
                $this->writeText("\n");
                $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
            }
        }
    }

    protected function describeCommand(Command $command, array $options = []): void
    {
        $command->mergeApplicationDefinition(false);

        if ($description = $command->getDescription()) {
            $this->writeText('<comment>Description:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  '.$description);
            $this->writeText("\n\n");
        }

        $this->writeText('<comment>Usage:</comment>', $options);
        foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) {
            $this->writeText("\n");
            $this->writeText('  '.OutputFormatter::escape($usage), $options);
        }
        $this->writeText("\n");

        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->writeText("\n");
            $this->describeInputDefinition($definition, $options);
            $this->writeText("\n");
        }

        $help = $command->getProcessedHelp();
        if ($help && $help !== $description) {
            $this->writeText("\n");
            $this->writeText('<comment>Help:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
            $this->writeText("\n");
        }
    }

    protected function describeApplication(Application $application, array $options = []): void
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace);

        if (isset($options['raw_text']) && $options['raw_text']) {
            $width = $this->getColumnWidth($description->getCommands());

            foreach ($description->getCommands() as $command) {
                $this->writeText(\sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
                $this->writeText("\n");
            }
        } else {
            if ('' != $help = $application->getHelp()) {
                $this->writeText("$help\n\n", $options);
            }

            $this->writeText("<comment>Usage:</comment>\n", $options);
            $this->writeText("  command [options] [arguments]\n\n", $options);

            $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);

            $this->writeText("\n");
            $this->writeText("\n");

            $commands = $description->getCommands();
            $namespaces = $description->getNamespaces();
            if ($describedNamespace && $namespaces) {
                // make sure all alias commands are included when describing a specific namespace
                $describedNamespaceInfo = reset($namespaces);
                foreach ($describedNamespaceInfo['commands'] as $name) {
                    $commands[$name] = $description->getCommand($name);
                }
            }

            // calculate max. width based on available commands per namespace
            $width = $this->getColumnWidth(array_merge(...array_values(array_map(static fn ($namespace) => array_intersect($namespace['commands'], array_keys($commands)), array_values($namespaces)))));

            if ($describedNamespace) {
                $this->writeText(\sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
            } else {
                $this->writeText('<comment>Available commands:</comment>', $options);
            }

            foreach ($namespaces as $namespace) {
                $namespace['commands'] = array_filter($namespace['commands'], static fn ($name) => isset($commands[$name]));

                if (!$namespace['commands']) {
                    continue;
                }

                if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                    $this->writeText("\n");
                    $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
                }

                foreach ($namespace['commands'] as $name) {
                    $this->writeText("\n");
                    $spacingWidth = $width - Helper::width($name);
                    $command = $commands[$name];
                    $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
                    $this->writeText(\sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options);
                }
            }

            $this->writeText("\n");
        }
    }

    private function writeText(string $content, array $options = []): void
    {
        $this->write(
            isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
            isset($options['raw_output']) ? !$options['raw_output'] : true
        );
    }

    /**
     * Formats command aliases to show them in the command description.
     */
    private function getCommandAliasesText(Command $command): string
    {
        $text = '';
        $aliases = $command->getAliases();

        if ($aliases) {
            $text = '['.implode('|', $aliases).'] ';
        }

        return $text;
    }

    /**
     * Formats input option/argument default value.
     */
    private function formatDefaultValue(mixed $default): string
    {
        if (\INF === $default) {
            return 'INF';
        }

        if (\is_string($default)) {
            $default = OutputFormatter::escape($default);
        } elseif (\is_array($default)) {
            foreach ($default as $key => $value) {
                if (\is_string($value)) {
                    $default[$key] = OutputFormatter::escape($value);
                }
            }
        }

        return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
    }

    /**
     * @param array<Command|string> $commands
     */
    private function getColumnWidth(array $commands): int
    {
        $widths = [];

        foreach ($commands as $command) {
            if ($command instanceof Command) {
                $widths[] = Helper::width($command->getName());
                foreach ($command->getAliases() as $alias) {
                    $widths[] = Helper::width($alias);
                }
            } else {
                $widths[] = Helper::width($command);
            }
        }

        return $widths ? max($widths) + 2 : 0;
    }

    /**
     * @param InputOption[] $options
     */
    private function calculateTotalWidthForOptions(array $options): int
    {
        $totalWidth = 0;
        foreach ($options as $option) {
            // "-" + shortcut + ", --" + name
            $nameLength = 1 + max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName());
            if ($option->isNegatable()) {
                $nameLength += 6 + Helper::width($option->getName()); // |--no- + name
            } elseif ($option->acceptValue()) {
                $valueLength = 1 + Helper::width($option->getName()); // = + value
                $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]

                $nameLength += $valueLength;
            }
            $totalWidth = max($totalWidth, $nameLength);
        }

        return $totalWidth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Php86;

/**
 * @author kylekatarnls <kylekatarnls@gmail.com>
 *
 * @internal
 */
final class Php86
{
    /**
     * @template Value
     * @template Minimum
     * @template Maximum
     *
     * @param Value   $value
     * @param Minimum $min
     * @param Maximum $max
     *
     * @return Value|Minimum|Maximum
     */
    public static function clamp($value, $min, $max)
    {
        if (\is_float($min) && is_nan($min)) {
            self::throwValueErrorIfAvailable('clamp(): Argument #2 ($min) must not be NAN');
        }

        if (\is_float($max) && is_nan($max)) {
            self::throwValueErrorIfAvailable('clamp(): Argument #3 ($max) must not be NAN');
        }

        if ($max < $min) {
            self::throwValueErrorIfAvailable('clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max)');
        }

        if ($value > $max) {
            return $max;
        }

        if ($value < $min) {
            return $min;
        }

        return $value;
    }

    private static function throwValueErrorIfAvailable(string $message): void
    {
        if (!class_exists(\ValueError::class)) {
            throw new \InvalidArgumentException($message);
        }

        throw new \ValueError($message);
    }

    public static function grapheme_strrev(string $string)
    {
        if (false === $units = grapheme_str_split($string)) {
            return false;
        }

        return implode('', array_reverse($units));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80600 && \PHP_VERSION_ID >= 80100) {
    enum SortDirection
    {
        case Ascending;
        case Descending;
    }
}
Copyright (c) 2025-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php86 as p;

if (\PHP_VERSION_ID >= 80600) {
    return;
}

if (!defined('ARRAY_FILTER_USE_VALUE')) {
    define('ARRAY_FILTER_USE_VALUE', 0);
}

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (!function_exists('clamp')) {
    /**
     * @template V
     * @template L
     * @template H
     *
     * @param V $value
     * @param L $min
     * @param H $max
     *
     * @return V|L|H
     */
    function clamp($value, $min, $max) { return p\Php86::clamp($value, $min, $max); }
}

if (extension_loaded('intl') && !function_exists('grapheme_strrev')) {
    function grapheme_strrev(string $string) { return p\Php86::grapheme_strrev($string); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php86 as p;

if (\PHP_VERSION_ID >= 80600) {
    return;
}

if (!function_exists('clamp')) {
    /**
     * @template V
     * @template L
     * @template H
     *
     * @param V $value
     * @param L $min
     * @param H $max
     *
     * @return V|L|H
     */
    function clamp(mixed $value, mixed $min, mixed $max): mixed { return p\Php86::clamp($value, $min, $max); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80500) {
    #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
    final class NoDiscard
    {
        public ?string $message;

        public function __construct(?string $message = null)
        {
            $this->message = $message;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80500) {
    // @author Daniel Scherzer <daniel.e.scherzer@gmail.com>
    #[Attribute(Attribute::TARGET_ALL)]
    final class DelayedTargetValidation
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Filter;

if (\PHP_VERSION_ID < 80500) {
    class FilterFailedException extends FilterException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Filter;

if (\PHP_VERSION_ID < 80500) {
    class FilterException extends \Exception
    {
    }
}
Copyright (c) 2025-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Php85;

/**
 * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
 * @author Alexander Schranz <alexander@sulu.io>
 *
 * @internal
 */
final class Php85
{
    public static function get_error_handler(): ?callable
    {
        $handler = set_error_handler(null);
        restore_error_handler();

        return $handler;
    }

    public static function get_exception_handler(): ?callable
    {
        $handler = set_exception_handler(null);
        restore_exception_handler();

        return $handler;
    }

    public static function array_first(array $array)
    {
        foreach ($array as $value) {
            return $value;
        }

        return null;
    }

    public static function array_last(array $array)
    {
        return $array ? current(\array_slice($array, -1)) : null;
    }

    private const RTL_SCRIPTS = [
        'Adlm' => true, 'Arab' => true, 'Armi' => true, 'Hebr' => true,
        'Mand' => true, 'Mani' => true, 'Mend' => true, 'Nkoo' => true,
        'Orkh' => true, 'Phnx' => true, 'Rohg' => true, 'Samr' => true,
        'Syrc' => true, 'Thaa' => true, 'Yezi' => true,
    ];

    private const LANG_TO_SCRIPT = [
        'ar' => 'Arab',
        'ckb' => 'Arab',
        'dv' => 'Thaa',
        'fa' => 'Arab',
        'he' => 'Hebr',
        'ku' => 'Arab',
        'nqo' => 'Nkoo',
        'ps' => 'Arab',
        'sd' => 'Arab',
        'ug' => 'Arab',
        'ur' => 'Arab',
        'yi' => 'Hebr',
    ];

    public static function locale_is_right_to_left(string $locale): bool
    {
        if ('' === $locale) {
            return false;
        }

        $parts = preg_split('/[_-]/', $locale);
        $language = strtolower($parts[0]);

        foreach ($parts as $part) {
            if (4 === \strlen($part) && ctype_alpha($part)) {
                return isset(self::RTL_SCRIPTS[ucfirst(strtolower($part))]);
            }
        }

        return isset(self::LANG_TO_SCRIPT[$language]) && isset(self::RTL_SCRIPTS[self::LANG_TO_SCRIPT[$language]]);
    }

    public static function grapheme_levenshtein(string $s1, string $s2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1)
    {
        if (!preg_match('//u', $s1) || !preg_match('//u', $s2)) {
            return false;
        }

        if (0 > $insertion_cost || 0 > $replacement_cost || 0 > $deletion_cost) {
            throw new \ValueError('grapheme_levenshtein(): Argument #3 ($insertion_cost), #4 ($replacement_cost), and #5 ($deletion_cost) must be greater than or equal to 0');
        }

        $regex = ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39)
            ? '\X'
            : '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';

        preg_match_all('/'.$regex.'/u', $s1, $s1);
        preg_match_all('/'.$regex.'/u', $s2, $s2);

        $s1 = $s1[0];
        $s2 = $s2[0];
        $l1 = \count($s1);
        $l2 = \count($s2);

        if (0 === $l1) {
            return $l2 * $insertion_cost;
        }
        if (0 === $l2) {
            return $l1 * $deletion_cost;
        }

        $dp = array_fill(0, $l1 + 1, array_fill(0, $l2 + 1, 0));

        for ($i = 1; $i <= $l1; ++$i) {
            $dp[$i][0] = $dp[$i - 1][0] + $deletion_cost;
        }
        for ($j = 1; $j <= $l2; ++$j) {
            $dp[0][$j] = $dp[0][$j - 1] + $insertion_cost;
        }

        for ($i = 1; $i <= $l1; ++$i) {
            for ($j = 1; $j <= $l2; ++$j) {
                $cost = ($s1[$i - 1] === $s2[$j - 1]) ? 0 : $replacement_cost;
                $dp[$i][$j] = min($dp[$i - 1][$j] + $deletion_cost, $dp[$i][$j - 1] + $insertion_cost, $dp[$i - 1][$j - 1] + $cost);
            }
        }

        return $dp[$l1][$l2];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php85 as p;

if (\PHP_VERSION_ID >= 80500) {
    return;
}

if (!function_exists('get_error_handler')) {
    function get_error_handler(): ?callable { return p\Php85::get_error_handler(); }
}

if (!function_exists('get_exception_handler')) {
    function get_exception_handler(): ?callable { return p\Php85::get_exception_handler(); }
}

if (!function_exists('array_first')) {
    function array_first(array $array) { return p\Php85::array_first($array); }
}

if (!function_exists('array_last')) {
    function array_last(array $array) { return p\Php85::array_last($array); }
}

if (extension_loaded('intl') && !function_exists('locale_is_right_to_left')) {
    function locale_is_right_to_left(string $locale): bool { return p\Php85::locale_is_right_to_left($locale); }
}

if (\PHP_VERSION_ID >= 80000) {
    require __DIR__.'/bootstrap80.php';

    return;
}

if (extension_loaded('intl') && !function_exists('grapheme_levenshtein')) {
    function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = '') { return p\Php85::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php85 as p;

if (\PHP_VERSION_ID >= 80500) {
    return;
}

if (extension_loaded('intl') && !function_exists('grapheme_levenshtein')) {
    function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = ''): int|false { return p\Php85::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateMalformedStringException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateObjectError extends DateError
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateMalformedPeriodStringException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateInvalidOperationException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateRangeError extends DateError
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateException extends Exception
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateInvalidTimeZoneException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateMalformedIntervalStringException extends DateException
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class SQLite3Exception extends Exception
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    #[Attribute(Attribute::TARGET_METHOD)]
    final class Override
    {
        public function __construct()
        {
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80300) {
    class DateError extends Error
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Php83;

/**
 * @author Ion Bazan <ion.bazan@gmail.com>
 * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
 *
 * @internal
 */
final class Php83
{
    private const JSON_MAX_DEPTH = 0x7FFFFFFF; // see https://www.php.net/manual/en/function.json-decode.php

    public static function json_validate(string $json, int $depth = 512, int $flags = 0): bool
    {
        if (0 !== $flags && \defined('JSON_INVALID_UTF8_IGNORE') && \JSON_INVALID_UTF8_IGNORE !== $flags) {
            throw new \ValueError('json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE)');
        }

        if ($depth <= 0) {
            throw new \ValueError('json_validate(): Argument #2 ($depth) must be greater than 0');
        }

        if ($depth > self::JSON_MAX_DEPTH) {
            throw new \ValueError(\sprintf('json_validate(): Argument #2 ($depth) must be less than %d', self::JSON_MAX_DEPTH));
        }

        json_decode($json, true, $depth, $flags);

        return \JSON_ERROR_NONE === json_last_error();
    }

    /** @return string|false */
    public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
    {
        if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
            throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
        }

        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }

        $errorToTrigger = null;
        try {
            if (!@mb_check_encoding('', $encoding)) {
                $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding);
            }
        } catch (\ValueError $e) {
            $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding);
        }

        if (mb_strlen($pad_string, $encoding) <= 0) {
            $errorToTrigger = 'mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string';
        }

        if (null !== $errorToTrigger) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error($errorToTrigger, \E_USER_WARNING);

                return false;
            }

            throw new \ValueError($errorToTrigger);
        }

        $paddingRequired = $length - mb_strlen($string, $encoding);

        if ($paddingRequired < 1) {
            return $string;
        }

        switch ($pad_type) {
            case \STR_PAD_LEFT:
                return mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string;
            case \STR_PAD_RIGHT:
                return $string.mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
            default:
                $leftPaddingLength = floor($paddingRequired / 2);
                $rightPaddingLength = $paddingRequired - $leftPaddingLength;

                return mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
        }
    }

    public static function str_increment(string $string): string
    {
        if ('' === $string) {
            throw new \ValueError('str_increment(): Argument #1 ($string) cannot be empty');
        }

        if (!preg_match('/^[a-zA-Z0-9]+$/', $string)) {
            throw new \ValueError('str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters');
        }

        if (is_numeric($string)) {
            $offset = stripos($string, 'e');
            if (false !== $offset) {
                $char = $string[$offset];
                ++$char;
                $string[$offset] = $char;
                ++$string;

                switch ($string[$offset]) {
                    case 'f':
                        $string[$offset] = 'e';
                        break;
                    case 'F':
                        $string[$offset] = 'E';
                        break;
                    case 'g':
                        $string[$offset] = 'f';
                        break;
                    case 'G':
                        $string[$offset] = 'F';
                        break;
                }

                return $string;
            }
        }

        return ++$string;
    }

    public static function str_decrement(string $string): string
    {
        if ('' === $string) {
            throw new \ValueError('str_decrement(): Argument #1 ($string) cannot be empty');
        }

        if (!preg_match('/^[a-zA-Z0-9]+$/', $string)) {
            throw new \ValueError('str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters');
        }

        if (preg_match('/\A(?:0[aA0]?|[aA])\z/', $string)) {
            throw new \ValueError(\sprintf('str_decrement(): Argument #1 ($string) "%s" is out of decrement range', $string));
        }

        if (!\in_array(substr($string, -1), ['A', 'a', '0'], true)) {
            return implode('', \array_slice(str_split($string), 0, -1)).\chr(\ord(substr($string, -1)) - 1);
        }

        $carry = '';
        $decremented = '';

        for ($i = \strlen($string) - 1; $i >= 0; --$i) {
            $char = $string[$i];

            switch ($char) {
                case 'A':
                    if ('' !== $carry) {
                        $decremented = $carry.$decremented;
                        $carry = '';
                    }
                    $carry = 'Z';

                    break;
                case 'a':
                    if ('' !== $carry) {
                        $decremented = $carry.$decremented;
                        $carry = '';
                    }
                    $carry = 'z';

                    break;
                case '0':
                    if ('' !== $carry) {
                        $decremented = $carry.$decremented;
                        $carry = '';
                    }
                    $carry = '9';

                    break;
                case '1':
                    if ('' !== $carry) {
                        $decremented = $carry.$decremented;
                        $carry = '';
                    }

                    break;
                default:
                    if ('' !== $carry) {
                        $decremented = $carry.$decremented;
                        $carry = '';
                    }

                    if (!\in_array($char, ['A', 'a', '0'], true)) {
                        $decremented = \chr(\ord($char) - 1).$decremented;
                    }
            }
        }

        return $decremented;
    }
}
Copyright (c) 2022-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID >= 80300) {
    return;
}

if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) {
    function ldap_exop_sync(\LDAP\Connection $ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); }
}

if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) {
    function ldap_connect_wallet(?string $uri, string $wallet, #[\SensitiveParameter] string $password, int $auth_mode = \GSLC_SSL_NO_AUTH): \LDAP\Connection|false { return ldap_connect($uri, $wallet, $password, $auth_mode); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php83 as p;

if (\PHP_VERSION_ID >= 80300) {
    return;
}

if (!function_exists('json_validate')) {
    function json_validate(string $json, int $depth = 512, int $flags = 0): bool { return p\Php83::json_validate($json, $depth, $flags); }
}

if (!function_exists('stream_context_set_options')) {
    function stream_context_set_options($context, array $options): bool { return stream_context_set_option($context, $options); }
}

if (!function_exists('str_increment')) {
    function str_increment(string $string): string { return p\Php83::str_increment($string); }
}

if (!function_exists('str_decrement')) {
    function str_decrement(string $string): string { return p\Php83::str_decrement($string); }
}

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_str_pad')) {
        function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null) { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
    }
}

if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) {
    function ldap_exop_sync($ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); }
}

if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) {
    function ldap_connect_wallet(?string $uri, string $wallet, string $password, int $auth_mode = \GSLC_SSL_NO_AUTH) { return ldap_connect($uri, $wallet, $password, $auth_mode); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php83 as p;

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_str_pad')) {
        function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
    }
}

if (\PHP_VERSION_ID >= 80100) {
    return require __DIR__.'/bootstrap81.php';
}

if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) {
    function ldap_exop_sync($ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); }
}

if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) {
    function ldap_connect_wallet(?string $uri, string $wallet, string $password, int $auth_mode = \GSLC_SSL_NO_AUTH) { return ldap_connect($uri, $wallet, $password, $auth_mode); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

if (!\function_exists(now::class)) {
    /**
     * @throws \DateMalformedStringException When the modifier is invalid
     */
    function now(string $modifier = 'now'): DatePoint
    {
        if ('now' !== $modifier) {
            return new DatePoint($modifier);
        }

        $now = Clock::get()->now();

        return $now instanceof DatePoint ? $now : DatePoint::createFromInterface($now);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

/**
 * A clock that relies the system time.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class NativeClock implements ClockInterface
{
    private \DateTimeZone $timezone;

    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function __construct(\DateTimeZone|string|null $timezone = null)
    {
        $this->timezone = \is_string($timezone ??= date_default_timezone_get()) ? $this->withTimeZone($timezone)->timezone : $timezone;
    }

    public function now(): DatePoint
    {
        return DatePoint::createFromInterface(new \DateTimeImmutable('now', $this->timezone));
    }

    public function sleep(float|int $seconds): void
    {
        if (0 < $s = (int) $seconds) {
            sleep($s);
        }

        if (0 < $us = $seconds - $s) {
            usleep((int) ($us * 1E6));
        }
    }

    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }

        $clone = clone $this;
        $clone->timezone = $timezone;

        return $clone;
    }
}
Copyright (c) 2022-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

use Psr\Clock\ClockInterface as PsrClockInterface;

/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ClockInterface extends PsrClockInterface
{
    public function sleep(float|int $seconds): void;

    public function withTimeZone(\DateTimeZone|string $timezone): static;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock\Test;

use PHPUnit\Framework\Attributes\After;
use PHPUnit\Framework\Attributes\Before;
use PHPUnit\Framework\Attributes\BeforeClass;
use Symfony\Component\Clock\Clock;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\Clock\MockClock;

use function Symfony\Component\Clock\now;

/**
 * Helps with mocking the time in your test cases.
 *
 * This trait provides one self::mockTime() method that freezes the time.
 * It restores the global clock after each test case.
 * self::mockTime() accepts either a string (eg '+1 days' or '2022-12-22'),
 * a DateTimeImmutable, or a boolean (to freeze/restore the global clock).
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ClockSensitiveTrait
{
    public static function mockTime(string|\DateTimeImmutable|bool $when = true): ClockInterface
    {
        Clock::set(match (true) {
            false === $when => self::saveClockBeforeTest(false),
            true === $when => new MockClock(),
            $when instanceof \DateTimeImmutable => new MockClock($when),
            default => new MockClock(now($when)),
        });

        return Clock::get();
    }

    /**
     * @beforeClass
     *
     * @before
     *
     * @internal
     */
    #[Before]
    #[BeforeClass]
    public static function saveClockBeforeTest(bool $save = true): ClockInterface
    {
        static $originalClock;

        if ($save && $originalClock) {
            self::restoreClockAfterTest();
        }

        return $save ? $originalClock = Clock::get() : $originalClock;
    }

    /**
     * @after
     *
     * @internal
     */
    #[After]
    protected static function restoreClockAfterTest(): void
    {
        Clock::set(self::saveClockBeforeTest(false));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

use Psr\Clock\ClockInterface as PsrClockInterface;

/**
 * A global clock.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class Clock implements ClockInterface
{
    private static ClockInterface $globalClock;

    public function __construct(
        private readonly ?PsrClockInterface $clock = null,
        private ?\DateTimeZone $timezone = null,
    ) {
    }

    /**
     * Returns the current global clock.
     *
     * Note that you should prefer injecting a ClockInterface or using
     * ClockAwareTrait when possible instead of using this method.
     */
    public static function get(): ClockInterface
    {
        return self::$globalClock ??= new NativeClock();
    }

    public static function set(PsrClockInterface $clock): void
    {
        self::$globalClock = $clock instanceof ClockInterface ? $clock : new self($clock);
    }

    public function now(): DatePoint
    {
        $now = ($this->clock ?? self::get())->now();

        if (!$now instanceof DatePoint) {
            $now = DatePoint::createFromInterface($now);
        }

        return isset($this->timezone) ? $now->setTimezone($this->timezone) : $now;
    }

    public function sleep(float|int $seconds): void
    {
        $clock = $this->clock ?? self::get();

        if ($clock instanceof ClockInterface) {
            $clock->sleep($seconds);
        } else {
            (new NativeClock())->sleep($seconds);
        }
    }

    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }

        $clone = clone $this;
        $clone->timezone = $timezone;

        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

/**
 * A monotonic clock suitable for performance profiling.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class MonotonicClock implements ClockInterface
{
    private int $sOffset;
    private int $usOffset;
    private \DateTimeZone $timezone;

    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function __construct(\DateTimeZone|string|null $timezone = null)
    {
        if (false === $offset = hrtime()) {
            throw new \RuntimeException('hrtime() returned false: the runtime environment does not provide access to a monotonic timer.');
        }

        $time = explode(' ', microtime(), 2);
        $this->sOffset = $time[1] - $offset[0];
        $this->usOffset = (int) ($time[0] * 1000000) - (int) ($offset[1] / 1000);

        $this->timezone = \is_string($timezone ??= date_default_timezone_get()) ? $this->withTimeZone($timezone)->timezone : $timezone;
    }

    public function now(): DatePoint
    {
        [$s, $us] = hrtime();

        if (1000000 <= $us = (int) ($us / 1000) + $this->usOffset) {
            ++$s;
            $us -= 1000000;
        } elseif (0 > $us) {
            --$s;
            $us += 1000000;
        }

        if (6 !== \strlen($now = (string) $us)) {
            $now = str_pad($now, 6, '0', \STR_PAD_LEFT);
        }

        $now = '@'.($s + $this->sOffset).'.'.$now;

        return DatePoint::createFromInterface(new \DateTimeImmutable($now, $this->timezone))->setTimezone($this->timezone);
    }

    public function sleep(float|int $seconds): void
    {
        if (0 < $s = (int) $seconds) {
            sleep($s);
        }

        if (0 < $us = $seconds - $s) {
            usleep((int) ($us * 1E6));
        }
    }

    /**
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }

        $clone = clone $this;
        $clone->timezone = $timezone;

        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

/**
 * An immmutable DateTime with stricter error handling and return types than the native one.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class DatePoint extends \DateTimeImmutable
{
    /**
     * @throws \DateMalformedStringException When $datetime is invalid
     */
    public function __construct(string $datetime = 'now', ?\DateTimeZone $timezone = null, ?parent $reference = null)
    {
        $now = $reference ?? Clock::get()->now();

        if ('now' !== $datetime) {
            if (!$now instanceof static) {
                $now = static::createFromInterface($now);
            }

            if (\PHP_VERSION_ID < 80300) {
                try {
                    $builtInDate = new parent($datetime, $timezone ?? $now->getTimezone());
                    $timezone = $builtInDate->getTimezone();
                } catch (\Exception $e) {
                    throw new \DateMalformedStringException($e->getMessage(), $e->getCode(), $e);
                }
            } else {
                $builtInDate = new parent($datetime, $timezone ?? $now->getTimezone());
                $timezone = $builtInDate->getTimezone();
            }

            $now = $now->setTimezone($timezone)->modify($datetime);

            if ('00:00:00.000000' === $builtInDate->format('H:i:s.u')) {
                $now = $now->setTime(0, 0);
            }
        } elseif (null !== $timezone) {
            $now = $now->setTimezone($timezone);
        }

        $this->__unserialize((array) $now);
    }

    /**
     * @throws \DateMalformedStringException When $format or $datetime are invalid
     */
    public static function createFromFormat(string $format, string $datetime, ?\DateTimeZone $timezone = null): static
    {
        return parent::createFromFormat($format, $datetime, $timezone) ?: throw new \DateMalformedStringException(static::getLastErrors()['errors'][0] ?? 'Invalid date string or format.');
    }

    public static function createFromInterface(\DateTimeInterface $object): static
    {
        return parent::createFromInterface($object);
    }

    public static function createFromMutable(\DateTime $object): static
    {
        return parent::createFromMutable($object);
    }

    public static function createFromTimestamp(int|float $timestamp): static
    {
        if (\PHP_VERSION_ID >= 80400) {
            return parent::createFromTimestamp($timestamp);
        }

        if (\is_int($timestamp) || !$ms = (int) $timestamp - $timestamp) {
            return static::createFromFormat('U', (string) $timestamp);
        }

        if (!is_finite($timestamp) || \PHP_INT_MAX + 1.0 <= $timestamp || \PHP_INT_MIN > $timestamp) {
            throw new \DateRangeError(\sprintf('DateTimeImmutable::createFromTimestamp(): Argument #1 ($timestamp) must be a finite number between %s and %s.999999, %s given', \PHP_INT_MIN, \PHP_INT_MAX, $timestamp));
        }

        if ($timestamp < 0) {
            $timestamp = (int) $timestamp - 2.0 + $ms;
        }

        return static::createFromFormat('U.u', \sprintf('%.6F', $timestamp));
    }

    public function add(\DateInterval $interval): static
    {
        return parent::add($interval);
    }

    public function sub(\DateInterval $interval): static
    {
        return parent::sub($interval);
    }

    /**
     * @throws \DateMalformedStringException When $modifier is invalid
     */
    public function modify(string $modifier): static
    {
        if (\PHP_VERSION_ID < 80300) {
            return @parent::modify($modifier) ?: throw new \DateMalformedStringException(error_get_last()['message'] ?? \sprintf('Invalid modifier: "%s".', $modifier));
        }

        return parent::modify($modifier);
    }

    public function setTimestamp(int $value): static
    {
        return parent::setTimestamp($value);
    }

    public function setDate(int $year, int $month, int $day): static
    {
        return parent::setDate($year, $month, $day);
    }

    public function setISODate(int $year, int $week, int $day = 1): static
    {
        return parent::setISODate($year, $week, $day);
    }

    public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0): static
    {
        return parent::setTime($hour, $minute, $second, $microsecond);
    }

    public function setTimezone(\DateTimeZone $timezone): static
    {
        return parent::setTimezone($timezone);
    }

    public function getTimezone(): \DateTimeZone
    {
        return parent::getTimezone() ?: throw new \DateInvalidTimeZoneException('The DatePoint object has no timezone.');
    }

    public function setMicrosecond(int $microsecond): static
    {
        if ($microsecond < 0 || $microsecond > 999999) {
            throw new \DateRangeError('DatePoint::setMicrosecond(): Argument #1 ($microsecond) must be between 0 and 999999, '.$microsecond.' given');
        }

        if (\PHP_VERSION_ID < 80400) {
            return $this->setTime(...explode('.', $this->format('H.i.s.'.$microsecond)));
        }

        return parent::setMicrosecond($microsecond);
    }

    public function getMicrosecond(): int
    {
        if (\PHP_VERSION_ID >= 80400) {
            return parent::getMicrosecond();
        }

        return $this->format('u');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

use Psr\Clock\ClockInterface;
use Symfony\Contracts\Service\Attribute\Required;

/**
 * A trait to help write time-sensitive classes.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ClockAwareTrait
{
    private readonly ClockInterface $clock;

    #[Required]
    public function setClock(ClockInterface $clock): void
    {
        $this->clock = $clock;
    }

    protected function now(): DatePoint
    {
        $now = ($this->clock ??= new Clock())->now();

        return $now instanceof DatePoint ? $now : DatePoint::createFromInterface($now);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Clock;

/**
 * A clock that always returns the same date, suitable for testing time-sensitive logic.
 *
 * Consider using ClockSensitiveTrait in your test cases instead of using this class directly.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class MockClock implements ClockInterface
{
    private DatePoint $now;

    /**
     * @throws \DateMalformedStringException When $now is invalid
     * @throws \DateInvalidTimeZoneException When $timezone is invalid
     */
    public function __construct(\DateTimeImmutable|string $now = 'now', \DateTimeZone|string|null $timezone = null)
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }

        if (\is_string($now)) {
            $now = new DatePoint($now, $timezone ?? new \DateTimeZone('UTC'));
        } elseif (!$now instanceof DatePoint) {
            $now = DatePoint::createFromInterface($now);
        }

        $this->now = null !== $timezone ? $now->setTimezone($timezone) : $now;
    }

    public function now(): DatePoint
    {
        return clone $this->now;
    }

    public function sleep(float|int $seconds): void
    {
        if (0 >= $seconds) {
            return;
        }

        $now = (float) $this->now->format('Uu') + $seconds * 1e6;
        $now = substr_replace(\sprintf('@%07.0F', $now), '.', -6, 0);
        $timezone = $this->now->getTimezone();

        $this->now = DatePoint::createFromInterface(new \DateTimeImmutable($now, $timezone))->setTimezone($timezone);
    }

    /**
     * @throws \DateMalformedStringException When $modifier is invalid
     */
    public function modify(string $modifier): void
    {
        if (\PHP_VERSION_ID < 80300) {
            $this->now = @$this->now->modify($modifier) ?: throw new \DateMalformedStringException(error_get_last()['message'] ?? \sprintf('Invalid modifier: "%s". Could not modify MockClock.', $modifier));

            return;
        }

        $this->now = $this->now->modify($modifier);
    }

    /**
     * @throws \DateInvalidTimeZoneException When the timezone name is invalid
     */
    public function withTimeZone(\DateTimeZone|string $timezone): static
    {
        if (\PHP_VERSION_ID >= 80300 && \is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        } elseif (\is_string($timezone)) {
            try {
                $timezone = new \DateTimeZone($timezone);
            } catch (\Exception $e) {
                throw new \DateInvalidTimeZoneException($e->getMessage(), $e->getCode(), $e);
            }
        }

        $clone = clone $this;
        $clone->now = $clone->now->setTimezone($timezone);

        return $clone;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

use Symfony\Component\Finder\Comparator\DateComparator;
use Symfony\Component\Finder\Comparator\NumberComparator;
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
use Symfony\Component\Finder\Iterator\CustomFilterIterator;
use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
use Symfony\Component\Finder\Iterator\LazyIterator;
use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
use Symfony\Component\Finder\Iterator\SortableIterator;

/**
 * Finder allows to build rules to find files and directories.
 *
 * It is a thin wrapper around several specialized iterator classes.
 *
 * All rules may be invoked several times.
 *
 * All methods return the current Finder object to allow chaining:
 *
 *     $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<non-empty-string, SplFileInfo>
 */
class Finder implements \IteratorAggregate, \Countable
{
    public const IGNORE_VCS_FILES = 1;
    public const IGNORE_DOT_FILES = 2;
    public const IGNORE_VCS_IGNORED_FILES = 4;

    private int $mode = 0;
    private array $names = [];
    private array $notNames = [];
    private array $exclude = [];
    private array $filters = [];
    private array $pruneFilters = [];
    private array $depths = [];
    private array $sizes = [];
    private bool $followLinks = false;
    private bool $reverseSorting = false;
    private \Closure|int|false $sort = false;
    private int $ignore = 0;
    /** @var list<string> */
    private array $dirs = [];
    private array $dates = [];
    /** @var list<iterable<SplFileInfo|\SplFileInfo|string>> */
    private array $iterators = [];
    private array $contains = [];
    private array $notContains = [];
    private array $paths = [];
    private array $notPaths = [];
    private bool $ignoreUnreadableDirs = false;

    private static array $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'];

    public function __construct()
    {
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
    }

    /**
     * Creates a new Finder.
     */
    public static function create(): static
    {
        return new static();
    }

    /**
     * Restricts the matching to directories only.
     *
     * @return $this
     */
    public function directories(): static
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;

        return $this;
    }

    /**
     * Restricts the matching to files only.
     *
     * @return $this
     */
    public function files(): static
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;

        return $this;
    }

    /**
     * Adds tests for the directory depth.
     *
     * Usage:
     *
     *     $finder->depth('> 1') // the Finder will start matching at level 1.
     *     $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
     *     $finder->depth(['>= 1', '< 3'])
     *
     * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels
     *
     * @return $this
     *
     * @see DepthRangeFilterIterator
     * @see NumberComparator
     */
    public function depth(string|int|array $levels): static
    {
        foreach ((array) $levels as $level) {
            $this->depths[] = new NumberComparator($level);
        }

        return $this;
    }

    /**
     * Adds tests for file dates (last modified).
     *
     * The date must be something that strtotime() is able to parse:
     *
     *     $finder->date('since yesterday');
     *     $finder->date('until 2 days ago');
     *     $finder->date('> now - 2 hours');
     *     $finder->date('>= 2005-10-15');
     *     $finder->date(['>= 2005-10-15', '<= 2006-05-27']);
     *
     * @param string|string[] $dates A date range string or an array of date ranges
     *
     * @return $this
     *
     * @see strtotime
     * @see DateRangeFilterIterator
     * @see DateComparator
     */
    public function date(string|array $dates): static
    {
        foreach ((array) $dates as $date) {
            $this->dates[] = new DateComparator($date);
        }

        return $this;
    }

    /**
     * Adds rules that files must match.
     *
     * You can use patterns (delimited with / sign), globs or simple strings.
     *
     *     $finder->name('/\.php$/')
     *     $finder->name('*.php') // same as above, without dot files
     *     $finder->name('test.php')
     *     $finder->name(['test.py', 'test.php'])
     *
     * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function name(string|array $patterns): static
    {
        $this->names = array_merge($this->names, (array) $patterns);

        return $this;
    }

    /**
     * Adds rules that files must not match.
     *
     * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function notName(string|array $patterns): static
    {
        $this->notNames = array_merge($this->notNames, (array) $patterns);

        return $this;
    }

    /**
     * Adds tests that file contents must match.
     *
     * Strings or PCRE patterns can be used:
     *
     *     $finder->contains('Lorem ipsum')
     *     $finder->contains('/Lorem ipsum/i')
     *     $finder->contains(['dolor', '/ipsum/i'])
     *
     * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
     *
     * @return $this
     *
     * @see FilecontentFilterIterator
     */
    public function contains(string|array $patterns): static
    {
        $this->contains = array_merge($this->contains, (array) $patterns);

        return $this;
    }

    /**
     * Adds tests that file contents must not match.
     *
     * Strings or PCRE patterns can be used:
     *
     *     $finder->notContains('Lorem ipsum')
     *     $finder->notContains('/Lorem ipsum/i')
     *     $finder->notContains(['lorem', '/dolor/i'])
     *
     * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
     *
     * @return $this
     *
     * @see FilecontentFilterIterator
     */
    public function notContains(string|array $patterns): static
    {
        $this->notContains = array_merge($this->notContains, (array) $patterns);

        return $this;
    }

    /**
     * Adds rules that filenames must match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     *     $finder->path('some/special/dir')
     *     $finder->path('/some\/special\/dir/') // same as above
     *     $finder->path(['some dir', 'another/dir'])
     *
     * Use only / as dirname separator.
     *
     * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function path(string|array $patterns): static
    {
        $this->paths = array_merge($this->paths, (array) $patterns);

        return $this;
    }

    /**
     * Adds rules that filenames must not match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     *     $finder->notPath('some/special/dir')
     *     $finder->notPath('/some\/special\/dir/') // same as above
     *     $finder->notPath(['some/file.txt', 'another/file.log'])
     *
     * Use only / as dirname separator.
     *
     * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
     *
     * @return $this
     *
     * @see FilenameFilterIterator
     */
    public function notPath(string|array $patterns): static
    {
        $this->notPaths = array_merge($this->notPaths, (array) $patterns);

        return $this;
    }

    /**
     * Adds tests for file sizes.
     *
     *     $finder->size('> 10K');
     *     $finder->size('<= 1Ki');
     *     $finder->size(4);
     *     $finder->size(['> 10K', '< 20K'])
     *
     * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges
     *
     * @return $this
     *
     * @see SizeRangeFilterIterator
     * @see NumberComparator
     */
    public function size(string|int|array $sizes): static
    {
        foreach ((array) $sizes as $size) {
            $this->sizes[] = new NumberComparator($size);
        }

        return $this;
    }

    /**
     * Excludes directories.
     *
     * Directories passed as argument must be relative to the ones defined with the `in()` method. For example:
     *
     *     $finder->in(__DIR__)->exclude('ruby');
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function exclude(string|array $dirs): static
    {
        $this->exclude = array_merge($this->exclude, (array) $dirs);

        return $this;
    }

    /**
     * Excludes "hidden" directories and files (starting with a dot).
     *
     * This option is enabled by default.
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function ignoreDotFiles(bool $ignoreDotFiles): static
    {
        if ($ignoreDotFiles) {
            $this->ignore |= static::IGNORE_DOT_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_DOT_FILES;
        }

        return $this;
    }

    /**
     * Forces the finder to ignore version control directories.
     *
     * This option is enabled by default.
     *
     * @return $this
     *
     * @see ExcludeDirectoryFilterIterator
     */
    public function ignoreVCS(bool $ignoreVCS): static
    {
        if ($ignoreVCS) {
            $this->ignore |= static::IGNORE_VCS_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_VCS_FILES;
        }

        return $this;
    }

    /**
     * Forces Finder to obey .gitignore and ignore files based on rules listed there.
     *
     * This option is disabled by default.
     *
     * @return $this
     */
    public function ignoreVCSIgnored(bool $ignoreVCSIgnored): static
    {
        if ($ignoreVCSIgnored) {
            $this->ignore |= static::IGNORE_VCS_IGNORED_FILES;
        } else {
            $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES;
        }

        return $this;
    }

    /**
     * Adds VCS patterns.
     *
     * @see ignoreVCS()
     *
     * @param string|string[] $pattern VCS patterns to ignore
     */
    public static function addVCSPattern(string|array $pattern): void
    {
        foreach ((array) $pattern as $p) {
            self::$vcsPatterns[] = $p;
        }

        self::$vcsPatterns = array_unique(self::$vcsPatterns);
    }

    /**
     * Sorts files and directories by an anonymous function.
     *
     * The anonymous function receives two \SplFileInfo instances to compare.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sort(\Closure $closure): static
    {
        $this->sort = $closure;

        return $this;
    }

    /**
     * Sorts files and directories by extension.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByExtension(): static
    {
        $this->sort = SortableIterator::SORT_BY_EXTENSION;

        return $this;
    }

    /**
     * Sorts files and directories by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByName(bool $useNaturalSort = false): static
    {
        $this->sort = $useNaturalSort ? SortableIterator::SORT_BY_NAME_NATURAL : SortableIterator::SORT_BY_NAME;

        return $this;
    }

    /**
     * Sorts files and directories by name case insensitive.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByCaseInsensitiveName(bool $useNaturalSort = false): static
    {
        $this->sort = $useNaturalSort ? SortableIterator::SORT_BY_NAME_NATURAL_CASE_INSENSITIVE : SortableIterator::SORT_BY_NAME_CASE_INSENSITIVE;

        return $this;
    }

    /**
     * Sorts files and directories by size.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortBySize(): static
    {
        $this->sort = SortableIterator::SORT_BY_SIZE;

        return $this;
    }

    /**
     * Sorts files and directories by type (directories before files), then by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByType(): static
    {
        $this->sort = SortableIterator::SORT_BY_TYPE;

        return $this;
    }

    /**
     * Sorts files and directories by the last accessed time.
     *
     * This is the time that the file was last accessed, read or written to.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByAccessedTime(): static
    {
        $this->sort = SortableIterator::SORT_BY_ACCESSED_TIME;

        return $this;
    }

    /**
     * Reverses the sorting.
     *
     * @return $this
     */
    public function reverseSorting(): static
    {
        $this->reverseSorting = true;

        return $this;
    }

    /**
     * Sorts files and directories by the last inode changed time.
     *
     * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
     *
     * On Windows, since inode is not available, changed time is actually the file creation time.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByChangedTime(): static
    {
        $this->sort = SortableIterator::SORT_BY_CHANGED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last modified time.
     *
     * This is the last time the actual contents of the file were last modified.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return $this
     *
     * @see SortableIterator
     */
    public function sortByModifiedTime(): static
    {
        $this->sort = SortableIterator::SORT_BY_MODIFIED_TIME;

        return $this;
    }

    /**
     * Filters the iterator with an anonymous function.
     *
     * The anonymous function receives a \SplFileInfo and must return false
     * to remove files.
     *
     * @param \Closure(SplFileInfo): bool $closure
     * @param bool                        $prune   Whether to skip traversing directories further
     *
     * @return $this
     *
     * @see CustomFilterIterator
     */
    public function filter(\Closure $closure, bool $prune = false): static
    {
        $this->filters[] = $closure;

        if ($prune) {
            $this->pruneFilters[] = $closure;
        }

        return $this;
    }

    /**
     * Forces the following of symlinks.
     *
     * @return $this
     */
    public function followLinks(): static
    {
        $this->followLinks = true;

        return $this;
    }

    /**
     * Tells finder to ignore unreadable directories.
     *
     * By default, scanning unreadable directories content throws an AccessDeniedException.
     *
     * @return $this
     */
    public function ignoreUnreadableDirs(bool $ignore = true): static
    {
        $this->ignoreUnreadableDirs = $ignore;

        return $this;
    }

    /**
     * Searches files and directories which match defined rules.
     *
     * @param string|string[] $dirs A directory path or an array of directories
     *
     * @return $this
     *
     * @throws DirectoryNotFoundException if one of the directories does not exist
     */
    public function in(string|array $dirs): static
    {
        $resolvedDirs = [];

        foreach ((array) $dirs as $dir) {
            if (is_dir($dir)) {
                $resolvedDirs[] = [$this->normalizeDir($dir)];
            } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) {
                sort($glob);
                $resolvedDirs[] = array_map($this->normalizeDir(...), $glob);
            } else {
                throw new DirectoryNotFoundException(\sprintf('The "%s" directory does not exist.', $dir));
            }
        }

        $this->dirs = array_merge($this->dirs, ...$resolvedDirs);

        return $this;
    }

    /**
     * Returns an Iterator for the current Finder configuration.
     *
     * This method implements the IteratorAggregate interface.
     *
     * @return \Iterator<non-empty-string, SplFileInfo>
     *
     * @throws \LogicException if the in() method has not been called
     */
    public function getIterator(): \Iterator
    {
        if (!$this->dirs && !$this->iterators) {
            throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
        }

        if (1 === \count($this->dirs) && !$this->iterators) {
            $iterator = $this->searchInDirectory($this->dirs[0]);
        } else {
            $iterator = new \AppendIterator();
            foreach ($this->dirs as $dir) {
                $iterator->append(new \IteratorIterator(new LazyIterator(fn () => $this->searchInDirectory($dir))));
            }

            foreach ($this->iterators as $it) {
                $iterator->append(new \IteratorIterator(new LazyIterator(static function () use ($it) {
                    foreach ($it as $file) {
                        if (!$file instanceof \SplFileInfo) {
                            $file = new \SplFileInfo($file);
                        }
                        $key = $file->getPathname();
                        if (!$file instanceof SplFileInfo) {
                            $file = new SplFileInfo($key, $file->getPath(), $key);
                        }

                        yield $key => $file;
                    }
                })));
            }
        }

        if ($this->sort || $this->reverseSorting) {
            $iterator = (new SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator();
        }

        return $iterator;
    }

    /**
     * Appends an existing set of files/directories to the finder.
     *
     * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
     *
     * @param iterable<SplFileInfo|\SplFileInfo|string> $iterator
     *
     * @return $this
     */
    public function append(iterable $iterator): static
    {
        $this->iterators[] = $iterator;

        return $this;
    }

    /**
     * Check if any results were found.
     */
    public function hasResults(): bool
    {
        foreach ($this->getIterator() as $_) {
            return true;
        }

        return false;
    }

    /**
     * Counts all the results collected by the iterators.
     */
    public function count(): int
    {
        return iterator_count($this->getIterator());
    }

    private function searchInDirectory(string $dir): \Iterator
    {
        $exclude = $this->exclude;
        $notPaths = $this->notPaths;

        if ($this->pruneFilters) {
            $exclude = array_merge($exclude, $this->pruneFilters);
        }

        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
            $exclude = array_merge($exclude, self::$vcsPatterns);
        }

        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
            $notPaths[] = '#(^|/)\..+(/|$)#';
        }

        $minDepth = 0;
        $maxDepth = \PHP_INT_MAX;

        foreach ($this->depths as $comparator) {
            switch ($comparator->getOperator()) {
                case '>':
                    $minDepth = $comparator->getTarget() + 1;
                    break;
                case '>=':
                    $minDepth = $comparator->getTarget();
                    break;
                case '<':
                    $maxDepth = $comparator->getTarget() - 1;
                    break;
                case '<=':
                    $maxDepth = $comparator->getTarget();
                    break;
                default:
                    $minDepth = $maxDepth = $comparator->getTarget();
            }
        }

        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;

        if ($this->followLinks) {
            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
        }

        $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);

        if ($exclude) {
            $iterator = new ExcludeDirectoryFilterIterator($iterator, $exclude);
        }

        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);

        if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) {
            $iterator = new DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
        }

        if ($this->mode) {
            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
        }

        if ($this->names || $this->notNames) {
            $iterator = new FilenameFilterIterator($iterator, $this->names, $this->notNames);
        }

        if ($this->contains || $this->notContains) {
            $iterator = new FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }

        if ($this->sizes) {
            $iterator = new SizeRangeFilterIterator($iterator, $this->sizes);
        }

        if ($this->dates) {
            $iterator = new DateRangeFilterIterator($iterator, $this->dates);
        }

        if ($this->filters) {
            $iterator = new CustomFilterIterator($iterator, $this->filters);
        }

        if ($this->paths || $notPaths) {
            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
        }

        if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) {
            $iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir);
        }

        return $iterator;
    }

    /**
     * Normalizes given directory names by removing trailing slashes.
     *
     * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper
     */
    private function normalizeDir(string $dir): string
    {
        if ('/' === $dir) {
            return $dir;
        }

        $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR);

        if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
            $dir .= '/';
        }

        return $dir;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Glob matches globbing patterns against text.
 *
 *     if match_glob("foo.*", "foo.bar") echo "matched\n";
 *
 *     // prints foo.bar and foo.baz
 *     $regex = glob_to_regex("foo.*");
 *     for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t)
 *     {
 *         if (/$regex/) echo "matched: $car\n";
 *     }
 *
 * Glob implements glob(3) style matching that can be used to match
 * against text, rather than fetching names from a filesystem.
 *
 * Based on the Perl Text::Glob module.
 *
 * @author Fabien Potencier <fabien@symfony.com> PHP port
 * @author     Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright  2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
 */
class Glob
{
    /**
     * Returns a regexp which is the equivalent of the glob pattern.
     */
    public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#'): string
    {
        $firstByte = true;
        $escaping = false;
        $inCurlies = 0;
        $regex = '';
        if ($unanchored = str_starts_with($glob, '**/')) {
            $glob = '/'.$glob;
        }
        $sizeGlob = \strlen($glob);
        for ($i = 0; $i < $sizeGlob; ++$i) {
            $car = $glob[$i];
            if ($firstByte && $strictLeadingDot && '.' !== $car) {
                $regex .= '(?=[^\.])';
            }

            $firstByte = '/' === $car;

            if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) {
                $car = '[^/]++/';
                if (!isset($glob[$i + 3])) {
                    $car .= '?';
                }

                if ($strictLeadingDot) {
                    $car = '(?=[^\.])'.$car;
                }

                $car = '/(?:'.$car.')*';
                $i += 2 + isset($glob[$i + 3]);

                if ('/' === $delimiter) {
                    $car = str_replace('/', '\\/', $car);
                }
            }

            if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\$car";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = false;
                } else {
                    $escaping = true;
                }

                continue;
            } else {
                $regex .= $car;
            }
            $escaping = false;
        }

        if ($unanchored) {
            $regex = substr_replace($regex, '?', 1 + ('/' === $delimiter) + ($strictLeadingDot ? \strlen('(?=[^\.])') : 0), 0);
        }

        return $delimiter.'^'.$regex.'$'.$delimiter;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AccessDeniedException extends \UnexpectedValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Andreas Erhard <andreas.erhard@i-med.ac.at>
 */
class DirectoryNotFoundException extends \InvalidArgumentException
{
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Gitignore matches against text.
 *
 * @author Michael Voříšek <vorismi3@fel.cvut.cz>
 * @author Ahmed Abdou <mail@ahmd.io>
 */
class Gitignore
{
    /**
     * Returns a regexp which is the equivalent of the gitignore pattern.
     *
     * Format specification: https://git-scm.com/docs/gitignore#_pattern_format
     */
    public static function toRegex(string $gitignoreFileContent): string
    {
        return self::buildRegex($gitignoreFileContent, false);
    }

    public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string
    {
        return self::buildRegex($gitignoreFileContent, true);
    }

    private static function buildRegex(string $gitignoreFileContent, bool $inverted): string
    {
        $gitignoreFileContent = preg_replace('~(?<!\\\\)#[^\n\r]*~', '', $gitignoreFileContent);
        $gitignoreLines = preg_split('~\r\n?|\n~', $gitignoreFileContent);

        $res = self::lineToRegex('');
        foreach ($gitignoreLines as $line) {
            $line = preg_replace('~(?<!\\\\)[ \t]+$~', '', $line);

            if (str_starts_with($line, '!')) {
                $line = substr($line, 1);
                $isNegative = true;
            } else {
                $isNegative = false;
            }

            if ('' !== $line) {
                if ($isNegative xor $inverted) {
                    $res = '(?!'.self::lineToRegex($line).'$)'.$res;
                } else {
                    $res = '(?:'.$res.'|'.self::lineToRegex($line).')';
                }
            }
        }

        return '~^(?:'.$res.')~s';
    }

    private static function lineToRegex(string $gitignoreLine): string
    {
        if ('' === $gitignoreLine) {
            return '$f'; // always false
        }

        $slashPos = strpos($gitignoreLine, '/');
        if (false !== $slashPos && \strlen($gitignoreLine) - 1 !== $slashPos) {
            if (0 === $slashPos) {
                $gitignoreLine = substr($gitignoreLine, 1);
            }
            $isAbsolute = true;
        } else {
            $isAbsolute = false;
        }

        $regex = preg_quote(str_replace('\\', '', $gitignoreLine), '~');
        $regex = preg_replace_callback('~\\\\\[((?:\\\\!)?)([^\[\]]*)\\\\\]~', fn (array $matches): string => '['.('' !== $matches[1] ? '^' : '').str_replace('\\-', '-', $matches[2]).']', $regex);
        $regex = preg_replace('~(?:(?:\\\\\*){2,}(/?))+~', '(?:(?:(?!//).(?<!//))+$1)?', $regex);
        $regex = preg_replace('~\\\\\*~', '[^/]*', $regex);
        $regex = preg_replace('~\\\\\?~', '[^/]', $regex);

        return ($isAbsolute ? '' : '(?:[^/]+/)*')
            .$regex
            .(!str_ends_with($gitignoreLine, '/') ? '(?:$|/)' : '');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Extends \SplFileInfo to support relative paths.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SplFileInfo extends \SplFileInfo
{
    /**
     * @param string $file             The file name
     * @param string $relativePath     The relative path
     * @param string $relativePathname The relative path name
     */
    public function __construct(
        string $file,
        private string $relativePath,
        private string $relativePathname,
    ) {
        parent::__construct($file);
    }

    /**
     * Returns the relative path.
     *
     * This path does not contain the file name.
     */
    public function getRelativePath(): string
    {
        return $this->relativePath;
    }

    /**
     * Returns the relative path name.
     *
     * This path contains the file name.
     */
    public function getRelativePathname(): string
    {
        return $this->relativePathname;
    }

    public function getFilenameWithoutExtension(): string
    {
        $filename = $this->getFilename();

        return pathinfo($filename, \PATHINFO_FILENAME);
    }

    /**
     * Returns the contents of the file.
     *
     * @throws \RuntimeException
     */
    public function getContents(): string
    {
        set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
        try {
            $content = file_get_contents($this->getPathname());
        } finally {
            restore_error_handler();
        }
        if (false === $content) {
            throw new \RuntimeException($error);
        }

        return $content;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * DateCompare compiles date comparisons.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateComparator extends Comparator
{
    /**
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct(string $test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(\sprintf('Don\'t understand "%s" as a date test.', $test));
        }

        try {
            $date = new \DateTimeImmutable($matches[2]);
            $target = $date->format('U');
        } catch (\Exception) {
            throw new \InvalidArgumentException(\sprintf('"%s" is not a valid date.', $matches[2]));
        }

        $operator = $matches[1] ?: '==';
        if ('since' === $operator || 'after' === $operator) {
            $operator = '>';
        }

        if ('until' === $operator || 'before' === $operator) {
            $operator = '<';
        }

        parent::__construct($target, $operator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * NumberComparator compiles a simple comparison to an anonymous
 * subroutine, which you can call with a value to be tested again.
 *
 * Now this would be very pointless, if NumberCompare didn't understand
 * magnitudes.
 *
 * The target value may use magnitudes of kilobytes (k, ki),
 * megabytes (m, mi), or gigabytes (g, gi). Those suffixed
 * with an i use the appropriate 2**n version in accordance with the
 * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
 *
 * Based on the Perl Number::Compare module.
 *
 * @author    Fabien Potencier <fabien@symfony.com> PHP port
 * @author    Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
 *
 * @see http://physics.nist.gov/cuu/Units/binary.html
 */
class NumberComparator extends Comparator
{
    /**
     * @param string|null $test A comparison string or null
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct(?string $test)
    {
        if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(\sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null'));
        }

        $target = $matches[2];
        if (!is_numeric($target)) {
            throw new \InvalidArgumentException(\sprintf('Invalid number "%s".', $target));
        }
        if (isset($matches[3])) {
            // magnitude
            switch (strtolower($matches[3])) {
                case 'k':
                    $target *= 1000;
                    break;
                case 'ki':
                    $target *= 1024;
                    break;
                case 'm':
                    $target *= 1000000;
                    break;
                case 'mi':
                    $target *= 1024 * 1024;
                    break;
                case 'g':
                    $target *= 1000000000;
                    break;
                case 'gi':
                    $target *= 1024 * 1024 * 1024;
                    break;
            }
        }

        parent::__construct($target, $matches[1] ?: '==');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Comparator
{
    private string $operator;

    public function __construct(
        private string $target,
        string $operator = '==',
    ) {
        if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='], true)) {
            throw new \InvalidArgumentException(\sprintf('Invalid operator "%s".', $operator));
        }

        $this->operator = $operator;
    }

    /**
     * Gets the target value.
     */
    public function getTarget(): string
    {
        return $this->target;
    }

    /**
     * Gets the comparison operator.
     */
    public function getOperator(): string
    {
        return $this->operator;
    }

    /**
     * Tests against the target.
     */
    public function test(mixed $test): bool
    {
        return match ($this->operator) {
            '>' => $test > $this->target,
            '>=' => $test >= $this->target,
            '<' => $test < $this->target,
            '<=' => $test <= $this->target,
            '!=' => $test != $this->target,
            default => $test == $this->target,
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\SplFileInfo;

/**
 * ExcludeDirectoryFilterIterator filters out directories.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, SplFileInfo>
 *
 * @implements \RecursiveIterator<string, SplFileInfo>
 */
class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator
{
    /** @var \Iterator<string, SplFileInfo> */
    private \Iterator $iterator;
    private bool $isRecursive;
    /** @var array<string, true> */
    private array $excludedDirs = [];
    private ?string $excludedPattern = null;
    /** @var list<callable(SplFileInfo):bool> */
    private array $pruneFilters = [];

    /**
     * @param \Iterator<string, SplFileInfo>          $iterator    The Iterator to filter
     * @param list<string|callable(SplFileInfo):bool> $directories An array of directories to exclude
     */
    public function __construct(\Iterator $iterator, array $directories)
    {
        $this->iterator = $iterator;
        $this->isRecursive = $iterator instanceof \RecursiveIterator;
        $patterns = [];
        foreach ($directories as $directory) {
            if (!\is_string($directory)) {
                if (!\is_callable($directory)) {
                    throw new \InvalidArgumentException('Invalid PHP callback.');
                }

                $this->pruneFilters[] = $directory;

                continue;
            }

            $directory = rtrim($directory, '/');
            if (!$this->isRecursive || str_contains($directory, '/')) {
                $patterns[] = preg_quote($directory, '#');
            } else {
                $this->excludedDirs[$directory] = true;
            }
        }
        if ($patterns) {
            $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
        }

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        if ($this->isRecursive && isset($this->excludedDirs[$this->current()->getFilename()]) && $this->current()->isDir()) {
            return false;
        }

        if ($this->excludedPattern) {
            $path = $this->current()->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
            $path = str_replace('\\', '/', $path);

            return !preg_match($this->excludedPattern, $path);
        }

        if ($this->pruneFilters && $this->hasChildren()) {
            foreach ($this->pruneFilters as $pruneFilter) {
                if (!$pruneFilter($this->current())) {
                    return false;
                }
            }
        }

        return true;
    }

    public function hasChildren(): bool
    {
        return $this->isRecursive && $this->iterator->hasChildren();
    }

    public function getChildren(): self
    {
        $children = new self($this->iterator->getChildren(), []);
        $children->excludedDirs = $this->excludedDirs;
        $children->excludedPattern = $this->excludedPattern;

        return $children;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * @author Jérémy Derussé <jeremy@derusse.com>
 *
 * @internal
 */
class LazyIterator implements \IteratorAggregate
{
    private \Closure $iteratorFactory;

    public function __construct(callable $iteratorFactory)
    {
        $this->iteratorFactory = $iteratorFactory(...);
    }

    public function getIterator(): \Traversable
    {
        yield from ($this->iteratorFactory)();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\SplFileInfo;

/**
 * Extends the \RecursiveDirectoryIterator to support relative paths.
 *
 * @author Victor Berchet <victor@suumit.com>
 *
 * @extends \RecursiveDirectoryIterator<string, SplFileInfo>
 */
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
    private bool $ignoreUnreadableDirs;
    private bool $ignoreFirstRewind = true;

    // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
    private string $rootPath;
    private string $subPath;
    private string $directorySeparator = '/';

    /**
     * @throws \RuntimeException
     */
    public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false)
    {
        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
        }

        parent::__construct($path, $flags);
        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
        $this->rootPath = $path;
        if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
            $this->directorySeparator = \DIRECTORY_SEPARATOR;
        }
    }

    /**
     * Return an instance of SplFileInfo with support for relative paths.
     */
    public function current(): SplFileInfo
    {
        // the logic here avoids redoing the same work in all iterations

        if (!isset($this->subPath)) {
            $this->subPath = $this->getSubPath();
        }
        $subPathname = $this->subPath;
        if ('' !== $subPathname) {
            $subPathname .= $this->directorySeparator;
        }
        $subPathname .= $this->getFilename();
        $basePath = $this->rootPath;

        if ('/' !== $basePath && !str_ends_with($basePath, $this->directorySeparator) && !str_ends_with($basePath, '/')) {
            $basePath .= $this->directorySeparator;
        }

        return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname);
    }

    public function hasChildren(bool $allowLinks = false): bool
    {
        $hasChildren = parent::hasChildren($allowLinks);

        if (!$hasChildren || !$this->ignoreUnreadableDirs) {
            return $hasChildren;
        }

        try {
            parent::getChildren();

            return true;
        } catch (\UnexpectedValueException) {
            // If directory is unreadable and finder is set to ignore it, skip children
            return false;
        }
    }

    /**
     * @throws AccessDeniedException
     */
    public function getChildren(): \RecursiveDirectoryIterator
    {
        try {
            $children = parent::getChildren();

            if ($children instanceof self) {
                // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
                $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;

                // performance optimization to avoid redoing the same work in all children
                $children->rootPath = $this->rootPath;
            }

            return $children;
        } catch (\UnexpectedValueException $e) {
            throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
        }
    }

    public function next(): void
    {
        $this->ignoreFirstRewind = false;

        parent::next();
    }

    public function rewind(): void
    {
        // some streams like FTP are not rewindable, ignore the first rewind after creation,
        // as newly created DirectoryIterator does not need to be rewound
        if ($this->ignoreFirstRewind) {
            $this->ignoreFirstRewind = false;

            return;
        }

        parent::rewind();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @template-covariant TKey
 * @template-covariant TValue
 *
 * @extends \FilterIterator<TKey, TValue>
 */
abstract class MultiplePcreFilterIterator extends \FilterIterator
{
    protected array $matchRegexps = [];
    protected array $noMatchRegexps = [];

    /**
     * @param \Iterator<TKey, TValue> $iterator        The Iterator to filter
     * @param string[]                $matchPatterns   An array of patterns that need to match
     * @param string[]                $noMatchPatterns An array of patterns that need to not match
     */
    public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
    {
        foreach ($matchPatterns as $pattern) {
            $this->matchRegexps[] = $this->toRegex($pattern);
        }

        foreach ($noMatchPatterns as $pattern) {
            $this->noMatchRegexps[] = $this->toRegex($pattern);
        }

        parent::__construct($iterator);
    }

    /**
     * Checks whether the string is accepted by the regex filters.
     *
     * If there is no regexps defined in the class, this method will accept the string.
     * Such case can be handled by child classes before calling the method if they want to
     * apply a different behavior.
     */
    protected function isAccepted(string $string): bool
    {
        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $string)) {
                return false;
            }
        }

        // should at least match one rule
        if ($this->matchRegexps) {
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $string)) {
                    return true;
                }
            }

            return false;
        }

        // If there is no match rules, the file is accepted
        return true;
    }

    /**
     * Checks whether the string is a regex.
     */
    protected function isRegex(string $str): bool
    {
        $availableModifiers = 'imsxuADUn';

        if (preg_match('/^(.{3,}?)['.$availableModifiers.']*$/', $str, $m)) {
            $start = substr($m[1], 0, 1);
            $end = substr($m[1], -1);

            if ($start === $end) {
                return !preg_match('/[*?[:alnum:] \\\\]/', $start);
            }

            foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) {
                if ($start === $delimiters[0] && $end === $delimiters[1]) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Converts string into regexp.
     */
    abstract protected function toRegex(string $str): string;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Comparator\DateComparator;

/**
 * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class DateRangeFilterIterator extends \FilterIterator
{
    private array $comparators = [];

    /**
     * @param \Iterator<string, \SplFileInfo> $iterator
     * @param DateComparator[]                $comparators
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();

        if (!file_exists($fileinfo->getPathname())) {
            return false;
        }

        $filedate = $fileinfo->getMTime();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filedate)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * FileTypeFilterIterator only keeps files, directories, or both.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class FileTypeFilterIterator extends \FilterIterator
{
    public const ONLY_FILES = 1;
    public const ONLY_DIRECTORIES = 2;

    /**
     * @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter
     * @param int                             $mode     The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
     */
    public function __construct(
        \Iterator $iterator,
        private int $mode,
    ) {
        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();
        if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
            return false;
        } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
            return false;
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\SplFileInfo;

/**
 * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 *
 * @extends MultiplePcreFilterIterator<string, SplFileInfo>
 */
class PathFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $filename = $this->current()->getRelativePathname();

        if ('\\' === \DIRECTORY_SEPARATOR) {
            $filename = str_replace('\\', '/', $filename);
        }

        return $this->isAccepted($filename);
    }

    /**
     * Converts strings to regexp.
     *
     * PCRE patterns are left unchanged.
     *
     * Default conversion:
     *     'lorem/ipsum/dolor' ==>  'lorem\/ipsum\/dolor/'
     *
     * Use only / as directory separator (on Windows also).
     *
     * @param string $str Pattern: regexp or dirname
     */
    protected function toRegex(string $str): string
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * SortableIterator applies a sort on a given Iterator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, \SplFileInfo>
 */
class SortableIterator implements \IteratorAggregate
{
    public const SORT_BY_NONE = 0;
    public const SORT_BY_NAME = 1;
    public const SORT_BY_TYPE = 2;
    public const SORT_BY_ACCESSED_TIME = 3;
    public const SORT_BY_CHANGED_TIME = 4;
    public const SORT_BY_MODIFIED_TIME = 5;
    public const SORT_BY_NAME_NATURAL = 6;
    public const SORT_BY_NAME_CASE_INSENSITIVE = 7;
    public const SORT_BY_NAME_NATURAL_CASE_INSENSITIVE = 8;
    public const SORT_BY_EXTENSION = 9;
    public const SORT_BY_SIZE = 10;

    /** @var \Traversable<string, \SplFileInfo> */
    private \Traversable $iterator;
    private \Closure|int $sort;

    /**
     * @param \Traversable<string, \SplFileInfo> $iterator
     * @param int|callable                       $sort     The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Traversable $iterator, int|callable $sort, bool $reverseOrder = false)
    {
        $this->iterator = $iterator;
        $order = $reverseOrder ? -1 : 1;

        if (self::SORT_BY_NAME === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_NAME_NATURAL === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_NAME_CASE_INSENSITIVE === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strcasecmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_NAME_NATURAL_CASE_INSENSITIVE === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcasecmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
        } elseif (self::SORT_BY_TYPE === $sort) {
            $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) {
                if ($a->isDir() && $b->isFile()) {
                    return -$order;
                } elseif ($a->isFile() && $b->isDir()) {
                    return $order;
                }

                return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
            };
        } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getATime() - $b->getATime());
        } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getCTime() - $b->getCTime());
        } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getMTime() - $b->getMTime());
        } elseif (self::SORT_BY_EXTENSION === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * strnatcmp($a->getExtension(), $b->getExtension());
        } elseif (self::SORT_BY_SIZE === $sort) {
            $this->sort = static fn (\SplFileInfo $a, \SplFileInfo $b) => $order * ($a->getSize() - $b->getSize());
        } elseif (self::SORT_BY_NONE === $sort) {
            $this->sort = $order;
        } elseif (\is_callable($sort)) {
            $this->sort = $reverseOrder ? static fn (\SplFileInfo $a, \SplFileInfo $b) => -$sort($a, $b) : $sort(...);
        } else {
            throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
        }
    }

    public function getIterator(): \Traversable
    {
        if (1 === $this->sort) {
            yield from $this->iterator;

            return;
        }

        $keys = $values = [];
        foreach ($this->iterator as $key => $value) {
            $keys[] = $key;
            $values[] = $value;
        }

        if (-1 === $this->sort) {
            for ($i = \count($values) - 1; $i >= 0; --$i) {
                yield $keys[$i] => $values[$i];
            }

            return;
        }

        uasort($values, $this->sort);

        foreach ($values as $i => $v) {
            yield $keys[$i] => $v;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Gitignore;

/**
 * @extends \FilterIterator<string, \SplFileInfo>
 */
final class VcsIgnoredFilterIterator extends \FilterIterator
{
    private string $baseDir;

    /**
     * @var array<string, array{0: string, 1: string}|null>
     */
    private array $gitignoreFilesCache = [];

    /**
     * @var array<string, bool>
     */
    private array $ignoredPathsCache = [];

    /**
     * @param \Iterator<string, \SplFileInfo> $iterator
     */
    public function __construct(\Iterator $iterator, string $baseDir)
    {
        $this->baseDir = $this->normalizePath($baseDir);

        foreach ([$this->baseDir, ...$this->parentDirectoriesUpwards($this->baseDir)] as $directory) {
            if (@is_dir("{$directory}/.git")) {
                $this->baseDir = $directory;
                break;
            }
        }

        parent::__construct($iterator);
    }

    public function accept(): bool
    {
        $file = $this->current();

        $fileRealPath = $this->normalizePath($file->getRealPath());

        return !$this->isIgnored($fileRealPath);
    }

    private function isIgnored(string $fileRealPath): bool
    {
        if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) {
            $fileRealPath .= '/';
        }

        if (isset($this->ignoredPathsCache[$fileRealPath])) {
            return $this->ignoredPathsCache[$fileRealPath];
        }

        $ignored = false;

        foreach ($this->parentDirectoriesDownwards($fileRealPath) as $parentDirectory) {
            if ($this->isIgnored($parentDirectory)) {
                // rules in ignored directories are ignored, no need to check further.
                break;
            }

            $fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1);

            if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) {
                continue;
            }

            [$exclusionRegex, $inclusionRegex] = $regexps;

            if (preg_match($exclusionRegex, $fileRelativePath)) {
                $ignored = true;

                continue;
            }

            if (preg_match($inclusionRegex, $fileRelativePath)) {
                $ignored = false;
            }
        }

        return $this->ignoredPathsCache[$fileRealPath] = $ignored;
    }

    /**
     * @return list<string>
     */
    private function parentDirectoriesUpwards(string $from): array
    {
        $parentDirectories = [];

        $parentDirectory = $from;

        while (true) {
            $newParentDirectory = \dirname($parentDirectory);

            // dirname('/') = '/'
            if ($newParentDirectory === $parentDirectory) {
                break;
            }

            $parentDirectories[] = $parentDirectory = $newParentDirectory;
        }

        return $parentDirectories;
    }

    private function parentDirectoriesUpTo(string $from, string $upTo): array
    {
        return array_filter(
            $this->parentDirectoriesUpwards($from),
            static fn (string $directory): bool => str_starts_with($directory, $upTo)
        );
    }

    /**
     * @return list<string>
     */
    private function parentDirectoriesDownwards(string $fileRealPath): array
    {
        return array_reverse(
            $this->parentDirectoriesUpTo($fileRealPath, $this->baseDir)
        );
    }

    /**
     * @return array{0: string, 1: string}|null
     */
    private function readGitignoreFile(string $path): ?array
    {
        if (\array_key_exists($path, $this->gitignoreFilesCache)) {
            return $this->gitignoreFilesCache[$path];
        }

        if (!file_exists($path)) {
            return $this->gitignoreFilesCache[$path] = null;
        }

        if (!is_file($path) || !is_readable($path)) {
            throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable.");
        }

        $gitignoreFileContent = file_get_contents($path);

        return $this->gitignoreFilesCache[$path] = [
            Gitignore::toRegex($gitignoreFileContent),
            Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent),
        ];
    }

    private function normalizePath(string $path): string
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return str_replace('\\', '/', $path);
        }

        return $path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Comparator\NumberComparator;

/**
 * SizeRangeFilterIterator filters out files that are not in the given size range.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class SizeRangeFilterIterator extends \FilterIterator
{
    private array $comparators = [];

    /**
     * @param \Iterator<string, \SplFileInfo> $iterator
     * @param NumberComparator[]              $comparators
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();
        if (!$fileinfo->isFile()) {
            return true;
        }

        $filesize = $fileinfo->getSize();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filesize)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Glob;

/**
 * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends MultiplePcreFilterIterator<string, \SplFileInfo>
 */
class FilenameFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        return $this->isAccepted($this->current()->getFilename());
    }

    /**
     * Converts glob to regexp.
     *
     * PCRE patterns are left unchanged.
     * Glob strings are transformed with Glob::toRegex().
     *
     * @param string $str Pattern: glob or regexp
     */
    protected function toRegex(string $str): string
    {
        return $this->isRegex($str) ? $str : Glob::toRegex($str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * DepthRangeFilterIterator limits the directory depth.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @template-covariant TKey
 * @template-covariant TValue
 *
 * @extends \FilterIterator<TKey, TValue>
 */
class DepthRangeFilterIterator extends \FilterIterator
{
    private int $minDepth = 0;

    /**
     * @param \RecursiveIteratorIterator<\RecursiveIterator<TKey, TValue>> $iterator The Iterator to filter
     * @param int                                                          $minDepth The min depth
     * @param int                                                          $maxDepth The max depth
     */
    public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = \PHP_INT_MAX)
    {
        $this->minDepth = $minDepth;
        $iterator->setMaxDepth(\PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        return $this->getInnerIterator()->getDepth() >= $this->minDepth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\SplFileInfo;

/**
 * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 *
 * @extends MultiplePcreFilterIterator<string, SplFileInfo>
 */
class FilecontentFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        if (!$this->matchRegexps && !$this->noMatchRegexps) {
            return true;
        }

        $fileinfo = $this->current();

        if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
            return false;
        }

        $content = $fileinfo->getContents();
        if (!$content) {
            return false;
        }

        return $this->isAccepted($content);
    }

    /**
     * Converts string to regexp if necessary.
     *
     * @param string $str Pattern: string or regexp
     */
    protected function toRegex(string $str): string
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * CustomFilterIterator filters files by applying anonymous functions.
 *
 * The anonymous function receives a \SplFileInfo and must return false
 * to remove files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @extends \FilterIterator<string, \SplFileInfo>
 */
class CustomFilterIterator extends \FilterIterator
{
    private array $filters = [];

    /**
     * @param \Iterator<string, \SplFileInfo> $iterator The Iterator to filter
     * @param callable[]                      $filters  An array of PHP callbacks
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Iterator $iterator, array $filters)
    {
        foreach ($filters as $filter) {
            if (!\is_callable($filter)) {
                throw new \InvalidArgumentException('Invalid PHP callback.');
            }
        }
        $this->filters = $filters;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     */
    public function accept(): bool
    {
        $fileinfo = $this->current();

        foreach ($this->filters as $filter) {
            if (false === $filter($fileinfo)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * An executable finder specifically designed for the PHP executable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PhpExecutableFinder
{
    private ExecutableFinder $executableFinder;

    public function __construct()
    {
        $this->executableFinder = new ExecutableFinder();
    }

    /**
     * Finds The PHP executable.
     */
    public function find(bool $includeArgs = true): string|false
    {
        if ($php = getenv('PHP_BINARY')) {
            if (!is_executable($php) && !$php = $this->executableFinder->find($php)) {
                return false;
            }

            if (@is_dir($php)) {
                return false;
            }

            return $php;
        }

        $args = $this->findArguments();
        $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';

        // PHP_BINARY return the current sapi executable
        if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cli', 'cli-server', 'phpdbg'], true)) {
            return \PHP_BINARY.$args;
        }

        if ($php = getenv('PHP_PATH')) {
            if (!@is_executable($php) || @is_dir($php)) {
                return false;
            }

            return $php;
        }

        if ($php = getenv('PHP_PEAR_PHP_BIN')) {
            if (@is_executable($php) && !@is_dir($php)) {
                return $php;
            }
        }

        if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) {
            return $php;
        }

        $dirs = [\PHP_BINDIR];
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $dirs[] = 'C:\xampp\php\\';
        }

        if ($herdPath = getenv('HERD_HOME')) {
            $dirs[] = $herdPath.\DIRECTORY_SEPARATOR.'bin';
        }

        return $this->executableFinder->find('php', false, $dirs);
    }

    /**
     * Finds the PHP executable arguments.
     *
     * @return list<non-empty-string>
     */
    public function findArguments(): array
    {
        $arguments = [];
        if ('phpdbg' === \PHP_SAPI) {
            $arguments[] = '-qrr';
        }

        return $arguments;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\RuntimeException;

/**
 * Provides a way to continuously write to the input of a Process until the InputStream is closed.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @implements \IteratorAggregate<int, string>
 */
class InputStream implements \IteratorAggregate
{
    private ?\Closure $onEmpty = null;
    private array $input = [];
    private bool $open = true;

    /**
     * Sets a callback that is called when the write buffer becomes empty.
     */
    public function onEmpty(?callable $onEmpty = null): void
    {
        $this->onEmpty = null !== $onEmpty ? $onEmpty(...) : null;
    }

    /**
     * Appends an input to the write buffer.
     *
     * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar,
     *                                                                stream resource or \Traversable
     */
    public function write(mixed $input): void
    {
        if (null === $input) {
            return;
        }
        if ($this->isClosed()) {
            throw new RuntimeException(\sprintf('"%s" is closed.', static::class));
        }
        $this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
    }

    /**
     * Closes the write buffer.
     */
    public function close(): void
    {
        $this->open = false;
    }

    /**
     * Tells whether the write buffer is closed or not.
     */
    public function isClosed(): bool
    {
        return !$this->open;
    }

    public function getIterator(): \Traversable
    {
        $this->open = true;

        while ($this->open || $this->input) {
            if (!$this->input) {
                yield '';
                continue;
            }
            $current = array_shift($this->input);

            if ($current instanceof \Iterator) {
                yield from $current;
            } else {
                yield $current;
            }
            if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) {
                $this->write($onEmpty($this));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception that is thrown when a process has been signaled.
 *
 * @author Sullivan Senechal <soullivaneuh@gmail.com>
 */
final class ProcessSignaledException extends RuntimeException
{
    public function __construct(
        private Process $process,
    ) {
        parent::__construct(\sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
    }

    public function getProcess(): Process
    {
        return $this->process;
    }

    public function getSignal(): int
    {
        return $this->getProcess()->getTermSignal();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * Marker Interface for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception for processes failed during startup.
 */
class ProcessStartFailedException extends ProcessFailedException
{
    public function __construct(
        private Process $process,
        ?string $message,
    ) {
        if ($process->isStarted()) {
            throw new InvalidArgumentException('Expected a process that failed during startup, but the given process was started successfully.');
        }

        $error = \sprintf('The command "%s" failed.'."\n\nWorking directory: %s\n\nError: %s",
            $process->getCommandLine(),
            $process->getWorkingDirectory(),
            $message ?? 'unknown'
        );

        // Skip parent constructor
        RuntimeException::__construct($error);
    }

    public function getProcess(): Process
    {
        return $this->process;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * InvalidArgumentException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Messenger\RunProcessContext;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunProcessFailedException extends RuntimeException
{
    public function __construct(ProcessFailedException $exception, public readonly RunProcessContext $context)
    {
        parent::__construct($exception->getMessage(), $exception->getCode());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception that is thrown when a process times out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessTimedOutException extends RuntimeException
{
    public const TYPE_GENERAL = 1;
    public const TYPE_IDLE = 2;

    public function __construct(
        private Process $process,
        private int $timeoutType,
    ) {
        parent::__construct(\sprintf(
            'The process "%s" exceeded the timeout of %s seconds.',
            $process->getCommandLine(),
            $this->getExceededTimeout()
        ));
    }

    public function getProcess(): Process
    {
        return $this->process;
    }

    public function isGeneralTimeout(): bool
    {
        return self::TYPE_GENERAL === $this->timeoutType;
    }

    public function isIdleTimeout(): bool
    {
        return self::TYPE_IDLE === $this->timeoutType;
    }

    public function getExceededTimeout(): ?float
    {
        return match ($this->timeoutType) {
            self::TYPE_GENERAL => $this->process->getTimeout(),
            self::TYPE_IDLE => $this->process->getIdleTimeout(),
            default => throw new \LogicException(\sprintf('Unknown timeout type "%d".', $this->timeoutType)),
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * LogicException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception for failed processes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessFailedException extends RuntimeException
{
    public function __construct(
        private Process $process,
    ) {
        if ($process->isSuccessful()) {
            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
        }

        $error = \sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
            $process->getCommandLine(),
            $process->getExitCode(),
            $process->getExitCodeText(),
            $process->getWorkingDirectory()
        );

        if (!$process->isOutputDisabled()) {
            $error .= \sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
                $process->getOutput(),
                $process->getErrorOutput()
            );
        }

        parent::__construct($error);

        $this->process = $process;
    }

    public function getProcess(): Process
    {
        return $this->process;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * RuntimeException for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
Copyright (c) 2004-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * Generic executable finder.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ExecutableFinder
{
    private const CMD_BUILTINS = [
        'assoc', 'break', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date',
        'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype', 'goto',
        'help', 'if', 'label', 'md', 'mkdir', 'mklink', 'move', 'path', 'pause',
        'popd', 'prompt', 'pushd', 'rd', 'rem', 'ren', 'rename', 'rmdir', 'set',
        'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver', 'vol',
    ];

    private array $suffixes = [];

    /**
     * Replaces default suffixes of executable.
     */
    public function setSuffixes(array $suffixes): void
    {
        $this->suffixes = $suffixes;
    }

    /**
     * Adds new possible suffix to check for executable, including the dot (.).
     *
     *     $finder = new ExecutableFinder();
     *     $finder->addSuffix('.foo');
     */
    public function addSuffix(string $suffix): void
    {
        $this->suffixes[] = $suffix;
    }

    /**
     * Finds an executable by name.
     *
     * @param string      $name      The executable name (without the extension)
     * @param string|null $default   The default to return if no executable is found
     * @param array       $extraDirs Additional dirs to check into
     */
    public function find(string $name, ?string $default = null, array $extraDirs = []): ?string
    {
        // windows built-in commands that are present in cmd.exe should not be resolved using PATH as they do not exist as exes
        if ('\\' === \DIRECTORY_SEPARATOR && \in_array(strtolower($name), self::CMD_BUILTINS, true)) {
            return $name;
        }

        $dirs = array_merge(
            explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path') ?: ''),
            $extraDirs
        );

        $suffixes = $this->suffixes;
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $pathExt = getenv('PATHEXT') ?: '';
            $suffixes = array_merge($suffixes, $pathExt ? explode(\PATH_SEPARATOR, $pathExt) : ['.exe', '.bat', '.cmd', '.com']);
        }
        $suffixes = '' !== pathinfo($name, \PATHINFO_EXTENSION) ? array_merge([''], $suffixes) : array_merge($suffixes, ['']);
        foreach ($suffixes as $suffix) {
            foreach ($dirs as $dir) {
                if ('' === $dir) {
                    $dir = '.';
                }
                if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) {
                    return $file;
                }

                if (!@is_dir($dir) && basename($dir) === $name.$suffix && @is_executable($dir)) {
                    return $dir;
                }
            }
        }

        if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('exec') || \strlen($name) !== strcspn($name, '/'.\DIRECTORY_SEPARATOR)) {
            return $default;
        }

        $execResult = exec('command -v -- '.escapeshellarg($name));

        if (($executablePath = substr($execResult, 0, strpos($execResult, \PHP_EOL) ?: null)) && @is_executable($executablePath)) {
            return $executablePath;
        }

        return $default;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Messenger;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class RunProcessMessage implements \Stringable
{
    public ?string $commandLine = null;

    public function __construct(
        public readonly array $command,
        public readonly ?string $cwd = null,
        public readonly ?array $env = null,
        public readonly mixed $input = null,
        public readonly ?float $timeout = 60.0,
    ) {
    }

    public function __toString(): string
    {
        return $this->commandLine ?? implode(' ', $this->command);
    }

    /**
     * Create a process message instance that will instantiate a Process using the fromShellCommandline method.
     *
     * @see Process::fromShellCommandline
     */
    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): self
    {
        $message = new self([], $cwd, $env, $input, $timeout);
        $message->commandLine = $command;

        return $message;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Messenger;

use Symfony\Component\Process\Process;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunProcessContext
{
    public readonly ?int $exitCode;
    public readonly ?string $output;
    public readonly ?string $errorOutput;

    public function __construct(
        public readonly RunProcessMessage $message,
        Process $process,
    ) {
        $this->exitCode = $process->getExitCode();
        $this->output = !$process->isStarted() || $process->isOutputDisabled() ? null : $process->getOutput();
        $this->errorOutput = !$process->isStarted() || $process->isOutputDisabled() ? null : $process->getErrorOutput();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Messenger;

use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Exception\RunProcessFailedException;
use Symfony\Component\Process\Process;

/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
final class RunProcessMessageHandler
{
    public function __invoke(RunProcessMessage $message): RunProcessContext
    {
        $process = match ($message->commandLine) {
            null => new Process($message->command, $message->cwd, $message->env, $message->input, $message->timeout),
            default => Process::fromShellCommandline($message->commandLine, $message->cwd, $message->env, $message->input, $message->timeout),
        };

        try {
            return new RunProcessContext($message, $process->mustRun());
        } catch (ProcessFailedException $e) {
            throw new RunProcessFailedException($e, new RunProcessContext($message, $e->getProcess()));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\RuntimeException;

/**
 * PhpProcess runs a PHP script in an independent process.
 *
 *     $p = new PhpProcess('<?php echo "foo"; ?>');
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpProcess extends Process
{
    /**
     * @param string      $script  The PHP script to run (as a string)
     * @param string|null $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null  $env     The environment variables or null to use the same environment as the current PHP process
     * @param int         $timeout The timeout in seconds
     * @param array|null  $php     Path to the PHP binary to use with any additional arguments
     */
    public function __construct(string $script, ?string $cwd = null, ?array $env = null, int $timeout = 60, ?array $php = null)
    {
        if (null === $php) {
            $executableFinder = new PhpExecutableFinder();
            $php = $executableFinder->find(false);
            $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments());
        }
        if ('phpdbg' === \PHP_SAPI) {
            $file = tempnam(sys_get_temp_dir(), 'dbg');
            file_put_contents($file, $script);
            register_shutdown_function('unlink', $file);
            $php[] = $file;
            $script = null;
        }

        parent::__construct($php, $cwd, $env, $script, $timeout);
    }

    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
    {
        throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
    }

    /**
     * @param (callable('out'|'err', string):void)|null $callback
     */
    public function start(?callable $callback = null, array $env = []): void
    {
        if (null === $this->getCommandLine()) {
            throw new RuntimeException('Unable to find the PHP executable.');
        }

        parent::start($callback, $env);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Pipes;

use Symfony\Component\Process\Exception\InvalidArgumentException;

/**
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
abstract class AbstractPipes implements PipesInterface
{
    public array $pipes = [];

    private string $inputBuffer = '';
    /** @var resource|string|\Iterator */
    private $input;
    private bool $blocked = true;
    private ?string $lastError = null;

    /**
     * @param resource|string|\Iterator $input
     */
    public function __construct($input)
    {
        if (\is_resource($input) || $input instanceof \Iterator) {
            $this->input = $input;
        } else {
            $this->inputBuffer = (string) $input;
        }
    }

    public function close(): void
    {
        foreach ($this->pipes as $pipe) {
            if (\is_resource($pipe)) {
                fclose($pipe);
            }
        }
        $this->pipes = [];
    }

    /**
     * Returns true if a system call has been interrupted.
     *
     * stream_select() returns false when the `select` system call is interrupted by an incoming signal.
     */
    protected function hasSystemCallBeenInterrupted(): bool
    {
        $lastError = $this->lastError;
        $this->lastError = null;

        if (null === $lastError) {
            return false;
        }

        if (false !== stripos($lastError, 'interrupted system call')) {
            return true;
        }

        // on applications with a different locale than english, the message above is not found because
        // it's translated. So we also check for the SOCKET_EINTR constant which is defined under
        // Windows and UNIX-like platforms (if available on the platform).
        return \defined('SOCKET_EINTR') && str_starts_with($lastError, 'stream_select(): Unable to select ['.\SOCKET_EINTR.']');
    }

    /**
     * Unblocks streams.
     */
    protected function unblock(): void
    {
        if (!$this->blocked) {
            return;
        }

        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, false);
        }
        if (\is_resource($this->input)) {
            stream_set_blocking($this->input, false);
        }

        $this->blocked = false;
    }

    /**
     * Writes input to stdin.
     *
     * @throws InvalidArgumentException When an input iterator yields a non supported value
     */
    protected function write(): ?array
    {
        if (!isset($this->pipes[0])) {
            return null;
        }
        $input = $this->input;

        if ($input instanceof \Iterator) {
            if (!$input->valid()) {
                $input = null;
            } elseif (\is_resource($input = $input->current())) {
                stream_set_blocking($input, false);
            } elseif (!isset($this->inputBuffer[0])) {
                if (!\is_string($input)) {
                    if (!\is_scalar($input)) {
                        throw new InvalidArgumentException(\sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input)));
                    }
                    $input = (string) $input;
                }
                $this->inputBuffer = $input;
                $this->input->next();
                $input = null;
            } else {
                $input = null;
            }
        }

        $r = $e = [];
        $w = [$this->pipes[0]];

        // let's have a look if something changed in streams
        if (false === @stream_select($r, $w, $e, 0, 0)) {
            return null;
        }

        foreach ($w as $stdin) {
            if (isset($this->inputBuffer[0])) {
                if (false === $written = @fwrite($stdin, $this->inputBuffer)) {
                    return $this->closeBrokenInputPipe();
                }
                $this->inputBuffer = substr($this->inputBuffer, $written);
                if (isset($this->inputBuffer[0]) && isset($this->pipes[0])) {
                    return [$this->pipes[0]];
                }
            }

            if ($input) {
                while (true) {
                    $data = fread($input, self::CHUNK_SIZE);
                    if (!isset($data[0])) {
                        break;
                    }
                    if (false === $written = @fwrite($stdin, $data)) {
                        return $this->closeBrokenInputPipe();
                    }
                    $data = substr($data, $written);
                    if (isset($data[0])) {
                        $this->inputBuffer = $data;

                        return isset($this->pipes[0]) ? [$this->pipes[0]] : null;
                    }
                }
                if (feof($input)) {
                    if ($this->input instanceof \Iterator) {
                        $this->input->next();
                    } else {
                        $this->input = null;
                    }
                }
            }
        }

        // no input to read on resource, buffer is empty
        if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
            $this->input = null;
            fclose($this->pipes[0]);
            unset($this->pipes[0]);
        } elseif (!$w) {
            return [$this->pipes[0]];
        }

        return null;
    }

    private function closeBrokenInputPipe(): void
    {
        $this->lastError = error_get_last()['message'] ?? null;
        if (\is_resource($this->pipes[0] ?? null)) {
            fclose($this->pipes[0]);
        }
        unset($this->pipes[0]);

        $this->input = null;
        $this->inputBuffer = '';
    }

    /**
     * @internal
     */
    public function handleError(int $type, string $msg): void
    {
        $this->lastError = $msg;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Pipes;

/**
 * PipesInterface manages descriptors and pipes for the use of proc_open.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
interface PipesInterface
{
    public const CHUNK_SIZE = 16384;

    /**
     * Returns an array of descriptors for the use of proc_open.
     */
    public function getDescriptors(): array;

    /**
     * Returns an array of filenames indexed by their related stream in case these pipes use temporary files.
     *
     * @return string[]
     */
    public function getFiles(): array;

    /**
     * Reads data in file handles and pipes.
     *
     * @param bool $blocking Whether to use blocking calls or not
     * @param bool $close    Whether to close pipes if they've reached EOF
     *
     * @return string[] An array of read data indexed by their fd
     */
    public function readAndWrite(bool $blocking, bool $close = false): array;

    /**
     * Returns if the current state has open file handles or pipes.
     */
    public function areOpen(): bool;

    /**
     * Returns if pipes are able to read output.
     */
    public function haveReadSupport(): bool;

    /**
     * Closes file handles and pipes.
     */
    public function close(): void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Pipes;

use Symfony\Component\Process\Exception\RuntimeException;
use Symfony\Component\Process\Process;

/**
 * WindowsPipes implementation uses temporary files as handles.
 *
 * @see https://bugs.php.net/51800
 * @see https://bugs.php.net/65650
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
class WindowsPipes extends AbstractPipes
{
    private array $files = [];
    private array $fileHandles = [];
    private array $lockHandles = [];
    private array $readBytes = [
        Process::STDOUT => 0,
        Process::STDERR => 0,
    ];

    public function __construct(
        mixed $input,
        private bool $haveReadSupport,
    ) {
        if ($this->haveReadSupport) {
            // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
            // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
            //
            // @see https://bugs.php.net/51800
            $pipes = [
                Process::STDOUT => Process::OUT,
                Process::STDERR => Process::ERR,
            ];
            $tmpDir = sys_get_temp_dir();
            $lastError = 'unknown reason';
            set_error_handler(static function ($type, $msg) use (&$lastError) { $lastError = $msg; });
            for ($i = 0;; ++$i) {
                foreach ($pipes as $pipe => $name) {
                    $file = \sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);

                    if (!$h = fopen($file.'.lock', 'w')) {
                        if (file_exists($file.'.lock')) {
                            continue 2;
                        }
                        restore_error_handler();
                        throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);
                    }
                    if (!flock($h, \LOCK_EX | \LOCK_NB)) {
                        continue 2;
                    }
                    if (isset($this->lockHandles[$pipe])) {
                        flock($this->lockHandles[$pipe], \LOCK_UN);
                        fclose($this->lockHandles[$pipe]);
                    }
                    $this->lockHandles[$pipe] = $h;

                    if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) {
                        flock($this->lockHandles[$pipe], \LOCK_UN);
                        fclose($this->lockHandles[$pipe]);
                        unset($this->lockHandles[$pipe]);
                        continue 2;
                    }
                    $this->fileHandles[$pipe] = $h;
                    $this->files[$pipe] = $file;
                }
                break;
            }
            restore_error_handler();
        }

        parent::__construct($input);
    }

    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
    }

    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
    }

    public function __destruct()
    {
        $this->close();
    }

    public function getDescriptors(): array
    {
        if (!$this->haveReadSupport) {
            $nullstream = fopen('NUL', 'c');

            return [
                ['pipe', 'r'],
                $nullstream,
                $nullstream,
            ];
        }

        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
        // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
        // So we redirect output within the commandline and pass the nul device to the process
        return [
            ['pipe', 'r'],
            ['file', 'NUL', 'w'],
            ['file', 'NUL', 'w'],
        ];
    }

    public function getFiles(): array
    {
        return $this->files;
    }

    public function readAndWrite(bool $blocking, bool $close = false): array
    {
        $this->unblock();
        $w = $this->write();
        $read = $r = $e = [];

        if ($blocking) {
            if ($w) {
                @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
            } elseif ($this->fileHandles) {
                usleep((int) (Process::TIMEOUT_PRECISION * 1E6));
            }
        }
        foreach ($this->fileHandles as $type => $fileHandle) {
            $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);

            if (isset($data[0])) {
                $this->readBytes[$type] += \strlen($data);
                $read[$type] = $data;
            }
            if ($close) {
                ftruncate($fileHandle, 0);
                fclose($fileHandle);
                flock($this->lockHandles[$type], \LOCK_UN);
                fclose($this->lockHandles[$type]);
                unset($this->fileHandles[$type], $this->lockHandles[$type]);
            }
        }

        return $read;
    }

    public function haveReadSupport(): bool
    {
        return $this->haveReadSupport;
    }

    public function areOpen(): bool
    {
        return $this->pipes && $this->fileHandles;
    }

    public function close(): void
    {
        parent::close();
        foreach ($this->fileHandles as $type => $handle) {
            ftruncate($handle, 0);
            fclose($handle);
            flock($this->lockHandles[$type], \LOCK_UN);
            fclose($this->lockHandles[$type]);
        }
        $this->fileHandles = $this->lockHandles = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Pipes;

use Symfony\Component\Process\Process;

/**
 * UnixPipes implementation uses unix pipes as handles.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
class UnixPipes extends AbstractPipes
{
    public function __construct(
        private ?bool $ttyMode,
        private bool $ptyMode,
        mixed $input,
        private bool $haveReadSupport,
    ) {
        parent::__construct($input);
    }

    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
    }

    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
    }

    public function __destruct()
    {
        $this->close();
    }

    public function getDescriptors(): array
    {
        if (!$this->haveReadSupport) {
            $nullstream = fopen('/dev/null', 'c');

            return [
                ['pipe', 'r'],
                $nullstream,
                $nullstream,
            ];
        }

        if ($this->ttyMode) {
            return [
                ['file', '/dev/tty', 'r'],
                ['file', '/dev/tty', 'w'],
                ['file', '/dev/tty', 'w'],
            ];
        }

        if ($this->ptyMode && Process::isPtySupported()) {
            return [
                ['pty'],
                ['pty'],
                ['pipe', 'w'], // stderr needs to be in a pipe to correctly split error and output, since PHP will use the same stream for both
            ];
        }

        return [
            ['pipe', 'r'],
            ['pipe', 'w'], // stdout
            ['pipe', 'w'], // stderr
        ];
    }

    public function getFiles(): array
    {
        return [];
    }

    public function readAndWrite(bool $blocking, bool $close = false): array
    {
        $this->unblock();
        $w = $this->write();

        $read = $e = [];
        $r = $this->pipes;
        unset($r[0]);

        // let's have a look if something changed in streams
        set_error_handler($this->handleError(...));
        if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
            restore_error_handler();
            // if a system call has been interrupted, forget about it, let's try again
            // otherwise, an error occurred, let's reset pipes
            if (!$this->hasSystemCallBeenInterrupted()) {
                $this->pipes = [];
            }

            return $read;
        }
        restore_error_handler();

        foreach ($r as $pipe) {
            // prior PHP 5.4 the array passed to stream_select is modified and
            // lose key association, we have to find back the key
            $read[$type = array_search($pipe, $this->pipes, true)] = '';

            do {
                $data = @fread($pipe, self::CHUNK_SIZE);
                $read[$type] .= $data;
            } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));

            if (!isset($read[$type][0])) {
                unset($read[$type]);
            }

            if ($close && feof($pipe)) {
                fclose($pipe);
                unset($this->pipes[$type]);
            }
        }

        return $read;
    }

    public function haveReadSupport(): bool
    {
        return $this->haveReadSupport;
    }

    public function areOpen(): bool
    {
        return (bool) $this->pipes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\RuntimeException;

/**
 * PhpSubprocess runs a PHP command as a subprocess while keeping the original php.ini settings.
 *
 * For this, it generates a temporary php.ini file taking over all the current settings and disables
 * loading additional .ini files. Basically, your command gets prefixed using "php -n -c /tmp/temp.ini".
 *
 * Given your php.ini contains "memory_limit=-1" and you have a "MemoryTest.php" with the following content:
 *
 *     <?php var_dump(ini_get('memory_limit'));
 *
 * These are the differences between the regular Process and PhpSubprocess classes:
 *
 *     $p = new Process(['php', '-d', 'memory_limit=256M', 'MemoryTest.php']);
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * This will output "string(2) "-1", because the process is started with the default php.ini settings.
 *
 *     $p = new PhpSubprocess(['MemoryTest.php'], null, null, 60, ['php', '-d', 'memory_limit=256M']);
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * This will output "string(4) "256M"", because the process is started with the temporarily created php.ini settings.
 *
 * @author Yanick Witschi <yanick.witschi@terminal42.ch>
 * @author Partially copied and heavily inspired from composer/xdebug-handler by John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class PhpSubprocess extends Process
{
    /**
     * @param array       $command The command to run and its arguments listed as separate entries. They will automatically
     *                             get prefixed with the PHP binary
     * @param string|null $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null  $env     The environment variables or null to use the same environment as the current PHP process
     * @param int         $timeout The timeout in seconds
     * @param array|null  $php     Path to the PHP binary to use with any additional arguments
     */
    public function __construct(array $command, ?string $cwd = null, ?array $env = null, int $timeout = 60, ?array $php = null)
    {
        if (null === $php) {
            $executableFinder = new PhpExecutableFinder();
            $php = $executableFinder->find(false);
            $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments());
        }

        if (null === $php) {
            throw new RuntimeException('Unable to find PHP binary.');
        }

        $tmpIni = $this->writeTmpIni($this->getAllIniFiles(), sys_get_temp_dir());

        $php = array_merge($php, ['-n', '-c', $tmpIni]);
        register_shutdown_function('unlink', $tmpIni);

        $command = array_merge($php, $command);

        parent::__construct($command, $cwd, $env, null, $timeout);
    }

    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
    {
        throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
    }

    /**
     * @param (callable('out'|'err', string):void)|null $callback
     */
    public function start(?callable $callback = null, array $env = []): void
    {
        if (null === $this->getCommandLine()) {
            throw new RuntimeException('Unable to find the PHP executable.');
        }

        parent::start($callback, $env);
    }

    private function writeTmpIni(array $iniFiles, string $tmpDir): string
    {
        if (false === $tmpfile = @tempnam($tmpDir, '')) {
            throw new RuntimeException('Unable to create temporary ini file.');
        }

        // $iniFiles has at least one item and it may be empty
        if ('' === $iniFiles[0]) {
            array_shift($iniFiles);
        }

        $content = '';

        foreach ($iniFiles as $file) {
            // Check for inaccessible ini files
            if (($data = @file_get_contents($file)) === false) {
                throw new RuntimeException('Unable to read ini: '.$file);
            }
            // Check and remove directives after HOST and PATH sections
            if (preg_match('/^\s*\[(?:PATH|HOST)\s*=/mi', $data, $matches, \PREG_OFFSET_CAPTURE)) {
                $data = substr($data, 0, $matches[0][1]);
            }

            $content .= $data."\n";
        }

        // Merge loaded settings into our ini content, if it is valid
        $config = parse_ini_string($content);
        $loaded = ini_get_all(null, false);

        if (false === $config || false === $loaded) {
            throw new RuntimeException('Unable to parse ini data.');
        }

        $content .= $this->mergeLoadedConfig($loaded, $config);

        // Work-around for https://bugs.php.net/bug.php?id=75932
        $content .= "opcache.enable_cli=0\n";

        if (false === @file_put_contents($tmpfile, $content)) {
            throw new RuntimeException('Unable to write temporary ini file.');
        }

        return $tmpfile;
    }

    private function mergeLoadedConfig(array $loadedConfig, array $iniConfig): string
    {
        $content = '';

        foreach ($loadedConfig as $name => $value) {
            if (!\is_string($value)) {
                continue;
            }

            if (!isset($iniConfig[$name]) || $iniConfig[$name] !== $value) {
                // Double-quote escape each value
                $content .= $name.'="'.addcslashes($value, '\\"')."\"\n";
            }
        }

        return $content;
    }

    private function getAllIniFiles(): array
    {
        $paths = [(string) php_ini_loaded_file()];

        if (false !== $scanned = php_ini_scanned_files()) {
            $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
        }

        return $paths;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\InvalidArgumentException;

/**
 * ProcessUtils is a bunch of utility methods.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class ProcessUtils
{
    /**
     * This class should not be instantiated.
     */
    private function __construct()
    {
    }

    /**
     * Validates and normalizes a Process input.
     *
     * @param string $caller The name of method call that validates the input
     * @param mixed  $input  The input to validate
     *
     * @throws InvalidArgumentException In case the input is not valid
     */
    public static function validateInput(string $caller, mixed $input): mixed
    {
        if (null !== $input) {
            if (\is_resource($input)) {
                return $input;
            }
            if (\is_scalar($input)) {
                return (string) $input;
            }
            if ($input instanceof Process) {
                return $input->getIterator($input::ITER_SKIP_ERR);
            }
            if ($input instanceof \Iterator) {
                return $input;
            }
            if ($input instanceof \Traversable) {
                return new \IteratorIterator($input);
            }

            throw new InvalidArgumentException(\sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
        }

        return $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Exception\ProcessSignaledException;
use Symfony\Component\Process\Exception\ProcessStartFailedException;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Exception\RuntimeException;
use Symfony\Component\Process\Pipes\UnixPipes;
use Symfony\Component\Process\Pipes\WindowsPipes;

/**
 * Process is a thin wrapper around proc_* functions to easily
 * start independent PHP processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @implements \IteratorAggregate<string, string>
 */
class Process implements \IteratorAggregate
{
    public const ERR = 'err';
    public const OUT = 'out';

    public const STATUS_READY = 'ready';
    public const STATUS_STARTED = 'started';
    public const STATUS_TERMINATED = 'terminated';

    public const STDIN = 0;
    public const STDOUT = 1;
    public const STDERR = 2;

    // Timeout Precision in seconds.
    public const TIMEOUT_PRECISION = 0.2;

    public const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
    public const ITER_KEEP_OUTPUT = 2;  // By default, outputs are cleared while iterating, use this flag to keep them in memory
    public const ITER_SKIP_OUT = 4;     // Use this flag to skip STDOUT while iterating
    public const ITER_SKIP_ERR = 8;     // Use this flag to skip STDERR while iterating

    /**
     * Maximum number of UTF-16 code units allowed in the Windows environment block.
     *
     * The Win32 CreateProcess API encodes env vars as KEY=VALUE\0 in UTF-16LE,
     * terminated by an extra \0. Exceeding this limit causes proc_open() to hang
     * silently rather than returning false.
     *
     * @see https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
     */
    private const WINDOWS_ENV_BLOCK_MAX_LENGTH = 32767;

    /**
     * @var \Closure('out'|'err', string):bool|null
     */
    private ?\Closure $callback = null;
    private array|string $commandline;
    private ?string $cwd;
    private array $env = [];
    /** @var resource|string|\Iterator|null */
    private $input;
    private ?float $starttime = null;
    private ?float $lastOutputTime = null;
    private ?float $timeout = null;
    private ?float $idleTimeout = null;
    private ?int $exitcode = null;
    private array $fallbackStatus = [];
    private array $processInformation;
    private bool $outputDisabled = false;
    /** @var resource */
    private $stdout;
    /** @var resource */
    private $stderr;
    /** @var resource|null */
    private $process;
    private string $status = self::STATUS_READY;
    private int $incrementalOutputOffset = 0;
    private int $incrementalErrorOutputOffset = 0;
    private bool $tty = false;
    private bool $pty;
    private array $options = ['suppress_errors' => true, 'bypass_shell' => true];
    private array $ignoredSignals = [];

    private WindowsPipes|UnixPipes $processPipes;

    private ?int $latestSignal = null;

    private static ?bool $sigchild = null;
    private static array $executables = [];

    /**
     * Exit codes translation table.
     *
     * User-defined errors must use exit codes in the 64-113 range.
     */
    public static array $exitCodes = [
        0 => 'OK',
        1 => 'General error',
        2 => 'Misuse of shell builtins',

        126 => 'Invoked command cannot execute',
        127 => 'Command not found',
        128 => 'Invalid exit argument',

        // signals
        129 => 'Hangup',
        130 => 'Interrupt',
        131 => 'Quit and dump core',
        132 => 'Illegal instruction',
        133 => 'Trace/breakpoint trap',
        134 => 'Process aborted',
        135 => 'Bus error: "access to undefined portion of memory object"',
        136 => 'Floating point exception: "erroneous arithmetic operation"',
        137 => 'Kill (terminate immediately)',
        138 => 'User-defined 1',
        139 => 'Segmentation violation',
        140 => 'User-defined 2',
        141 => 'Write to pipe with no one reading',
        142 => 'Signal raised by alarm',
        143 => 'Termination (request to terminate)',
        // 144 - not defined
        145 => 'Child process terminated, stopped (or continued*)',
        146 => 'Continue if stopped',
        147 => 'Stop executing temporarily',
        148 => 'Terminal stop signal',
        149 => 'Background process attempting to read from tty ("in")',
        150 => 'Background process attempting to write to tty ("out")',
        151 => 'Urgent data available on socket',
        152 => 'CPU time limit exceeded',
        153 => 'File size limit exceeded',
        154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
        155 => 'Profiling timer expired',
        // 156 - not defined
        157 => 'Pollable event',
        // 158 - not defined
        159 => 'Bad syscall',
    ];

    /**
     * @param array          $command The command to run and its arguments listed as separate entries
     * @param string|null    $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null     $env     The environment variables or null to use the same environment as the current PHP process
     * @param mixed          $input   The input as stream resource, scalar or \Traversable, or null for no input
     * @param int|float|null $timeout The timeout in seconds or null to disable
     *
     * @throws LogicException When proc_open is not installed
     */
    public function __construct(array $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60)
    {
        if (!\function_exists('proc_open')) {
            throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.');
        }

        $this->commandline = $command;
        $this->cwd = $cwd;

        // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
        // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected
        // @see : https://bugs.php.net/51800
        // @see : https://bugs.php.net/50524
        if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
            $this->cwd = getcwd();
        }
        if (null !== $env) {
            $this->setEnv($env);
        }

        $this->setInput($input);
        $this->setTimeout($timeout);
        $this->pty = false;
    }

    /**
     * Creates a Process instance as a command-line to be run in a shell wrapper.
     *
     * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.)
     * This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the
     * shell wrapper and not to your commands.
     *
     * In order to inject dynamic values into command-lines, we strongly recommend using placeholders.
     * This will save escaping values, which is not portable nor secure anyway:
     *
     *   $process = Process::fromShellCommandline('my_command "${:MY_VAR}"');
     *   $process->run(null, ['MY_VAR' => $theValue]);
     *
     * @param string         $command The command line to pass to the shell of the OS
     * @param string|null    $cwd     The working directory or null to use the working dir of the current PHP process
     * @param array|null     $env     The environment variables or null to use the same environment as the current PHP process
     * @param mixed          $input   The input as stream resource, scalar or \Traversable, or null for no input
     * @param int|float|null $timeout The timeout in seconds or null to disable
     *
     * @throws LogicException When proc_open is not installed
     */
    public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): static
    {
        $process = new static([], $cwd, $env, $input, $timeout);
        $process->commandline = $command;

        return $process;
    }

    public function __serialize(): array
    {
        throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
    }

    public function __unserialize(array $data): void
    {
        throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
    }

    public function __destruct()
    {
        if ($this->options['create_new_console'] ?? false) {
            $this->processPipes->close();
        } else {
            $this->stop(0);
        }
    }

    public function __clone()
    {
        $this->resetProcessData();
    }

    /**
     * Runs the process.
     *
     * The callback receives the type of output (out or err) and
     * some bytes from the output in real-time. It allows to have feedback
     * from the independent process during execution.
     *
     * The STDOUT and STDERR are also available after the process is finished
     * via the getOutput() and getErrorOutput() methods.
     *
     * @param (callable('out'|'err', string):void)|null $callback A PHP callback to run whenever there is some
     *                                                            output available on STDOUT or STDERR
     *
     * @return int The exit status code
     *
     * @throws ProcessStartFailedException When process can't be launched
     * @throws RuntimeException            When process is already running
     * @throws ProcessTimedOutException    When process timed out
     * @throws ProcessSignaledException    When process stopped after receiving signal
     * @throws LogicException              In case a callback is provided and output has been disabled
     *
     * @final
     */
    public function run(?callable $callback = null, array $env = []): int
    {
        $this->start($callback, $env);

        return $this->wait();
    }

    /**
     * Runs the process.
     *
     * This is identical to run() except that an exception is thrown if the process
     * exits with a non-zero exit code.
     *
     * @param (callable('out'|'err', string):void)|null $callback A PHP callback to run whenever there is some
     *                                                            output available on STDOUT or STDERR
     *
     * @return $this
     *
     * @throws ProcessFailedException   When process didn't terminate successfully
     * @throws RuntimeException         When process can't be launched
     * @throws RuntimeException         When process is already running
     * @throws ProcessTimedOutException When process timed out
     * @throws ProcessSignaledException When process stopped after receiving signal
     * @throws LogicException           In case a callback is provided and output has been disabled
     *
     * @final
     */
    public function mustRun(?callable $callback = null, array $env = []): static
    {
        if (0 !== $this->run($callback, $env)) {
            throw new ProcessFailedException($this);
        }

        return $this;
    }

    /**
     * Starts the process and returns after writing the input to STDIN.
     *
     * This method blocks until all STDIN data is sent to the process then it
     * returns while the process runs in the background.
     *
     * The termination of the process can be awaited with wait().
     *
     * The callback receives the type of output (out or err) and some bytes from
     * the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param (callable('out'|'err', string):void)|null $callback A PHP callback to run whenever there is some
     *                                                            output available on STDOUT or STDERR
     *
     * @throws ProcessStartFailedException When process can't be launched
     * @throws RuntimeException            When process is already running
     * @throws LogicException              In case a callback is provided and output has been disabled
     */
    public function start(?callable $callback = null, array $env = []): void
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running.');
        }

        $this->resetProcessData();
        $this->starttime = $this->lastOutputTime = microtime(true);
        $this->callback = $this->buildCallback($callback);
        $descriptors = $this->getDescriptors(null !== $callback);

        if ($this->env) {
            $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env;
        }

        $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv();

        if (\is_array($commandline = $this->commandline)) {
            $commandline = array_values(array_map(strval(...), $commandline));
        } else {
            $commandline = $this->replacePlaceholders($commandline, $env);
        }

        if ('\\' === \DIRECTORY_SEPARATOR) {
            $commandline = $this->prepareWindowsCommandLine($commandline, $env);
        } elseif ($this->isSigchildEnabled()) {
            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
            $descriptors[3] = ['pipe', 'w'];

            if (\is_array($commandline)) {
                // exec is mandatory to deal with sending a signal to the process
                $commandline = 'exec '.$this->buildShellCommandline($commandline);
            }

            // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
            $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
            $commandline .= 'pid=$!; echo $pid >&3; wait $pid 2>/dev/null; code=$?; echo $code >&3; exit $code';
        }

        $envPairs = [];
        foreach ($env as $k => $v) {
            if (!\is_scalar($v ?? '') && !$v instanceof \Stringable) {
                continue;
            }

            if (false !== $v && !\in_array($k = (string) $k, ['', 'argc', 'argv', 'ARGC', 'ARGV'], true) && !str_contains($k, '=') && !str_contains($k, "\0")) {
                $envPairs[] = $k.'='.$v;
            }
        }

        if ('\\' === \DIRECTORY_SEPARATOR) {
            $this->validateWindowsEnvBlockSize($envPairs);
        }

        if (!is_dir($this->cwd)) {
            throw new RuntimeException(\sprintf('The provided cwd "%s" does not exist.', $this->cwd));
        }

        $lastError = null;
        set_error_handler(static function ($type, $msg) use (&$lastError) {
            $lastError = $msg;

            return true;
        });

        $oldMask = [];

        if ($this->ignoredSignals && \function_exists('pcntl_sigprocmask')) {
            // we block signals we want to ignore, as proc_open will use fork / posix_spawn which will copy the signal mask this allow to block
            // signals in the child process
            pcntl_sigprocmask(\SIG_BLOCK, $this->ignoredSignals, $oldMask);
        }

        try {
            $process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);

            // Ensure array vs string commands behave the same
            if (!$process && \is_array($commandline)) {
                $process = @proc_open('exec '.$this->buildShellCommandline($commandline), $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
            }
        } finally {
            if ($this->ignoredSignals && \function_exists('pcntl_sigprocmask')) {
                // we restore the signal mask here to avoid any side effects
                pcntl_sigprocmask(\SIG_SETMASK, $oldMask);
            }

            restore_error_handler();
        }

        if (!$process) {
            throw new ProcessStartFailedException($this, $lastError);
        }
        $this->process = $process;
        $this->status = self::STATUS_STARTED;

        if (isset($descriptors[3])) {
            $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
        }

        if ($this->tty) {
            return;
        }

        $this->updateStatus(false);
        $this->checkTimeout();
    }

    /**
     * Restarts the process.
     *
     * Be warned that the process is cloned before being started.
     *
     * @param (callable('out'|'err', string):void)|null $callback A PHP callback to run whenever there is some
     *                                                            output available on STDOUT or STDERR
     *
     * @throws ProcessStartFailedException When process can't be launched
     * @throws RuntimeException            When process is already running
     *
     * @see start()
     *
     * @final
     */
    public function restart(?callable $callback = null, array $env = []): static
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running.');
        }

        $process = clone $this;
        $process->start($callback, $env);

        return $process;
    }

    /**
     * Waits for the process to terminate.
     *
     * The callback receives the type of output (out or err) and some bytes
     * from the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param (callable('out'|'err', string):void)|null $callback A PHP callback to run whenever there is some
     *                                                            output available on STDOUT or STDERR
     *
     * @return int The exitcode of the process
     *
     * @throws ProcessTimedOutException When process timed out
     * @throws ProcessSignaledException When process stopped after receiving signal
     * @throws LogicException           When process is not yet started
     */
    public function wait(?callable $callback = null): int
    {
        $this->requireProcessIsStarted(__FUNCTION__);

        $this->updateStatus(false);

        if (null !== $callback) {
            if (!$this->processPipes->haveReadSupport()) {
                $this->stop(0);
                throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".');
            }
            $this->callback = $this->buildCallback($callback);
        }

        do {
            $this->checkTimeout();
            $running = $this->isRunning() && ('\\' === \DIRECTORY_SEPARATOR || $this->processPipes->areOpen());
            $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
        } while ($running);

        while ($this->isRunning()) {
            $this->checkTimeout();
            usleep(1000);
        }

        if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
            throw new ProcessSignaledException($this);
        }

        return $this->exitcode;
    }

    /**
     * Waits until the callback returns true.
     *
     * The callback receives the type of output (out or err) and some bytes
     * from the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param (callable('out'|'err', string):bool)|null $callback A PHP callback to run whenever there is some
     *                                                            output available on STDOUT or STDERR
     *
     * @throws RuntimeException         When process timed out
     * @throws LogicException           When process is not yet started
     * @throws ProcessTimedOutException In case the timeout was reached
     */
    public function waitUntil(callable $callback): bool
    {
        $this->requireProcessIsStarted(__FUNCTION__);
        $this->updateStatus(false);

        if (!$this->processPipes->haveReadSupport()) {
            $this->stop(0);
            throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::waitUntil".');
        }
        $callback = $this->buildCallback($callback);

        $ready = false;
        while (true) {
            $this->checkTimeout();
            $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
            $output = $this->processPipes->readAndWrite($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);

            foreach ($output as $type => $data) {
                if (3 !== $type) {
                    $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready;
                } elseif (!isset($this->fallbackStatus['signaled'])) {
                    $this->fallbackStatus['exitcode'] = (int) $data;
                }
            }
            if ($ready) {
                return true;
            }
            if (!$running) {
                return false;
            }

            usleep(1000);
        }
    }

    /**
     * Returns the Pid (process identifier), if applicable.
     *
     * @return int|null The process id if running, null otherwise
     */
    public function getPid(): ?int
    {
        return $this->isRunning() ? $this->processInformation['pid'] : null;
    }

    /**
     * Sends a POSIX signal to the process.
     *
     * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)
     *
     * @return $this
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    public function signal(int $signal): static
    {
        $this->doSignal($signal, true);

        return $this;
    }

    /**
     * Disables fetching output and error output from the underlying process.
     *
     * @return $this
     *
     * @throws RuntimeException In case the process is already running
     * @throws LogicException   if an idle timeout is set
     */
    public function disableOutput(): static
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Disabling output while the process is running is not possible.');
        }
        if (null !== $this->idleTimeout) {
            throw new LogicException('Output cannot be disabled while an idle timeout is set.');
        }

        $this->outputDisabled = true;

        return $this;
    }

    /**
     * Enables fetching output and error output from the underlying process.
     *
     * @return $this
     *
     * @throws RuntimeException In case the process is already running
     */
    public function enableOutput(): static
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Enabling output while the process is running is not possible.');
        }

        $this->outputDisabled = false;

        return $this;
    }

    /**
     * Returns true in case the output is disabled, false otherwise.
     */
    public function isOutputDisabled(): bool
    {
        return $this->outputDisabled;
    }

    /**
     * Returns the current output of the process (STDOUT).
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);

        if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
            return '';
        }

        return $ret;
    }

    /**
     * Returns the output incrementally.
     *
     * In comparison with the getOutput method which always return the whole
     * output, this one returns the new output since the last call.
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getIncrementalOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);

        $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
        $this->incrementalOutputOffset = ftell($this->stdout);

        if (false === $latest) {
            return '';
        }

        return $latest;
    }

    /**
     * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR).
     *
     * @param int $flags A bit field of Process::ITER_* flags
     *
     * @return \Generator<string, string>
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getIterator(int $flags = 0): \Generator
    {
        $this->readPipesForOutput(__FUNCTION__, false);

        $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags);
        $blocking = !(self::ITER_NON_BLOCKING & $flags);
        $yieldOut = !(self::ITER_SKIP_OUT & $flags);
        $yieldErr = !(self::ITER_SKIP_ERR & $flags);

        while (null !== $this->callback || ($yieldOut && !feof($this->stdout)) || ($yieldErr && !feof($this->stderr))) {
            if ($yieldOut) {
                $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);

                if (isset($out[0])) {
                    if ($clearOutput) {
                        $this->clearOutput();
                    } else {
                        $this->incrementalOutputOffset = ftell($this->stdout);
                    }

                    yield self::OUT => $out;
                }
            }

            if ($yieldErr) {
                $err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);

                if (isset($err[0])) {
                    if ($clearOutput) {
                        $this->clearErrorOutput();
                    } else {
                        $this->incrementalErrorOutputOffset = ftell($this->stderr);
                    }

                    yield self::ERR => $err;
                }
            }

            if (!$blocking && !isset($out[0]) && !isset($err[0])) {
                yield self::OUT => '';
            }

            $this->checkTimeout();
            $this->readPipesForOutput(__FUNCTION__, $blocking);
        }
    }

    /**
     * Clears the process output.
     *
     * @return $this
     */
    public function clearOutput(): static
    {
        ftruncate($this->stdout, 0);
        fseek($this->stdout, 0);
        $this->incrementalOutputOffset = 0;

        return $this;
    }

    /**
     * Returns the current error output of the process (STDERR).
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getErrorOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);

        if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
            return '';
        }

        return $ret;
    }

    /**
     * Returns the errorOutput incrementally.
     *
     * In comparison with the getErrorOutput method which always return the
     * whole error output, this one returns the new error output since the last
     * call.
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getIncrementalErrorOutput(): string
    {
        $this->readPipesForOutput(__FUNCTION__);

        $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
        $this->incrementalErrorOutputOffset = ftell($this->stderr);

        if (false === $latest) {
            return '';
        }

        return $latest;
    }

    /**
     * Clears the process output.
     *
     * @return $this
     */
    public function clearErrorOutput(): static
    {
        ftruncate($this->stderr, 0);
        fseek($this->stderr, 0);
        $this->incrementalErrorOutputOffset = 0;

        return $this;
    }

    /**
     * Returns the exit code returned by the process.
     *
     * @return int|null The exit status code, null if the Process is not terminated
     */
    public function getExitCode(): ?int
    {
        $this->updateStatus(false);

        return $this->exitcode;
    }

    /**
     * Returns a string representation for the exit code returned by the process.
     *
     * This method relies on the Unix exit code status standardization
     * and might not be relevant for other operating systems.
     *
     * @return string|null A string representation for the exit status code, null if the Process is not terminated
     *
     * @see http://tldp.org/LDP/abs/html/exitcodes.html
     * @see http://en.wikipedia.org/wiki/Unix_signal
     */
    public function getExitCodeText(): ?string
    {
        if (null === $exitcode = $this->getExitCode()) {
            return null;
        }

        return self::$exitCodes[$exitcode] ?? 'Unknown error';
    }

    /**
     * Checks if the process ended successfully.
     */
    public function isSuccessful(): bool
    {
        return 0 === $this->getExitCode();
    }

    /**
     * Returns true if the child process has been terminated by an uncaught signal.
     *
     * It always returns false on Windows.
     *
     * @throws LogicException In case the process is not terminated
     */
    public function hasBeenSignaled(): bool
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        return $this->processInformation['signaled'];
    }

    /**
     * Returns the number of the signal that caused the child process to terminate its execution.
     *
     * It is only meaningful if hasBeenSignaled() returns true.
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws LogicException   In case the process is not terminated
     */
    public function getTermSignal(): int
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.');
        }

        return $this->processInformation['termsig'];
    }

    /**
     * Returns true if the child process has been stopped by a signal.
     *
     * It always returns false on Windows.
     *
     * @throws LogicException In case the process is not terminated
     */
    public function hasBeenStopped(): bool
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        return $this->processInformation['stopped'];
    }

    /**
     * Returns the number of the signal that caused the child process to stop its execution.
     *
     * It is only meaningful if hasBeenStopped() returns true.
     *
     * @throws LogicException In case the process is not terminated
     */
    public function getStopSignal(): int
    {
        $this->requireProcessIsTerminated(__FUNCTION__);

        return $this->processInformation['stopsig'];
    }

    /**
     * Checks if the process is currently running.
     */
    public function isRunning(): bool
    {
        if (self::STATUS_STARTED !== $this->status) {
            return false;
        }

        $this->updateStatus(false);

        return $this->processInformation['running'];
    }

    /**
     * Checks if the process has been started with no regard to the current state.
     */
    public function isStarted(): bool
    {
        return self::STATUS_READY != $this->status;
    }

    /**
     * Checks if the process is terminated.
     */
    public function isTerminated(): bool
    {
        $this->updateStatus(false);

        return self::STATUS_TERMINATED == $this->status;
    }

    /**
     * Gets the process status.
     *
     * The status is one of: ready, started, terminated.
     */
    public function getStatus(): string
    {
        $this->updateStatus(false);

        return $this->status;
    }

    /**
     * Stops the process.
     *
     * @param int|float $timeout The timeout in seconds
     * @param int|null  $signal  A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9)
     *
     * @return int|null The exit-code of the process or null if it's not running
     */
    public function stop(float $timeout = 10, ?int $signal = null): ?int
    {
        $timeoutMicro = microtime(true) + $timeout;
        if ($this->isRunning()) {
            // given SIGTERM may not be defined and that "proc_terminate" uses the constant value and not the constant itself, we use the same here
            $this->doSignal(15, false);
            do {
                usleep(1000);
            } while ($this->isRunning() && microtime(true) < $timeoutMicro);

            if ($this->isRunning()) {
                // Avoid exception here: process is supposed to be running, but it might have stopped just
                // after this line. In any case, let's silently discard the error, we cannot do anything.
                $this->doSignal($signal ?: 9, false);
            }
        }

        if ($this->isRunning()) {
            if (isset($this->fallbackStatus['pid'])) {
                unset($this->fallbackStatus['pid']);

                return $this->stop(0, $signal);
            }
            $this->close();
        }

        return $this->exitcode;
    }

    /**
     * Adds a line to the STDOUT stream.
     *
     * @internal
     */
    public function addOutput(string $line): void
    {
        $this->lastOutputTime = microtime(true);

        fseek($this->stdout, 0, \SEEK_END);
        fwrite($this->stdout, $line);
        fseek($this->stdout, $this->incrementalOutputOffset);
    }

    /**
     * Adds a line to the STDERR stream.
     *
     * @internal
     */
    public function addErrorOutput(string $line): void
    {
        $this->lastOutputTime = microtime(true);

        fseek($this->stderr, 0, \SEEK_END);
        fwrite($this->stderr, $line);
        fseek($this->stderr, $this->incrementalErrorOutputOffset);
    }

    /**
     * Gets the last output time in seconds.
     */
    public function getLastOutputTime(): ?float
    {
        return $this->lastOutputTime;
    }

    /**
     * Gets the command line to be executed.
     */
    public function getCommandLine(): string
    {
        return $this->buildShellCommandline($this->commandline);
    }

    /**
     * Gets the process timeout in seconds (max. runtime).
     */
    public function getTimeout(): ?float
    {
        return $this->timeout;
    }

    /**
     * Gets the process idle timeout in seconds (max. time since last output).
     */
    public function getIdleTimeout(): ?float
    {
        return $this->idleTimeout;
    }

    /**
     * Sets the process timeout (max. runtime) in seconds.
     *
     * To disable the timeout, set this value to null.
     *
     * @return $this
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setTimeout(?float $timeout): static
    {
        $this->timeout = $this->validateTimeout($timeout);

        return $this;
    }

    /**
     * Sets the process idle timeout (max. time since last output) in seconds.
     *
     * To disable the timeout, set this value to null.
     *
     * @return $this
     *
     * @throws LogicException           if the output is disabled
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setIdleTimeout(?float $timeout): static
    {
        if (null !== $timeout && $this->outputDisabled) {
            throw new LogicException('Idle timeout cannot be set while the output is disabled.');
        }

        $this->idleTimeout = $this->validateTimeout($timeout);

        return $this;
    }

    /**
     * Enables or disables the TTY mode.
     *
     * @return $this
     *
     * @throws RuntimeException In case the TTY mode is not supported
     */
    public function setTty(bool $tty): static
    {
        if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
            throw new RuntimeException('TTY mode is not supported on Windows platform.');
        }

        if ($tty && !self::isTtySupported()) {
            throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
        }

        $this->tty = $tty;

        return $this;
    }

    /**
     * Checks if the TTY mode is enabled.
     */
    public function isTty(): bool
    {
        return $this->tty;
    }

    /**
     * Sets PTY mode.
     *
     * @return $this
     */
    public function setPty(bool $bool): static
    {
        $this->pty = $bool;

        return $this;
    }

    /**
     * Returns PTY state.
     */
    public function isPty(): bool
    {
        return $this->pty;
    }

    /**
     * Gets the working directory.
     */
    public function getWorkingDirectory(): ?string
    {
        if (null === $this->cwd) {
            // getcwd() will return false if any one of the parent directories does not have
            // the readable or search mode set, even if the current directory does
            return getcwd() ?: null;
        }

        return $this->cwd;
    }

    /**
     * Sets the current working directory.
     *
     * @return $this
     */
    public function setWorkingDirectory(string $cwd): static
    {
        $this->cwd = $cwd;

        return $this;
    }

    /**
     * Gets the environment variables.
     */
    public function getEnv(): array
    {
        return $this->env;
    }

    /**
     * Sets the environment variables.
     *
     * @param array<string|\Stringable> $env The new environment variables
     *
     * @return $this
     */
    public function setEnv(array $env): static
    {
        $this->env = $env;

        return $this;
    }

    /**
     * Gets the Process input.
     *
     * @return resource|string|\Iterator|null
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Sets the input.
     *
     * This content will be passed to the underlying process standard input.
     *
     * @param string|resource|\Traversable|self|null $input The content
     *
     * @return $this
     *
     * @throws LogicException In case the process is running
     */
    public function setInput(mixed $input): static
    {
        if ($this->isRunning()) {
            throw new LogicException('Input cannot be set while the process is running.');
        }

        $this->input = ProcessUtils::validateInput(__METHOD__, $input);

        return $this;
    }

    /**
     * Performs a check between the timeout definition and the time the process started.
     *
     * In case you run a background process (with the start method), you should
     * trigger this method regularly to ensure the process timeout
     *
     * @throws ProcessTimedOutException In case the timeout was reached
     */
    public function checkTimeout(): void
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }

        if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
        }

        if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
        }
    }

    /**
     * @throws LogicException in case process is not started
     */
    public function getStartTime(): float
    {
        if (!$this->isStarted()) {
            throw new LogicException('Start time is only available after process start.');
        }

        return $this->starttime;
    }

    /**
     * Defines options to pass to the underlying proc_open().
     *
     * @see https://php.net/proc_open for the options supported by PHP.
     *
     * Enabling the "create_new_console" option allows a subprocess to continue
     * to run after the main process exited, on both Windows and *nix
     */
    public function setOptions(array $options): void
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Setting options while the process is running is not possible.');
        }

        $defaultOptions = $this->options;
        $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console'];

        foreach ($options as $key => $value) {
            if (!\in_array($key, $existingOptions)) {
                $this->options = $defaultOptions;
                throw new LogicException(\sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions)));
            }
            $this->options[$key] = $value;
        }
    }

    /**
     * Defines a list of posix signals that will not be propagated to the process.
     *
     * @param list<\SIG*> $signals
     */
    public function setIgnoredSignals(array $signals): void
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Setting ignored signals while the process is running is not possible.');
        }

        $this->ignoredSignals = $signals;
    }

    /**
     * Returns whether TTY is supported on the current operating system.
     */
    public static function isTtySupported(): bool
    {
        static $isTtySupported;

        return $isTtySupported ??= ('/' === \DIRECTORY_SEPARATOR && stream_isatty(\STDOUT) && @is_writable('/dev/tty'));
    }

    /**
     * Returns whether PTY is supported on the current operating system.
     */
    public static function isPtySupported(): bool
    {
        static $result;

        if (null !== $result) {
            return $result;
        }

        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $result = false;
        }

        return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes);
    }

    /**
     * Creates the descriptors needed by the proc_open.
     */
    private function getDescriptors(bool $hasCallback): array
    {
        if ($this->input instanceof \Iterator) {
            $this->input->rewind();
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $hasCallback);
        } else {
            $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $hasCallback);
        }

        return $this->processPipes->getDescriptors();
    }

    /**
     * Builds up the callback used by wait().
     *
     * The callbacks adds all occurred output to the specific buffer and calls
     * the user callback (if present) with the received output.
     *
     * @param callable('out'|'err', string)|null $callback
     *
     * @return \Closure('out'|'err', string):bool
     */
    protected function buildCallback(?callable $callback = null): \Closure
    {
        if ($this->outputDisabled) {
            return static fn ($type, $data): bool => null !== $callback && $callback($type, $data);
        }

        return function ($type, $data) use ($callback): bool {
            match ($type) {
                self::OUT => $this->addOutput($data),
                self::ERR => $this->addErrorOutput($data),
            };

            return null !== $callback && $callback($type, $data);
        };
    }

    /**
     * Updates the status of the process, reads pipes.
     *
     * @param bool $blocking Whether to use a blocking read call
     */
    protected function updateStatus(bool $blocking): void
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }

        if ($this->processInformation['running'] ?? true) {
            $this->processInformation = proc_get_status($this->process);
        }
        $running = $this->processInformation['running'];

        $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);

        if ($this->fallbackStatus && $this->isSigchildEnabled()) {
            $this->processInformation = $this->fallbackStatus + $this->processInformation;
        }

        if (!$running) {
            $this->close();
        }
    }

    /**
     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
     */
    protected function isSigchildEnabled(): bool
    {
        if (null !== self::$sigchild) {
            return self::$sigchild;
        }

        if (!\function_exists('phpinfo')) {
            return self::$sigchild = false;
        }

        ob_start();
        phpinfo(\INFO_GENERAL);

        return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild');
    }

    /**
     * Reads pipes for the freshest output.
     *
     * @param string $caller   The name of the method that needs fresh outputs
     * @param bool   $blocking Whether to use blocking calls or not
     *
     * @throws LogicException in case output has been disabled or process is not started
     */
    private function readPipesForOutput(string $caller, bool $blocking = false): void
    {
        if ($this->outputDisabled) {
            throw new LogicException('Output has been disabled.');
        }

        $this->requireProcessIsStarted($caller);

        $this->updateStatus($blocking);
    }

    /**
     * Validates and returns the filtered timeout.
     *
     * @throws InvalidArgumentException if the given timeout is a negative number
     */
    private function validateTimeout(?float $timeout): ?float
    {
        $timeout = (float) $timeout;

        if (0.0 === $timeout) {
            $timeout = null;
        } elseif ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }

        return $timeout;
    }

    /**
     * Reads pipes, executes callback.
     *
     * @param bool $blocking Whether to use blocking calls or not
     * @param bool $close    Whether to close file handles or not
     */
    private function readPipes(bool $blocking, bool $close): void
    {
        $result = $this->processPipes->readAndWrite($blocking, $close);

        $callback = $this->callback;
        foreach ($result as $type => $data) {
            if (3 !== $type) {
                $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
            } elseif (!isset($this->fallbackStatus['signaled'])) {
                $this->fallbackStatus['exitcode'] = (int) $data;
            }
        }
    }

    /**
     * Closes process resource, closes file handles, sets the exitcode.
     *
     * @return int The exitcode
     */
    private function close(): int
    {
        $this->processPipes->close();
        if ($this->process) {
            proc_close($this->process);
            $this->process = null;
        }
        $this->exitcode = $this->processInformation['exitcode'];
        $this->status = self::STATUS_TERMINATED;

        if (-1 === $this->exitcode) {
            if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
                // if process has been signaled, no exitcode but a valid termsig, apply Unix convention
                $this->exitcode = 128 + $this->processInformation['termsig'];
            } elseif ($this->isSigchildEnabled()) {
                $this->processInformation['signaled'] = true;
                $this->processInformation['termsig'] = -1;
            }
        }

        // Free memory from self-reference callback created by buildCallback
        // Doing so in other contexts like __destruct or by garbage collector is ineffective
        // Now pipes are closed, so the callback is no longer necessary
        $this->callback = null;

        return $this->exitcode;
    }

    /**
     * Resets data related to the latest run of the process.
     */
    private function resetProcessData(): void
    {
        $this->starttime = null;
        $this->callback = null;
        $this->exitcode = null;
        $this->fallbackStatus = [];
        $this->processInformation = [];
        $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+');
        $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+');
        $this->process = null;
        $this->latestSignal = null;
        $this->status = self::STATUS_READY;
        $this->incrementalOutputOffset = 0;
        $this->incrementalErrorOutputOffset = 0;
    }

    /**
     * Sends a POSIX signal to the process.
     *
     * @param int  $signal         A valid POSIX signal (see https://php.net/pcntl.constants)
     * @param bool $throwException Whether to throw exception in case signal failed
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    private function doSignal(int $signal, bool $throwException): bool
    {
        // Signal seems to be send when sigchild is enable, this allow blocking the signal correctly in this case
        if ($this->isSigchildEnabled() && \in_array($signal, $this->ignoredSignals)) {
            return false;
        }

        if (null === $pid = $this->getPid()) {
            if ($throwException) {
                throw new LogicException('Cannot send signal on a non running process.');
            }

            return false;
        }

        if ('\\' === \DIRECTORY_SEPARATOR) {
            exec(\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
            if ($exitCode && $this->isRunning()) {
                if ($throwException) {
                    throw new RuntimeException(\sprintf('Unable to kill the process (%s).', implode(' ', $output)));
                }

                return false;
            }
        } else {
            if (!$this->isSigchildEnabled()) {
                $ok = @proc_terminate($this->process, $signal);
            } elseif (\function_exists('posix_kill')) {
                $ok = @posix_kill($pid, $signal);
            } elseif ($ok = proc_open(\sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
                $ok = false === fgets($pipes[2]);
            }
            if (!$ok) {
                if ($throwException) {
                    throw new RuntimeException(\sprintf('Error while sending signal "%s".', $signal));
                }

                return false;
            }
        }

        $this->latestSignal = $signal;
        $this->fallbackStatus['signaled'] = true;
        $this->fallbackStatus['exitcode'] = -1;
        $this->fallbackStatus['termsig'] = $this->latestSignal;

        return true;
    }

    private function buildShellCommandline(string|array $commandline): string
    {
        if (\is_string($commandline)) {
            return $commandline;
        }

        if ('\\' === \DIRECTORY_SEPARATOR && isset($commandline[0][0]) && \strlen($commandline[0]) === strcspn($commandline[0], ':/\\')) {
            // On Windows, we don't rely on the OS to find the executable if possible to avoid lookups
            // in the current directory which could be untrusted. Instead we use the ExecutableFinder.
            $commandline[0] = (self::$executables[$commandline[0]] ??= (new ExecutableFinder())->find($commandline[0])) ?? $commandline[0];
        }

        return implode(' ', array_map($this->escapeArgument(...), $commandline));
    }

    private function prepareWindowsCommandLine(string|array $cmd, array &$env): string
    {
        $cmd = $this->buildShellCommandline($cmd);
        $uid = bin2hex(random_bytes(4));
        $cmd = preg_replace_callback(
            '/"(?:(
                [^"%!^]*+
                (?:
                    (?: !LF! | "(?:\^[%!^])?+" )
                    [^"%!^]*+
                )++
            ) | [^"]*+ )"/x',
            static function ($m) use (&$env, $uid) {
                static $varCount = 0;
                static $varCache = [];
                if (!isset($m[1])) {
                    return $m[0];
                }
                if (isset($varCache[$m[0]])) {
                    return $varCache[$m[0]];
                }
                if (str_contains($value = $m[1], "\0")) {
                    $value = str_replace("\0", '?', $value);
                }
                if (false === strpbrk($value, "\"%!\n")) {
                    return '"'.$value.'"';
                }

                $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value);
                $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"';
                $var = $uid.++$varCount;

                $env[$var] = $value;

                return $varCache[$m[0]] = '!'.$var.'!';
            },
            $cmd
        );

        static $comSpec;

        if (!$comSpec && $comSpec = (new ExecutableFinder())->find('cmd.exe')) {
            // Escape according to CommandLineToArgvW rules
            $comSpec = '"'.preg_replace('{(\\\\*+)"}', '$1$1\"', $comSpec).'"';
        }

        $cmd = ($comSpec ?? 'cmd').' /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')';
        foreach ($this->processPipes->getFiles() as $offset => $filename) {
            $cmd .= ' '.$offset.'>"'.$filename.'"';
        }

        return $cmd;
    }

    /**
     * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
     *
     * @throws LogicException if the process has not run
     */
    private function requireProcessIsStarted(string $functionName): void
    {
        if (!$this->isStarted()) {
            throw new LogicException(\sprintf('Process must be started before calling "%s()".', $functionName));
        }
    }

    /**
     * Ensures the process is terminated, throws a LogicException if the process has a status different than "terminated".
     *
     * @throws LogicException if the process is not yet terminated
     */
    private function requireProcessIsTerminated(string $functionName): void
    {
        if (!$this->isTerminated()) {
            throw new LogicException(\sprintf('Process must be terminated before calling "%s()".', $functionName));
        }
    }

    /**
     * Escapes a string to be used as a shell argument.
     */
    private function escapeArgument(?string $argument): string
    {
        if ('' === $argument || null === $argument) {
            return '""';
        }
        if ('\\' !== \DIRECTORY_SEPARATOR) {
            return "'".str_replace("'", "'\\''", $argument)."'";
        }
        if (str_contains($argument, "\0")) {
            $argument = str_replace("\0", '?', $argument);
        }
        if (!preg_match('/[()%!^"<>&|\s[\]=;*?\'$]/', $argument)) {
            return $argument;
        }
        $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument);

        return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"';
    }

    private function replacePlaceholders(string $commandline, array $env): string
    {
        return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) {
            if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) {
                throw new InvalidArgumentException(\sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline);
            }

            return $this->escapeArgument($env[$matches[1]]);
        }, $commandline);
    }

    private function getDefaultEnv(): array
    {
        $env = getenv();
        $env = ('\\' === \DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env;

        return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env);
    }

    private function validateWindowsEnvBlockSize(array $envPairs): void
    {
        $block = implode("\0", $envPairs)."\0";
        @preg_replace('/./u', '', $block, -1, $blockLength)
            ?? preg_replace('/./', '', $block, -1, $blockLength);
        $blockLength += 1 + preg_match_all('/[\xF0-\xF4][\x80-\xBF]{3}/', $block);

        if ($blockLength > self::WINDOWS_ENV_BLOCK_MAX_LENGTH) {
            throw new InvalidArgumentException(\sprintf('The environment block size (%d) exceeds the Windows limit of %d UTF-16 code units.', $blockLength, self::WINDOWS_ENV_BLOCK_MAX_LENGTH));
        }
    }
}
Copyright (c) 2020-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (!function_exists('trigger_deprecation')) {
    /**
     * Triggers a silenced deprecation notice.
     *
     * @param string $package The name of the Composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The message of the deprecation
     * @param mixed  ...$args Values to insert in the message using printf() formatting
     *
     * @author Nicolas Grekas <p@tchwork.com>
     */
    function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void
    {
        @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

/**
 * Provides a way to reset an object to its initial state.
 *
 * When calling the "reset()" method on an object, it should be put back to its
 * initial state. This usually means clearing any internal buffers and forwarding
 * the call to internal dependencies. All properties of the object should be put
 * back to the same state it had when it was first ready to use.
 *
 * This method could be called, for example, to recycle objects that are used as
 * services, so that they can be used to handle several requests in the same
 * process loop (note that we advise making your services stateless instead of
 * implementing this interface when possible.)
 */
interface ResetInterface
{
    /**
     * @return void
     */
    public function reset();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\Attribute\Required;
use Symfony\Contracts\Service\Attribute\SubscribedService;

/**
 * Implementation of ServiceSubscriberInterface that determines subscribed services
 * from methods that have the #[SubscribedService] attribute.
 *
 * Service ids are available as "ClassName::methodName" so that the implementation
 * of subscriber methods can be just `return $this->container->get(__METHOD__);`.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
trait ServiceMethodsSubscriberTrait
{
    protected ContainerInterface $container;

    public static function getSubscribedServices(): array
    {
        $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];

        $reflectors = [
            ...(new \ReflectionClass(self::class))->getMethods(),
            ...(new \ReflectionClass(self::class))->getProperties(),
        ];

        foreach ($reflectors as $reflector) {
            if (self::class !== $reflector->class) {
                continue;
            }

            if (!$reflectionAttribute = $reflector->getAttributes(SubscribedService::class)[0] ?? null) {
                continue;
            }

            if ($reflector instanceof \ReflectionMethod) {
                if ($reflector->isStatic() || $reflector->isAbstract() || $reflector->isGenerator() || $reflector->isInternal() || $reflector->getNumberOfRequiredParameters()) {
                    throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $reflector->name));
                }

                if (!$autowireType = $reflector->getReturnType()) {
                    throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $reflector->name, self::class));
                }

                $defaultKey = self::class.'::'.$reflector->name;
            } elseif ($reflector instanceof \ReflectionProperty) {
                if (\PHP_VERSION_ID < 80400 || !$reflector->hasHook(\PropertyHookType::Get)) {
                    throw new \LogicException(\sprintf('Cannot use "%s" on property "%s::$%s" (can only be used on properties with a get hook).', SubscribedService::class, self::class, $reflector->name));
                }

                if (!$autowireType = $reflector->getType()) {
                    throw new \LogicException(\sprintf('Cannot use "%s" on properties without a type in "%s::$%s".', SubscribedService::class, $reflector->name, self::class));
                }

                $defaultKey = self::class.'::$'.$reflector->name.'::get';
            } else {
                throw new \LogicException('Unexpected reflector: '.get_debug_type($reflector));
            }

            /* @var SubscribedService $attribute */
            $attribute = $reflectionAttribute->newInstance();
            $attribute->key ??= $defaultKey;
            $attribute->type ??= $autowireType instanceof \ReflectionNamedType ? $autowireType->getName() : (string) $autowireType;
            $attribute->nullable = $attribute->nullable ?: $autowireType->allowsNull();

            if ($attribute->attributes) {
                $services[] = $attribute;
            } else {
                $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type;
            }
        }

        return $services;
    }

    #[Required]
    public function setContainer(ContainerInterface $container): ?ContainerInterface
    {
        $ret = null;
        if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) {
            $ret = parent::setContainer($container);
        }

        $this->container = $container;

        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

use Psr\Container\ContainerInterface;

/**
 * Implemented by objects that expose a service container.
 */
interface ContainerAwareInterface
{
    public function getContainer(): ContainerInterface;
}
Copyright (c) 2018-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

use Psr\Container\ContainerInterface;

/**
 * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Mateusz Sip <mateusz.sip@gmail.com>
 *
 * @template-covariant T of mixed
 */
interface ServiceProviderInterface extends ContainerInterface
{
    /**
     * @return T
     */
    public function get(string $id): mixed;

    public function has(string $id): bool;

    /**
     * Returns an associative array of service types keyed by the identifiers provided by the current container.
     *
     * Examples:
     *
     *  * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface
     *  * ['foo' => '?'] means the container provides service name "foo" of unspecified type
     *  * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null
     *
     * @return array<string, string> The provided service types, keyed by service names
     */
    public function getProvidedServices(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service\Test;

use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Contracts\Service\ServiceLocatorTrait;

abstract class ServiceLocatorTestCase extends TestCase
{
    /**
     * @param array<string, callable> $factories
     */
    protected function getServiceLocator(array $factories): ContainerInterface
    {
        return new class($factories) implements ContainerInterface {
            use ServiceLocatorTrait;
        };
    }

    public function testHas()
    {
        $locator = $this->getServiceLocator([
            'foo' => static fn () => 'bar',
            'bar' => static fn () => 'baz',
            static fn () => 'dummy',
        ]);

        $this->assertTrue($locator->has('foo'));
        $this->assertTrue($locator->has('bar'));
        $this->assertFalse($locator->has('dummy'));
    }

    public function testGet()
    {
        $locator = $this->getServiceLocator([
            'foo' => static fn () => 'bar',
            'bar' => static fn () => 'baz',
        ]);

        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame('baz', $locator->get('bar'));
    }

    public function testGetDoesNotMemoize()
    {
        $i = 0;
        $locator = $this->getServiceLocator([
            'foo' => static function () use (&$i) {
                ++$i;

                return 'bar';
            },
        ]);

        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame(2, $i);
    }

    public function testThrowsOnUndefinedInternalService()
    {
        $locator = $this->getServiceLocator([
            'foo' => static function () use (&$locator) { return $locator->get('bar'); },
        ]);

        $this->expectException(NotFoundExceptionInterface::class);
        $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.');

        $locator->get('foo');
    }

    public function testThrowsOnCircularReference()
    {
        $locator = $this->getServiceLocator([
            'foo' => static function () use (&$locator) { return $locator->get('bar'); },
            'bar' => static function () use (&$locator) { return $locator->get('baz'); },
            'baz' => static function () use (&$locator) { return $locator->get('bar'); },
        ]);

        $this->expectException(ContainerExceptionInterface::class);
        $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".');

        $locator->get('foo');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service\Test;

/**
 * @deprecated since PHPUnit 9.6
 */
class ServiceLocatorTest extends ServiceLocatorTestCase
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\Attribute\Required;
use Symfony\Contracts\Service\Attribute\SubscribedService;

trigger_deprecation('symfony/contracts', 'v3.5', '"%s" is deprecated, use "ServiceMethodsSubscriberTrait" instead.', ServiceSubscriberTrait::class);

/**
 * Implementation of ServiceSubscriberInterface that determines subscribed services
 * from methods that have the #[SubscribedService] attribute.
 *
 * Service ids are available as "ClassName::methodName" so that the implementation
 * of subscriber methods can be just `return $this->container->get(__METHOD__);`.
 *
 * @property ContainerInterface $container
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 *
 * @deprecated since symfony/contracts v3.5, use ServiceMethodsSubscriberTrait instead
 */
trait ServiceSubscriberTrait
{
    public static function getSubscribedServices(): array
    {
        $services = method_exists(get_parent_class(self::class) ?: '', __FUNCTION__) ? parent::getSubscribedServices() : [];

        foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
            if (self::class !== $method->class) {
                continue;
            }

            if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) {
                continue;
            }

            if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
            }

            if (!$returnType = $method->getReturnType()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
            }

            /** @var SubscribedService $attribute */
            $attribute = $attribute->newInstance();
            $attribute->key ??= self::class.'::'.$method->name;
            $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
            $attribute->nullable = $attribute->nullable ?: $returnType->allowsNull();

            if ($attribute->attributes) {
                $services[] = $attribute;
            } else {
                $services[$attribute->key] = ($attribute->nullable ? '?' : '').$attribute->type;
            }
        }

        return $services;
    }

    #[Required]
    public function setContainer(ContainerInterface $container): ?ContainerInterface
    {
        $ret = null;
        if (method_exists(get_parent_class(self::class) ?: '', __FUNCTION__)) {
            $ret = parent::setContainer($container);
        }

        $this->container = $container;

        return $ret;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service\Attribute;

use Symfony\Contracts\Service\ServiceMethodsSubscriberTrait;
use Symfony\Contracts\Service\ServiceSubscriberInterface;

/**
 * For use as the return value for {@see ServiceSubscriberInterface}.
 *
 * @example new SubscribedService('http_client', HttpClientInterface::class, false, new Target('githubApi'))
 *
 * Use with {@see ServiceMethodsSubscriberTrait} to mark a method's return type
 * as a subscribed service.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
final class SubscribedService
{
    /** @var object[] */
    public array $attributes;

    /**
     * @param string|null     $key        The key to use for the service
     * @param string|null     $type       The service type (a class name, "string", "iterable", etc.)
     * @param bool            $nullable   Whether the service is optional
     * @param object|object[] $attributes One or more dependency injection attributes to use
     */
    public function __construct(
        public ?string $key = null,
        public ?string $type = null,
        public bool $nullable = false,
        array|object $attributes = [],
    ) {
        $this->attributes = \is_array($attributes) ? $attributes : [$attributes];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service\Attribute;

/**
 * A required dependency.
 *
 * This attribute indicates that a property holds a required dependency. The annotated property or method should be
 * considered during the instantiation process of the containing class.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
final class Required
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

/**
 * A ServiceProviderInterface that is also countable and iterable.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 *
 * @template-covariant T of mixed
 *
 * @extends ServiceProviderInterface<T>
 * @extends \IteratorAggregate<string, T>
 */
interface ServiceCollectionInterface extends ServiceProviderInterface, \Countable, \IteratorAggregate
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

use Symfony\Contracts\Service\Attribute\SubscribedService;

/**
 * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
 *
 * The getSubscribedServices method returns an array of service types required by such instances,
 * optionally keyed by the service names used internally. Service types that start with an interrogation
 * mark "?" are optional, while the other ones are mandatory service dependencies.
 *
 * The injected service locators SHOULD NOT allow access to any other services not specified by the method.
 *
 * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
 * This interface does not dictate any injection method for these service locators, although constructor
 * injection is recommended.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ServiceSubscriberInterface
{
    /**
     * Returns an array of service types (or {@see SubscribedService} objects) required
     * by such instances, optionally keyed by the service names used internally.
     *
     * For mandatory dependencies:
     *
     *  * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name
     *    internally to fetch a service which must implement Psr\Log\LoggerInterface.
     *  * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name
     *    internally to fetch an iterable of Psr\Log\LoggerInterface instances.
     *  * ['Psr\Log\LoggerInterface'] is a shortcut for
     *  * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface']
     *
     * otherwise:
     *
     *  * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency
     *  * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency
     *  * ['?Psr\Log\LoggerInterface'] is a shortcut for
     *  * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface']
     *
     * additionally, an array of {@see SubscribedService}'s can be returned:
     *
     *  * [new SubscribedService('logger', Psr\Log\LoggerInterface::class)]
     *  * [new SubscribedService(type: Psr\Log\LoggerInterface::class, nullable: true)]
     *  * [new SubscribedService('http_client', HttpClientInterface::class, attributes: new Target('githubApi'))]
     *
     * @return string[]|SubscribedService[] The required service types, optionally keyed by service names
     */
    public static function getSubscribedServices(): array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Contracts\Service;

use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

// Help opcache.preload discover always-needed symbols
class_exists(ContainerExceptionInterface::class);
class_exists(NotFoundExceptionInterface::class);

/**
 * A trait to help implement ServiceProviderInterface.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ServiceLocatorTrait
{
    private array $loading = [];
    private array $providedTypes;

    /**
     * @param array<string, callable> $factories
     */
    public function __construct(
        private array $factories,
    ) {
    }

    public function has(string $id): bool
    {
        return isset($this->factories[$id]);
    }

    public function get(string $id): mixed
    {
        if (!isset($this->factories[$id])) {
            throw $this->createNotFoundException($id);
        }

        if (isset($this->loading[$id])) {
            $ids = array_values($this->loading);
            $ids = \array_slice($this->loading, array_search($id, $ids));
            $ids[] = $id;

            throw $this->createCircularReferenceException($id, $ids);
        }

        $this->loading[$id] = $id;
        try {
            return $this->factories[$id]($this);
        } finally {
            unset($this->loading[$id]);
        }
    }

    public function getProvidedServices(): array
    {
        if (!isset($this->providedTypes)) {
            $this->providedTypes = [];

            foreach ($this->factories as $name => $factory) {
                if (!\is_callable($factory)) {
                    $this->providedTypes[$name] = '?';
                } else {
                    $type = (new \ReflectionFunction($factory))->getReturnType();

                    $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?';
                }
            }
        }

        return $this->providedTypes;
    }

    private function createNotFoundException(string $id): NotFoundExceptionInterface
    {
        if (!$alternatives = array_keys($this->factories)) {
            $message = 'is empty...';
        } else {
            $last = array_pop($alternatives);
            if ($alternatives) {
                $message = \sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last);
            } else {
                $message = \sprintf('only knows about the "%s" service.', $last);
            }
        }

        if ($this->loading) {
            $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message);
        } else {
            $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message);
        }

        return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface {
        };
    }

    private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface
    {
        return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface {
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php84 as p;

if (\PHP_VERSION_ID >= 80400) {
    return;
}

if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1): array|false { return p\Php84::grapheme_str_split($string, $length); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Polyfill\Php84;

/**
 * @author Ayesh Karunaratne <ayesh@aye.sh>
 * @author Pierre Ambroise <pierre27.ambroise@gmail.com>
 *
 * @internal
 */
final class Php84
{
    /** @return string|false */
    public static function mb_ucfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }

        try {
            $validEncoding = @mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }

        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding), \E_USER_WARNING);

                return false;
            }

            throw new \ValueError(\sprintf('mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }

        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);

        return $firstChar.mb_substr($string, 1, null, $encoding);
    }

    /** @return string|false */
    public static function mb_lcfirst(string $string, ?string $encoding = null)
    {
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }

        try {
            $validEncoding = @mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }

        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding), \E_USER_WARNING);

                return false;
            }

            throw new \ValueError(\sprintf('mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given', $encoding));
        }

        $firstChar = mb_substr($string, 0, 1, $encoding);
        $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);

        return $firstChar.mb_substr($string, 1, null, $encoding);
    }

    public static function array_find(array $array, callable $callback)
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return $value;
            }
        }

        return null;
    }

    public static function array_find_key(array $array, callable $callback)
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return $key;
            }
        }

        return null;
    }

    public static function array_any(array $array, callable $callback): bool
    {
        foreach ($array as $key => $value) {
            if ($callback($value, $key)) {
                return true;
            }
        }

        return false;
    }

    public static function array_all(array $array, callable $callback): bool
    {
        foreach ($array as $key => $value) {
            if (!$callback($value, $key)) {
                return false;
            }
        }

        return true;
    }

    public static function fpow(float $num, float $exponent): float
    {
        return $num ** $exponent;
    }

    /** @return string|false */
    public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
    }

    /** @return string|false */
    public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
    }

    /** @return string|false */
    public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null)
    {
        return self::mb_internal_trim('{[%s]+$}D', $string, $characters, $encoding, __FUNCTION__);
    }

    /** @return string|false */
    private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function)
    {
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }

        try {
            $validEncoding = @mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
        }

        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding), \E_USER_WARNING);

                return false;
            }

            throw new \ValueError(\sprintf('%s(): Argument #3 ($encoding) must be a valid encoding, "%s" given', $function, $encoding));
        }

        if ('' === $characters) {
            return null === $encoding ? $string : mb_convert_encoding($string, $encoding);
        }

        if ('UTF-8' === $encoding || \in_array(strtolower($encoding), ['utf-8', 'utf8'], true)) {
            $encoding = 'UTF-8';
        }

        $string = mb_convert_encoding($string, 'UTF-8', $encoding);

        if (null !== $characters) {
            $characters = mb_convert_encoding($characters, 'UTF-8', $encoding);
        }

        if (null === $characters) {
            $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}";
        } else {
            $characters = preg_quote($characters);
        }

        $string = preg_replace(\sprintf($regex, $characters), '', $string);

        if ('UTF-8' === $encoding) {
            return $string;
        }

        return mb_convert_encoding($string, $encoding, 'UTF-8');
    }

    public static function grapheme_str_split(string $string, int $length)
    {
        if (0 > $length || 1073741823 < $length) {
            throw new \ValueError('grapheme_str_split(): Argument #2 ($length) must be greater than 0 and less than or equal to 1073741823.');
        }

        if ('' === $string) {
            return [];
        }

        $regex = ((float) \PCRE_VERSION < 10 ? (float) \PCRE_VERSION >= 8.32 : (float) \PCRE_VERSION >= 10.39)
            ? '\X'
            : '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])';

        if (!preg_match_all('/'.$regex.'/u', $string, $matches)) {
            return false;
        }

        if (1 === $length) {
            return $matches[0];
        }

        $chunks = array_chunk($matches[0], $length);
        foreach ($chunks as &$chunk) {
            $chunk = implode('', $chunk);
        }

        return $chunks;
    }

    public static function bcceil(string $num): string
    {
        if (!is_numeric($num)) {
            throw new \ValueError('bcceil(): Argument #1 ($num) is not well-formed');
        }

        return self::bcround($num, 0, \RoundingMode::PositiveInfinity);
    }

    public static function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array
    {
        if (null === $quot = @bcdiv($num1, $num2, 0)) {
            throw new \DivisionByZeroError('Division by zero');
        }
        $scale = $scale ?? (\PHP_VERSION_ID >= 70300 ? bcscale() : (\ini_get('bcmath.scale') ?: 0));

        return [$quot, bcmod($num1, $num2, $scale)];
    }

    public static function bcfloor(string $num): string
    {
        if (!is_numeric($num)) {
            throw new \ValueError('bcfloor(): Argument #1 ($num) is not well-formed');
        }

        return self::bcround($num, 0, \RoundingMode::NegativeInfinity);
    }

    /**
     * @param \RoundingMode|\RoundingMode::* $mode
     */
    public static function bcround(string $num, int $precision = 0, $mode = \RoundingMode::HalfAwayFromZero): string
    {
        if (!is_numeric($num)) {
            throw new \ValueError('bcround(): Argument #1 ($num) is not well-formed');
        }

        $sign = 1;
        if ('' !== $num && ('-' === $num[0] || '+' === $num[0])) {
            if ('-' === $num[0]) {
                $sign = -1;
            }

            $num = substr($num, 1);
        }

        if (false !== strpos($num, '.')) {
            [$intPart, $fracPart] = array_pad(explode('.', $num, 2), 2, '');
        } else {
            $intPart = $num;
            $fracPart = '';
        }

        if ('' === $intPart) {
            $intPart = '0';
        }

        $intPart = self::trimLeadingZeros($intPart);
        $fracPart = (string) $fracPart;

        if ($precision >= 0) {
            $fracLength = \strlen($fracPart);

            if ($precision <= $fracLength) {
                $scaledInt = $intPart.(string) substr($fracPart, 0, $precision);
                $scaledFrac = (string) substr($fracPart, $precision);
            } else {
                $scaledInt = $intPart.$fracPart.str_repeat('0', $precision - $fracLength);
                $scaledFrac = '';
            }
        } else {
            $shift = -$precision;
            $intLength = \strlen($intPart);

            if ($shift <= $intLength) {
                $splitPos = $intLength - $shift;
                $scaledInt = substr($intPart, 0, $splitPos);
                $scaledInt = '' === $scaledInt ? '0' : $scaledInt;
                $scaledFrac = substr($intPart, $splitPos).$fracPart;
            } else {
                $scaledInt = '0';
                $scaledFrac = str_repeat('0', $shift - $intLength).$intPart.$fracPart;
            }
        }

        $roundedInt = self::roundIntegerPart($scaledInt, $scaledFrac, $sign, $mode);
        $isZero = '' === trim($roundedInt, '0');
        $absResult = self::formatRoundedDigits($roundedInt, $precision);

        if (-1 === $sign && !$isZero) {
            $absResult = '-'.$absResult;
        }

        return $absResult;
    }

    private static function roundIntegerPart(string $intPart, string $fracPart, int $sign, $mode): string
    {
        $intPart = self::trimLeadingZeros($intPart);

        if ('' === $fracPart || '' === trim($fracPart, '0')) {
            return $intPart;
        }

        $firstDigit = $fracPart[0];
        $tail = (string) substr($fracPart, 1);
        $tailNonZero = '' !== trim($tail, '0');
        $isGreaterThanHalf = $firstDigit > '5' || ('5' === $firstDigit && $tailNonZero);
        $isExactlyHalf = '5' === $firstDigit && !$tailNonZero;
        $shouldIncrease = false;

        switch ($mode) {
            case \RoundingMode::TowardsZero:
                break;

            case \RoundingMode::AwayFromZero:
                $shouldIncrease = true;
                break;

            case \RoundingMode::PositiveInfinity:
                $shouldIncrease = $sign > 0;
                break;

            case \RoundingMode::NegativeInfinity:
                $shouldIncrease = $sign < 0;
                break;

            case \RoundingMode::HalfAwayFromZero:
                $shouldIncrease = $isGreaterThanHalf || $isExactlyHalf;
                break;

            case \RoundingMode::HalfTowardsZero:
                $shouldIncrease = $isGreaterThanHalf;
                break;

            case \RoundingMode::HalfEven:
                if ($isGreaterThanHalf) {
                    $shouldIncrease = true;
                } elseif ($isExactlyHalf && 1 === self::lastDigit($intPart) % 2) {
                    $shouldIncrease = true;
                }
                break;

            case \RoundingMode::HalfOdd:
                if ($isGreaterThanHalf) {
                    $shouldIncrease = true;
                } elseif ($isExactlyHalf && 0 === self::lastDigit($intPart) % 2) {
                    $shouldIncrease = true;
                }
                break;
        }

        if ($shouldIncrease) {
            $intPart = self::incrementDigits($intPart);
        }

        return self::trimLeadingZeros($intPart);
    }

    private static function formatRoundedDigits(string $roundedInt, int $precision): string
    {
        if ($precision > 0) {
            if (\strlen($roundedInt) <= $precision) {
                $roundedInt = str_pad($roundedInt, $precision + 1, '0', \STR_PAD_LEFT);
            }

            $intDigits = substr($roundedInt, 0, -$precision);
            $fracDigits = substr($roundedInt, -$precision);

            $intDigits = self::trimLeadingZeros('' === $intDigits ? '0' : $intDigits);
            $fracDigits = str_pad($fracDigits, $precision, '0', \STR_PAD_LEFT);

            return $intDigits.'.'.$fracDigits;
        }

        if (0 === $precision) {
            return self::trimLeadingZeros($roundedInt);
        }

        $shift = -$precision;
        $digits = $roundedInt.str_repeat('0', $shift);

        return self::trimLeadingZeros($digits);
    }

    private static function incrementDigits(string $digits): string
    {
        $digits = '' === $digits ? '0' : $digits;
        $index = \strlen($digits) - 1;
        $result = $digits;
        $carry = 1;

        while ($index >= 0 && $carry) {
            $value = \ord($result[$index]) - 48 + $carry;
            $carry = $value >= 10 ? 1 : 0;
            $result[$index] = \chr(48 + ($value % 10));
            --$index;
        }

        return $carry ? '1'.$result : $result;
    }

    private static function trimLeadingZeros(string $digits): string
    {
        $digits = ltrim($digits, '0');

        return '' === $digits ? '0' : $digits;
    }

    private static function lastDigit(string $digits): int
    {
        $length = \strlen($digits);

        return $length ? \ord($digits[$length - 1]) - 48 : 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80400) {
    // @author Daniel Scherzer <daniel.e.scherzer@gmail.com>
    final class ReflectionConstant
    {
        /**
         * @var string
         *
         * @readonly
         */
        public $name;

        private $value;
        private $deprecated;

        private static $persistentConstants = [];

        public function __construct(string $name)
        {
            if (!defined($name) || false !== strpos($name, '::')) {
                throw new ReflectionException("Constant \"$name\" does not exist");
            }

            $this->name = ltrim($name, '\\');
            $deprecated = false;
            $eh = set_error_handler(static function ($type, $msg, $file, $line) use ($name, &$deprecated, &$eh) {
                if (\E_DEPRECATED === $type && "Constant $name is deprecated" === $msg) {
                    return $deprecated = true;
                }

                return $eh && $eh($type, $msg, $file, $line);
            });

            try {
                $this->value = constant($name);
                $this->deprecated = $deprecated;
            } finally {
                restore_error_handler();
            }
        }

        public function getName(): string
        {
            return $this->name;
        }

        public function getValue()
        {
            return $this->value;
        }

        public function getNamespaceName(): string
        {
            if (false === $slashPos = strrpos($this->name, '\\')) {
                return '';
            }

            return substr($this->name, 0, $slashPos);
        }

        public function getShortName(): string
        {
            if (false === $slashPos = strrpos($this->name, '\\')) {
                return $this->name;
            }

            return substr($this->name, $slashPos + 1);
        }

        public function isDeprecated(): bool
        {
            return $this->deprecated;
        }

        public function __toString(): string
        {
            // A constant is persistent if provided by PHP itself rather than
            // being defined by users. If we got here, we know that it *is*
            // defined, so we just need to figure out if it is defined by the
            // user or not
            if (!self::$persistentConstants) {
                $persistentConstants = get_defined_constants(true);
                unset($persistentConstants['user']);
                foreach ($persistentConstants as $constants) {
                    self::$persistentConstants += $constants;
                }
            }
            $persistent = array_key_exists($this->name, self::$persistentConstants);

            // Can't match the inclusion of `no_file_cache` but the rest is
            // possible to match
            $result = 'Constant [ ';
            if ($persistent || $this->deprecated) {
                $result .= '<';
                if ($persistent) {
                    $result .= 'persistent';
                    if ($this->deprecated) {
                        $result .= ', ';
                    }
                }
                if ($this->deprecated) {
                    $result .= 'deprecated';
                }
                $result .= '> ';
            }
            // Cannot just use gettype() to match zend_zval_type_name()
            if (is_object($this->value)) {
                $result .= \PHP_VERSION_ID >= 80000 ? get_debug_type($this->value) : gettype($this->value);
            } elseif (is_bool($this->value)) {
                $result .= 'bool';
            } elseif (is_int($this->value)) {
                $result .= 'int';
            } elseif (is_float($this->value)) {
                $result .= 'float';
            } elseif (null === $this->value) {
                $result .= 'null';
            } else {
                $result .= gettype($this->value);
            }
            $result .= ' ';
            $result .= $this->name;
            $result .= ' ] { ';
            if (is_array($this->value)) {
                $result .= 'Array';
            } else {
                // This will throw an exception if the value is an object that
                // cannot be converted to string; that is expected and matches
                // the behavior of zval_get_string_func()
                $result .= (string) $this->value;
            }
            $result .= " }\n";

            return $result;
        }

        public function __sleep(): array
        {
            throw new Exception("Serialization of 'ReflectionConstant' is not allowed");
        }

        public function __wakeup(): void
        {
            throw new Exception("Unserialization of 'ReflectionConstant' is not allowed");
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_sqlite')) {
    class Sqlite extends \PDO
    {
        public const ATTR_EXTENDED_RESULT_CODES = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES : 1002;
        public const ATTR_OPEN_FLAGS = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_ATTR_OPEN_FLAGS : 1000;
        public const ATTR_READONLY_STATEMENT = \PHP_VERSION_ID >= 70400 ? \PDO::SQLITE_ATTR_READONLY_STATEMENT : 1001;
        public const DETERMINISTIC = \PDO::SQLITE_DETERMINISTIC;
        public const OPEN_READONLY = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READONLY : 1;
        public const OPEN_READWRITE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_READWRITE : 2;
        public const OPEN_CREATE = \PHP_VERSION_ID >= 70300 ? \PDO::SQLITE_OPEN_CREATE : 4;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('sqlite' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Sqlite::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Sqlite::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Sqlite::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }

        public function createAggregate(string $name, callable $step, callable $finalize, int $numArgs = -1): bool
        {
            return $this->sqliteCreateAggregate($name, $step, $finalize, $numArgs);
        }

        public function createCollation(string $name, callable $callback): bool
        {
            return $this->sqliteCreateCollation($name, $callback);
        }

        public function createFunction(string $function_name, callable $callback, int $num_args = -1, int $flags = 0): bool
        {
            return $this->sqliteCreateFunction($function_name, $callback, $num_args, $flags);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_firebird')) {
    class Firebird extends \PDO
    {
        public const ATTR_DATE_FORMAT = \PDO::FB_ATTR_DATE_FORMAT;
        public const ATTR_TIME_FORMAT = \PDO::FB_ATTR_TIME_FORMAT;
        public const ATTR_TIMESTAMP_FORMAT = \PDO::FB_ATTR_TIMESTAMP_FORMAT;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('firebird' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Firebird::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Firebird::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Firebird::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_dblib')) {
    class Dblib extends \PDO
    {
        public const ATTR_CONNECTION_TIMEOUT = \PDO::DBLIB_ATTR_CONNECTION_TIMEOUT;
        public const ATTR_QUERY_TIMEOUT = \PDO::DBLIB_ATTR_QUERY_TIMEOUT;
        public const ATTR_STRINGIFY_UNIQUEIDENTIFIER = \PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER;
        public const ATTR_VERSION = \PDO::DBLIB_ATTR_VERSION;
        public const ATTR_TDS_VERSION = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_TDS_VERSION : 1004;
        public const ATTR_SKIP_EMPTY_ROWSETS = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS : 1005;
        public const ATTR_DATETIME_CONVERT = \PHP_VERSION_ID >= 70300 ? \PDO::DBLIB_ATTR_DATETIME_CONVERT : 1006;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('dblib' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Dblib::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Dblib::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Dblib::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_odbc')) {
    class Odbc extends \PDO
    {
        public const ATTR_USE_CURSOR_LIBRARY = \PDO::ODBC_ATTR_USE_CURSOR_LIBRARY;
        public const ATTR_ASSUME_UTF8 = \PDO::ODBC_ATTR_ASSUME_UTF8;
        public const SQL_USE_IF_NEEDED = \PDO::ODBC_SQL_USE_IF_NEEDED;
        public const SQL_USE_DRIVER = \PDO::ODBC_SQL_USE_DRIVER;
        public const SQL_USE_ODBC = \PDO::ODBC_SQL_USE_ODBC;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('odbc' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Odbc::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Odbc::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Odbc::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

use PDO;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_mysql')) {
    // Feature detection for non-mysqlnd; see also https://www.php.net/manual/en/class.pdo-mysql.php#pdo-mysql.constants.attr-max-buffer-size
    if (\defined('PDO::MYSQL_ATTR_MAX_BUFFER_SIZE') && \defined('PDO::MYSQL_ATTR_READ_DEFAULT_FILE') && \defined('PDO::MYSQL_ATTR_READ_DEFAULT_GROUP')) {
        class Mysql extends \PDO
        {
            public const ATTR_COMPRESS = \PDO::MYSQL_ATTR_COMPRESS;
            public const ATTR_DIRECT_QUERY = \PDO::MYSQL_ATTR_DIRECT_QUERY;
            public const ATTR_FOUND_ROWS = \PDO::MYSQL_ATTR_FOUND_ROWS;
            public const ATTR_IGNORE_SPACE = \PDO::MYSQL_ATTR_IGNORE_SPACE;
            public const ATTR_INIT_COMMAND = \PDO::MYSQL_ATTR_INIT_COMMAND;
            public const ATTR_LOCAL_INFILE = \PDO::MYSQL_ATTR_LOCAL_INFILE;
            public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015;
            public const ATTR_MAX_BUFFER_SIZE = \PDO::MYSQL_ATTR_MAX_BUFFER_SIZE;
            public const ATTR_MULTI_STATEMENTS = \PDO::MYSQL_ATTR_MULTI_STATEMENTS;
            public const ATTR_READ_DEFAULT_FILE = \PDO::MYSQL_ATTR_READ_DEFAULT_FILE;
            public const ATTR_READ_DEFAULT_GROUP = \PDO::MYSQL_ATTR_READ_DEFAULT_GROUP;
            public const ATTR_SERVER_PUBLIC_KEY = \PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY;
            public const ATTR_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA;
            public const ATTR_SSL_CAPATH = \PDO::MYSQL_ATTR_SSL_CAPATH;
            public const ATTR_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT;
            public const ATTR_SSL_CIPHER = \PDO::MYSQL_ATTR_SSL_CIPHER;
            public const ATTR_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY;
            public const ATTR_SSL_VERIFY_SERVER_CERT = \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT;
            public const ATTR_USE_BUFFERED_QUERY = \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY;

            public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
            {
                parent::__construct($dsn, $username, $password, $options);

                if ('mysql' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                    throw new \PDOException(\sprintf('Pdo\Mysql::__construct() cannot be used for connecting to the "%s" driver', $driver));
                }
            }

            public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
            {
                try {
                    return new self($dsn, $username, $password, $options);
                } catch (\PDOException $e) {
                    throw preg_match('/^Pdo\\\\Mysql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Mysql::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
                }
            }
        }
    } else {
        class Mysql extends \PDO
        {
            public const ATTR_COMPRESS = \PDO::MYSQL_ATTR_COMPRESS;
            public const ATTR_DIRECT_QUERY = \PDO::MYSQL_ATTR_DIRECT_QUERY;
            public const ATTR_FOUND_ROWS = \PDO::MYSQL_ATTR_FOUND_ROWS;
            public const ATTR_IGNORE_SPACE = \PDO::MYSQL_ATTR_IGNORE_SPACE;
            public const ATTR_INIT_COMMAND = \PDO::MYSQL_ATTR_INIT_COMMAND;
            public const ATTR_LOCAL_INFILE = \PDO::MYSQL_ATTR_LOCAL_INFILE;
            public const ATTR_LOCAL_INFILE_DIRECTORY = \PHP_VERSION_ID >= 80100 ? \PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY : 1015;
            // public const ATTR_MAX_BUFFER_SIZE = PDO::MYSQL_ATTR_MAX_BUFFER_SIZE; // disabled for mysqlnd
            public const ATTR_MULTI_STATEMENTS = \PDO::MYSQL_ATTR_MULTI_STATEMENTS;
            // public const ATTR_READ_DEFAULT_FILE = PDO::MYSQL_ATTR_READ_DEFAULT_FILE; // disabled for mysqlnd
            // public const ATTR_READ_DEFAULT_GROUP = PDO::MYSQL_ATTR_READ_DEFAULT_GROUP; // disabled for mysqlnd
            public const ATTR_SERVER_PUBLIC_KEY = \PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY;
            public const ATTR_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA;
            public const ATTR_SSL_CAPATH = \PDO::MYSQL_ATTR_SSL_CAPATH;
            public const ATTR_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT;
            public const ATTR_SSL_CIPHER = \PDO::MYSQL_ATTR_SSL_CIPHER;
            public const ATTR_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY;
            public const ATTR_SSL_VERIFY_SERVER_CERT = \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT;
            public const ATTR_USE_BUFFERED_QUERY = \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY;

            public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
            {
                parent::__construct($dsn, $username, $password, $options);

                if ('mysql' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                    throw new \PDOException(\sprintf('Pdo\Mysql::__construct() cannot be used for connecting to the "%s" driver', $driver));
                }
            }

            public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
            {
                try {
                    return new self($dsn, $username, $password, $options);
                } catch (\PDOException $e) {
                    throw preg_match('/^Pdo\\\\Mysql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Mysql::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Pdo;

if (\PHP_VERSION_ID < 80400 && \extension_loaded('pdo_pgsql')) {
    class Pgsql extends \PDO
    {
        public const ATTR_DISABLE_PREPARES = \PDO::PGSQL_ATTR_DISABLE_PREPARES;

        public function __construct(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null)
        {
            parent::__construct($dsn, $username, $password, $options);

            if ('pgsql' !== $driver = $this->getAttribute(\PDO::ATTR_DRIVER_NAME)) {
                throw new \PDOException(\sprintf('Pdo\Pgsql::__construct() cannot be used for connecting to the "%s" driver', $driver));
            }
        }

        public static function connect(string $dsn, ?string $username = null, ?string $password = null, ?array $options = null): self
        {
            try {
                return new self($dsn, $username, $password, $options);
            } catch (\PDOException $e) {
                throw preg_match('/^Pdo\\\\Pgsql::__construct\(\) cannot be used for connecting to the "([a-z]+)" driver/', $e->getMessage(), $matches) ? new \PDOException(\sprintf('Pdo\Pgsql::connect() cannot be used for connecting to the "%s" driver', $matches[1])) : $e;
            }
        }

        public function copyFromArray(string $tableName, array $rows, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null): bool
        {
            return $this->pgsqlCopyFromArray($tableName, $rows, $separator, $nullAs, $fields);
        }

        public function copyFromFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null): bool
        {
            return $this->pgsqlCopyFromFile($tableName, $filename, $separator, $nullAs, $fields);
        }

        /**
         * @return array|false
         */
        public function copyToArray(string $tableName, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null)
        {
            return $this->pgsqlCopyToArray($tableName, $separator, $nullAs, $fields);
        }

        public function copyToFile(string $tableName, string $filename, string $separator = "\t", string $nullAs = '\\\\N', ?string $fields = null): bool
        {
            return $this->pgsqlCopyToFile($tableName, $filename, $separator, $nullAs, $fields);
        }

        /**
         * @return array|false
         */
        public function getNotify(int $fetchMode = \PDO::FETCH_DEFAULT, int $timeoutMilliseconds = 0)
        {
            return $this->pgsqlGetNotify($fetchMode, $timeoutMilliseconds);
        }

        public function getPid(): int
        {
            return $this->pgsqlGetPid();
        }

        /**
         * @return string|false
         */
        public function lobCreate()
        {
            return $this->pgsqlLOBCreate();
        }

        /**
         * @return resource|false
         */
        public function lobOpen(string $oid, string $mode = 'rb')
        {
            return $this->pgsqlLOBOpen($oid, $mode);
        }

        public function lobUnlink(string $oid): bool
        {
            return $this->pgsqlLOBUnlink($oid);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80100) {
    final class RoundingMode
    {
        const HalfAwayFromZero = 0;
        const HalfTowardsZero = 1;
        const HalfEven = 2;
        const HalfOdd = 3;
        const TowardsZero = 4;
        const AwayFromZero = 5;
        const NegativeInfinity = 6;
        const PositiveInfinity = 7;

        private function __construct()
        {
        }

        public static function cases(): array
        {
            return [
                self::HalfAwayFromZero,
                self::HalfTowardsZero,
                self::HalfEven,
                self::HalfOdd,
                self::TowardsZero,
                self::AwayFromZero,
                self::NegativeInfinity,
                self::PositiveInfinity,
            ];
        }
    }
} elseif (\PHP_VERSION_ID < 80400) {
    require dirname(__DIR__).'/RoundingMode.php';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80100) {
    #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::TARGET_CLASS_CONSTANT)]
    final class Deprecated
    {
        /**
         * @readonly
         */
        public ?string $message;

        /**
         * @readonly
         */
        public ?string $since;

        public function __construct(?string $message = null, ?string $since = null)
        {
            $this->message = $message;
            $this->since = $since;
        }
    }
} elseif (\PHP_VERSION_ID < 80400) {
    require dirname(__DIR__).'/Deprecated.php';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80400) {
    enum RoundingMode
    {
        case HalfAwayFromZero;
        case HalfTowardsZero;
        case HalfEven;
        case HalfOdd;
        case TowardsZero;
        case AwayFromZero;
        case NegativeInfinity;
        case PositiveInfinity;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

if (\PHP_VERSION_ID < 80400) {
    #[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::TARGET_CLASS_CONSTANT)]
    final class Deprecated
    {
        public readonly ?string $message;
        public readonly ?string $since;

        public function __construct(?string $message = null, ?string $since = null)
        {
            $this->message = $message;
            $this->since = $since;
        }
    }
}
Copyright (c) 2024-present Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php84 as p;

if (\PHP_VERSION_ID >= 80400) {
    return;
}

if (defined('CURL_VERSION_HTTP3') || \PHP_VERSION_ID < 80200 && function_exists('curl_version') && curl_version()['version'] >= 0x074200) { // libcurl >= 7.66.0
    if (!defined('CURL_HTTP_VERSION_3')) {
        define('CURL_HTTP_VERSION_3', 30);
    }

    if (!defined('CURL_HTTP_VERSION_3ONLY') && defined('CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256')) { // libcurl >= 7.80.0 (7.88 would be better but is slow to check)
        define('CURL_HTTP_VERSION_3ONLY', 31);
    }
}

if (!function_exists('array_find')) {
    function array_find(array $array, callable $callback) { return p\Php84::array_find($array, $callback); }
}

if (!function_exists('array_find_key')) {
    function array_find_key(array $array, callable $callback) { return p\Php84::array_find_key($array, $callback); }
}

if (!function_exists('array_any')) {
    function array_any(array $array, callable $callback): bool { return p\Php84::array_any($array, $callback); }
}

if (!function_exists('array_all')) {
    function array_all(array $array, callable $callback): bool { return p\Php84::array_all($array, $callback); }
}

if (!function_exists('fpow')) {
    function fpow(float $num, float $exponent): float { return p\Php84::fpow($num, $exponent); }
}

if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__.'/bootstrap80.php';
}

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_ucfirst')) {
        function mb_ucfirst(string $string, ?string $encoding = null) { return p\Php84::mb_ucfirst($string, $encoding); }
    }

    if (!function_exists('mb_lcfirst')) {
        function mb_lcfirst(string $string, ?string $encoding = null) { return p\Php84::mb_lcfirst($string, $encoding); }
    }

    if (!function_exists('mb_trim')) {
        function mb_trim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Php84::mb_trim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_ltrim')) {
        function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Php84::mb_ltrim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_rtrim')) {
        function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Php84::mb_rtrim($string, $characters, $encoding); }
    }
}

if (extension_loaded('bcmath')) {
    if (!function_exists('bcceil')) {
        function bcceil(string $num): string { return p\Php84::bcceil($num); }
    }
    if (!function_exists('bcdivmod')) {
        function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { return p\Php84::bcdivmod($num1, $num2, $scale); }
    }
    if (!function_exists('bcfloor')) {
        function bcfloor(string $num): string { return p\Php84::bcfloor($num); }
    }
    if (!function_exists('bcround')) {
        function bcround(string $num, int $precision = 0, $mode = RoundingMode::HalfAwayFromZero): string { return p\Php84::bcround($num, $precision, $mode); }
    }
}

if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1) { return p\Php84::grapheme_str_split($string, $length); }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Symfony\Polyfill\Php84 as p;

if (extension_loaded('mbstring')) {
    if (!function_exists('mb_ucfirst')) {
        function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Php84::mb_ucfirst($string, $encoding); }
    }

    if (!function_exists('mb_lcfirst')) {
        function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Php84::mb_lcfirst($string, $encoding); }
    }

    if (!function_exists('mb_trim')) {
        function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_trim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_ltrim')) {
        function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_ltrim($string, $characters, $encoding); }
    }

    if (!function_exists('mb_rtrim')) {
        function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Php84::mb_rtrim($string, $characters, $encoding); }
    }
}

if (extension_loaded('bcmath')) {
    if (!function_exists('bcceil')) {
        function bcceil(string $num): string { return p\Php84::bcceil($num); }
    }
    if (!function_exists('bcdivmod')) {
        function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { return p\Php84::bcdivmod($num1, $num2, $scale); }
    }
    if (!function_exists('bcfloor')) {
        function bcfloor(string $num): string { return p\Php84::bcfloor($num); }
    }
    if (!function_exists('bcround')) {
        function bcround(string $num, int $precision = 0, $mode = RoundingMode::HalfAwayFromZero): string { return p\Php84::bcround($num, $precision, $mode); }
    }
}

if (\PHP_VERSION_ID >= 80200) {
    return require __DIR__.'/bootstrap82.php';
}

if (extension_loaded('intl') && !function_exists('grapheme_str_split')) {
    function grapheme_str_split(string $string, int $length = 1) { return p\Php84::grapheme_str_split($string, $length); }
}
<?php

declare(strict_types=1);

namespace voku\helper;

/**
 * ## 🇷🇺 Русским гражданам
 * В Украине сейчас идет война. Силами РФ наносятся удары по гражданской инфраструктуре в [Харькове][1], [Киеве][2], [Чернигове][3], [Сумах][4], [Ирпене][5] и десятках других городов. Гибнут люди - и гражданское население, и военные, в том числе российские призывники, которых бросили воевать. Чтобы лишить собственный народ доступа к информации, правительство РФ запретило называть войну войной, закрыло независимые СМИ и принимает сейчас ряд диктаторских законов. Эти законы призваны заткнуть рот всем, кто против войны. За обычный призыв к миру сейчас можно получить несколько лет тюрьмы.
 * Не молчите! Молчание - знак вашего согласия с политикой российского правительства.
 *  **Вы можете сделать выбор НЕ МОЛЧАТЬ.**
 * ---
 * ## 🇺🇸 To people of Russia
 * There is a war in Ukraine right now. The forces of the Russian Federation are attacking civilian infrastructure in [Kharkiv][1], [Kyiv][2], [Chernihiv][3], [Sumy][4], [Irpin][5] and dozens of other cities. People are dying – both civilians and military servicemen, including Russian conscripts who were thrown into the fighting. In order to deprive its own people of access to information, the government of the Russian Federation has forbidden calling a war a war, shut down independent media and is passing a number of dictatorial laws. These laws are meant to silence all those who are against war. You can be jailed for multiple years for simply calling for peace.
 * Do not be silent! Silence is a sign that you accept the Russian government's policy.
 * **You can choose NOT TO BE SILENT.**
 * ---
 * - [1] https://cloudfront-us-east-2.images.arcpublishing.com/reuters/P7K2MSZDGFMIJPDD7CI2GIROJI.jpg "Kharkiv under attack"
 * - [2] https://gdb.voanews.com/01bd0000-0aff-0242-fad0-08d9fc92c5b3_cx0_cy5_cw0_w1023_r1_s.jpg "Kyiv under attack"
 * - [3] https://ichef.bbci.co.uk/news/976/cpsprodpb/163DD/production/_123510119_hi074310744.jpg "Chernihiv under attack"
 * - [4] https://www.youtube.com/watch?v=8K-bkqKKf2A "Sumy under attack"
 * - [5] https://cloudfront-us-east-2.images.arcpublishing.com/reuters/K4MTMLEHTRKGFK3GSKAT4GR3NE.jpg "Irpin under attack"
 *
 * @psalm-immutable
 */
final class ASCII
{
    //
    // INFO: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
    //

    const UZBEK_LANGUAGE_CODE = 'uz';

    const TURKMEN_LANGUAGE_CODE = 'tk';

    const THAI_LANGUAGE_CODE = 'th';

    const PASHTO_LANGUAGE_CODE = 'ps';

    const ORIYA_LANGUAGE_CODE = 'or';

    const MONGOLIAN_LANGUAGE_CODE = 'mn';

    const KOREAN_LANGUAGE_CODE = 'ko';

    const KIRGHIZ_LANGUAGE_CODE = 'ky';

    const ARMENIAN_LANGUAGE_CODE = 'hy';

    const BENGALI_LANGUAGE_CODE = 'bn';

    const BELARUSIAN_LANGUAGE_CODE = 'be';

    const AMHARIC_LANGUAGE_CODE = 'am';

    const JAPANESE_LANGUAGE_CODE = 'ja';

    const CHINESE_LANGUAGE_CODE = 'zh';

    const DUTCH_LANGUAGE_CODE = 'nl';

    const ITALIAN_LANGUAGE_CODE = 'it';

    const MACEDONIAN_LANGUAGE_CODE = 'mk';

    const PORTUGUESE_LANGUAGE_CODE = 'pt';

    const GREEKLISH_LANGUAGE_CODE = 'el__greeklish';

    const GREEK_LANGUAGE_CODE = 'el';

    const HINDI_LANGUAGE_CODE = 'hi';

    const SWEDISH_LANGUAGE_CODE = 'sv';

    const TURKISH_LANGUAGE_CODE = 'tr';

    const BULGARIAN_LANGUAGE_CODE = 'bg';

    const HUNGARIAN_LANGUAGE_CODE = 'hu';

    const MYANMAR_LANGUAGE_CODE = 'my';

    const CROATIAN_LANGUAGE_CODE = 'hr';

    const FINNISH_LANGUAGE_CODE = 'fi';

    const GEORGIAN_LANGUAGE_CODE = 'ka';

    const RUSSIAN_LANGUAGE_CODE = 'ru';

    const RUSSIAN_PASSPORT_2013_LANGUAGE_CODE = 'ru__passport_2013';

    const RUSSIAN_GOST_2000_B_LANGUAGE_CODE = 'ru__gost_2000_b';

    const UKRAINIAN_LANGUAGE_CODE = 'uk';

    const KAZAKH_LANGUAGE_CODE = 'kk';

    const CZECH_LANGUAGE_CODE = 'cs';

    const DANISH_LANGUAGE_CODE = 'da';

    const POLISH_LANGUAGE_CODE = 'pl';

    const ROMANIAN_LANGUAGE_CODE = 'ro';

    const ESPERANTO_LANGUAGE_CODE = 'eo';

    const ESTONIAN_LANGUAGE_CODE = 'et';

    const LATVIAN_LANGUAGE_CODE = 'lv';

    const LITHUANIAN_LANGUAGE_CODE = 'lt';

    const NORWEGIAN_LANGUAGE_CODE = 'no';

    const VIETNAMESE_LANGUAGE_CODE = 'vi';

    const ARABIC_LANGUAGE_CODE = 'ar';

    const PERSIAN_LANGUAGE_CODE = 'fa';

    const SERBIAN_LANGUAGE_CODE = 'sr';

    const SERBIAN_CYRILLIC_LANGUAGE_CODE = 'sr__cyr';

    const SERBIAN_LATIN_LANGUAGE_CODE = 'sr__lat';

    const AZERBAIJANI_LANGUAGE_CODE = 'az';

    const SLOVAK_LANGUAGE_CODE = 'sk';

    const FRENCH_LANGUAGE_CODE = 'fr';

    const FRENCH_AUSTRIAN_LANGUAGE_CODE = 'fr_at';

    const FRENCH_SWITZERLAND_LANGUAGE_CODE = 'fr_ch';

    const GERMAN_LANGUAGE_CODE = 'de';

    const GERMAN_AUSTRIAN_LANGUAGE_CODE = 'de_at';

    const GERMAN_SWITZERLAND_LANGUAGE_CODE = 'de_ch';

    const ENGLISH_LANGUAGE_CODE = 'en';

    const EXTRA_LATIN_CHARS_LANGUAGE_CODE = 'latin';

    const EXTRA_WHITESPACE_CHARS_LANGUAGE_CODE = ' ';

    const EXTRA_MSWORD_CHARS_LANGUAGE_CODE = 'msword';

    /**
     * @var array<string, array<string, string>>|null
     */
    private static $ASCII_MAPS;

    /**
     * @var array<string, array<string, string>>|null
     */
    private static $ASCII_MAPS_AND_EXTRAS;

    /**
     * @var array<string, array<string, string>>|null
     */
    private static $ASCII_EXTRAS;

    /**
     * @var array<string, int>|null
     */
    private static $ORD;

    /**
     * url: https://en.wikipedia.org/wiki/Wikipedia:ASCII#ASCII_printable_characters
     *
     * @var string
     */
    private static $REGEX_ASCII = "[^\x09\x10\x13\x0A\x0D\x20-\x7E]";

    private const REGEX_PRINTABLE_ASCII = '[^\x20-\x7E]';

    /**
     * bidirectional text chars
     *
     * url: https://www.w3.org/International/questions/qa-bidi-unicode-controls
     *
     * @var array<int, string>
     */
    private static $BIDI_UNI_CODE_CONTROLS_TABLE = [
        // LEFT-TO-RIGHT EMBEDDING (use -> dir = "ltr")
        8234 => "\xE2\x80\xAA",
        // RIGHT-TO-LEFT EMBEDDING (use -> dir = "rtl")
        8235 => "\xE2\x80\xAB",
        // POP DIRECTIONAL FORMATTING // (use -> </bdo>)
        8236 => "\xE2\x80\xAC",
        // LEFT-TO-RIGHT OVERRIDE // (use -> <bdo dir = "ltr">)
        8237 => "\xE2\x80\xAD",
        // RIGHT-TO-LEFT OVERRIDE // (use -> <bdo dir = "rtl">)
        8238 => "\xE2\x80\xAE",
        // LEFT-TO-RIGHT ISOLATE // (use -> dir = "ltr")
        8294 => "\xE2\x81\xA6",
        // RIGHT-TO-LEFT ISOLATE // (use -> dir = "rtl")
        8295 => "\xE2\x81\xA7",
        // FIRST STRONG ISOLATE // (use -> dir = "auto")
        8296 => "\xE2\x81\xA8",
        // POP DIRECTIONAL ISOLATE
        8297 => "\xE2\x81\xA9",
    ];

    /**
     * Transliteration placeholders used by the generated data tables.
     *
     * @var array<string, true>
     */
    private const UNKNOWN_TRANSLITERATION_MARKERS = [
        '[?]' => true,
        '[?] ' => true,
    ];

    /**
     * Match exactly the structurally valid multibyte UTF-8 sequences defined by RFC 3629.
     *
     * The ranges mirror those used in clean() and deliberately exclude:
     *   - 0xC0/0xC1 lead bytes (overlong 2-byte sequences such as "\xC0\xAF" for "/")
     *   - \xE0 followed by \x80–\x9F (overlong 3-byte sequences)
     *   - \xED followed by \xA0–\xBF (UTF-16 surrogate halves U+D800–U+DFFF)
     *   - \xF0 followed by \x80–\x8F (overlong 4-byte sequences)
     *   - \xF4 followed by \x90–\xBF, and \xF5–\xFF (code points above U+10FFFF)
     *
     * Without this strictness the later ordinal arithmetic (ord – 192/224/240) would
     * silently decode overlong sequences into their ASCII equivalents (e.g. "\xC0\xAF" → "/"),
     * introducing an input-sanitization bypass even though clean() already strips them.
     *
     * @var string
     */
    private const UTF8_MULTIBYTE_SEQUENCE_RX = '/[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE-\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}/';


    /**
     * Get all languages from the constants "ASCII::.*LANGUAGE_CODE".
     *
     * @return array<string, string>
     *                                 <p>An associative array where the key is the language code in lowercase
     *                                 and the value is the corresponding language string.</p>
     */
    public static function getAllLanguages(): array
    {
        // init
        static $LANGUAGES = [];

        if ($LANGUAGES !== []) {
            return $LANGUAGES;
        }

        foreach ((new \ReflectionClass(__CLASS__))->getConstants() as $constant => $lang) {
            if (\strpos($constant, 'EXTRA') !== false) {
                $LANGUAGES[\strtolower($constant)] = $lang;
            } else {
                $LANGUAGES[\strtolower(\str_replace('_LANGUAGE_CODE', '', $constant))] = $lang;
            }
        }

        return $LANGUAGES;
    }

    /**
     * Returns an replacement array for ASCII methods.
     *
     * EXAMPLE: <code>
     * $array = ASCII::charsArray();
     * var_dump($array['ru']['б']); // 'b'
     * </code>
     *
     * @param bool $replace_extra_symbols [optional] <p>Add some more replacements e.g. "£" with " pound ".</p>
     *
     * @psalm-pure
     *
     * @return array<string, array<string , string>>
     *                                               <p>An array where the key is the language code, and the value is
     *                                               an associative array mapping original characters to their replacements.</p>
     */
    public static function charsArray(bool $replace_extra_symbols = false): array
    {
        if ($replace_extra_symbols) {
            self::prepareAsciiAndExtrasMaps();

            return self::$ASCII_MAPS_AND_EXTRAS ?? [];
        }

        self::prepareAsciiMaps();

        return self::$ASCII_MAPS ?? [];
    }

    /**
     * Returns an replacement array for ASCII methods with a mix of multiple languages.
     *
     * EXAMPLE: <code>
     * $array = ASCII::charsArrayWithMultiLanguageValues();
     * var_dump($array['b']); // ['β', 'б', 'ဗ', 'ბ', 'ب']
     * </code>
     *
     * @param bool $replace_extra_symbols [optional] <p>Add some more replacements e.g. "£" with " pound ".</p>
     *
     * @psalm-pure
     *
     * @return array<string, list<string>>
     *                                     <p>An array of replacements.</p>
     */
    public static function charsArrayWithMultiLanguageValues(bool $replace_extra_symbols = false): array
    {
        static $CHARS_ARRAY = [];
        $cacheKey = '' . $replace_extra_symbols;

        if (isset($CHARS_ARRAY[$cacheKey])) {
            return $CHARS_ARRAY[$cacheKey];
        }

        // init
        $return = [];
        $language_all_chars = self::charsArrayWithSingleLanguageValues(
            $replace_extra_symbols,
            false
        );

        /* @noinspection AlterInForeachInspection | ok here */
        foreach ($language_all_chars as $key => &$value) {
            $return[$value][] = $key;
        }

        $CHARS_ARRAY[$cacheKey] = $return;

        return $return;
    }

    /**
     * Returns an replacement array for ASCII methods with one language.
     *
     * For example, German will map 'ä' to 'ae', while other languages
     * will simply return e.g. 'a'.
     *
     * EXAMPLE: <code>
     * $array = ASCII::charsArrayWithOneLanguage('ru');
     * $tmpKey = \array_search('yo', $array['replace']);
     * echo $array['orig'][$tmpKey]; // 'ё'
     * </code>
     *
     * @param string $language              [optional] <p>Language of the source string e.g.: en, de_at, or de-ch.
     *                                      (default is 'en') | ASCII::*_LANGUAGE_CODE</p>
     * @param bool   $replace_extra_symbols [optional] <p>Add some more replacements e.g. "£" with " pound ".</p>
     * @param bool   $asOrigReplaceArray    [optional] <p>TRUE === return {orig: list<string>, replace: list<string>}
     *                                      array</p>
     *
     * @psalm-pure
     *
     * @return ($asOrigReplaceArray is true ? array{orig: list<string>, replace: list<string>} : array<string, string>)
     *
     * @phpstan-param ASCII::*_LANGUAGE_CODE $language
     */
    public static function charsArrayWithOneLanguage(
        string $language = self::ENGLISH_LANGUAGE_CODE,
        bool $replace_extra_symbols = false,
        bool $asOrigReplaceArray = true
    ): array {
        $language = self::get_language($language);

        // init
        static $CHARS_ARRAY = [];
        $cacheKey = '' . $replace_extra_symbols . '-' . $asOrigReplaceArray;

        // check static cache
        if (isset($CHARS_ARRAY[$cacheKey][$language])) {
            return $CHARS_ARRAY[$cacheKey][$language];
        }

        if ($replace_extra_symbols) {
            self::prepareAsciiAndExtrasMaps();

            if (isset(self::$ASCII_MAPS_AND_EXTRAS[$language])) {
                $tmpArray = self::$ASCII_MAPS_AND_EXTRAS[$language];

                if ($asOrigReplaceArray) {
                    $CHARS_ARRAY[$cacheKey][$language] = [
                        'orig'    => \array_keys($tmpArray),
                        'replace' => \array_values($tmpArray),
                    ];
                } else {
                    $CHARS_ARRAY[$cacheKey][$language] = $tmpArray;
                }
            } else {
                if ($asOrigReplaceArray) {
                    $CHARS_ARRAY[$cacheKey][$language] = [
                        'orig'    => [],
                        'replace' => [],
                    ];
                } else {
                    $CHARS_ARRAY[$cacheKey][$language] = [];
                }
            }
        } else {
            self::prepareAsciiMaps();

            if (isset(self::$ASCII_MAPS[$language])) {
                $tmpArray = self::$ASCII_MAPS[$language];

                if ($asOrigReplaceArray) {
                    $CHARS_ARRAY[$cacheKey][$language] = [
                        'orig'    => \array_keys($tmpArray),
                        'replace' => \array_values($tmpArray),
                    ];
                } else {
                    $CHARS_ARRAY[$cacheKey][$language] = $tmpArray;
                }
            } else {
                if ($asOrigReplaceArray) {
                    $CHARS_ARRAY[$cacheKey][$language] = [
                        'orig'    => [],
                        'replace' => [],
                    ];
                } else {
                    $CHARS_ARRAY[$cacheKey][$language] = [];
                }
            }
        }

        return $CHARS_ARRAY[$cacheKey][$language] ?? ['orig' => [], 'replace' => []];
    }

    /**
     * Returns an replacement array for ASCII methods with multiple languages.
     *
     * EXAMPLE: <code>
     * $array = ASCII::charsArrayWithSingleLanguageValues();
     * $tmpKey = \array_search('hnaik', $array['replace']);
     * echo $array['orig'][$tmpKey]; // '၌'
     * </code>
     *
     * @param bool $replace_extra_symbols [optional] <p>Add some more replacements e.g. "£" with " pound ".</p>
     * @param bool $asOrigReplaceArray    [optional] <p>TRUE === return {orig: list<string>, replace: list<string>}
     *                                    array</p>
     *
     * @psalm-pure
     *
     * @return ($asOrigReplaceArray is true ? array{orig: list<string>, replace: list<string>} : array<string, string>)
     */
    public static function charsArrayWithSingleLanguageValues(
        bool $replace_extra_symbols = false,
        bool $asOrigReplaceArray = true
    ): array {
        // init
        static $CHARS_ARRAY = [];
        $cacheKey = '' . $replace_extra_symbols . '-' . $asOrigReplaceArray;

        if (isset($CHARS_ARRAY[$cacheKey])) {
            return $CHARS_ARRAY[$cacheKey];
        }

        if ($replace_extra_symbols) {
            self::prepareAsciiAndExtrasMaps();

            /* @noinspection AlterInForeachInspection | ok here */
            foreach (self::$ASCII_MAPS_AND_EXTRAS ?? [] as &$map) {
                $CHARS_ARRAY[$cacheKey][] = $map;
            }
        } else {
            self::prepareAsciiMaps();

            /* @noinspection AlterInForeachInspection | ok here */
            foreach (self::$ASCII_MAPS ?? [] as &$map) {
                $CHARS_ARRAY[$cacheKey][] = $map;
            }
        }

        $CHARS_ARRAY[$cacheKey] = \array_merge([], ...$CHARS_ARRAY[$cacheKey]);

        if ($asOrigReplaceArray) {
            $CHARS_ARRAY[$cacheKey] = [
                'orig'    => \array_keys($CHARS_ARRAY[$cacheKey]),
                'replace' => \array_values($CHARS_ARRAY[$cacheKey]),
            ];
        }

        return $CHARS_ARRAY[$cacheKey];
    }

    /**
     * Accepts a string and removes all non-UTF-8 characters from it + extras if needed.
     *
     * @param string $str                         <p>The string to be sanitized.</p>
     * @param bool   $normalize_whitespace        [optional] <p>Set to true, if you need to normalize the
     *                                            whitespace.</p>
     * @param bool   $normalize_msword            [optional] <p>Set to true, if you need to normalize MS Word chars
     *                                            e.g.: "…"
     *                                            => "..."</p>
     * @param bool   $keep_non_breaking_space     [optional] <p>Set to true, to keep non-breaking-spaces, in
     *                                            combination with
     *                                            $normalize_whitespace</p>
     * @param bool   $remove_invisible_characters [optional] <p>Set to false, if you not want to remove invisible
     *                                            characters e.g.: "\0"</p>
     * @param bool   $remove_invalid_utf8         [optional] <p>Set to true to discard malformed UTF-8 byte
     *                                            sequences before other normalization steps.</p>
     *
     * @psalm-pure
     *
     * @return string
     *                <p>A clean UTF-8 string.</p>
     */
    public static function clean(
        string $str,
        bool $normalize_whitespace = true,
        bool $keep_non_breaking_space = false,
        bool $normalize_msword = true,
        bool $remove_invisible_characters = true,
        bool $remove_invalid_utf8 = true
    ): string {
        // http://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string
        // caused connection reset problem on larger strings

        if ($remove_invalid_utf8) {
            $regex = '/
              (
                (?: [\x00-\x7F]                           # single-byte sequences   0xxxxxxx
                |   [\xC2-\xDF][\x80-\xBF]                # double-byte sequences   110xxxxx 10xxxxxx
                |   \xE0[\xA0-\xBF][\x80-\xBF]            # triple-byte sequences   excluding overlongs
                |   [\xE1-\xEC\xEE-\xEF][\x80-\xBF]{2}    # triple-byte sequences   excluding surrogates
                |   \xED[\x80-\x9F][\x80-\xBF]            # triple-byte sequences   excluding surrogates
                |   \xF0[\x90-\xBF][\x80-\xBF]{2}         # quadruple-byte sequences excluding overlongs
                |   [\xF1-\xF3][\x80-\xBF]{3}             # quadruple-byte sequences
                |   \xF4[\x80-\x8F][\x80-\xBF]{2}         # quadruple-byte sequences up to U+10FFFF
                ){1,100}                                  # ...one or more times
              )
            | ( [\x80-\xBF] )                             # invalid byte in range 10000000 - 10111111
            | ( [\xC0-\xFF] )                             # invalid byte in range 11000000 - 11111111
            /x';
            $str = (string) \preg_replace($regex, '$1', $str);
        }

        if ($normalize_whitespace) {
            $str = self::normalize_whitespace($str, $keep_non_breaking_space);
        }

        if ($normalize_msword) {
            $str = self::normalize_msword($str);
        }

        if ($remove_invisible_characters) {
            $str = self::remove_invisible_characters($str);
        }

        return $str;
    }

    /**
     * Checks if a string is 7-bit ASCII.
     *
     * EXAMPLE: <code>
     * ASCII::is_ascii('白'); // false
     * </code>
     *
     * @param string $str <p>The string to check.</p>
     *
     * @psalm-pure
     *
     * @return bool
     *              <p>
     *              <strong>true</strong> if it is ASCII<br>
     *              <strong>false</strong> otherwise
     *              </p>
     */
    public static function is_ascii(string $str): bool
    {
        if ($str === '') {
            return true;
        }

        return !\preg_match('/' . self::$REGEX_ASCII . '/', $str);
    }

    /**
     * Returns a string with smart quotes, ellipsis characters, and dashes from
     * Windows-1252 (commonly used in Word documents) replaced by their ASCII
     * equivalents.
     *
     * EXAMPLE: <code>
     * ASCII::normalize_msword('„Abcdef…”'); // '"Abcdef..."'
     * </code>
     *
     * @param string $str <p>The string to be normalized.</p>
     *
     * @psalm-pure
     *
     * @return string
     *                <p>A string with normalized characters for commonly used chars in Word documents.</p>
     */
    public static function normalize_msword(string $str): string
    {
        if ($str === '') {
            return '';
        }

        static $MSWORD_CACHE = ['orig' => [], 'replace' => []];

        if (empty($MSWORD_CACHE['orig'])) {
            self::prepareAsciiMaps();

            $map = self::$ASCII_MAPS[self::EXTRA_MSWORD_CHARS_LANGUAGE_CODE] ?? [];

            $MSWORD_CACHE = [
                'orig'    => \array_keys($map),
                'replace' => \array_values($map),
            ];
        }

        return \str_replace($MSWORD_CACHE['orig'], $MSWORD_CACHE['replace'], $str);
    }

    /**
     * Normalize the whitespace.
     *
     * EXAMPLE: <code>
     * ASCII::normalize_whitespace("abc-\xc2\xa0-öäü-\xe2\x80\xaf-\xE2\x80\xAC", true); // "abc-\xc2\xa0-öäü- -"
     * </code>
     *
     * @param string $str                          <p>The string to be normalized.</p>
     * @param bool   $keepNonBreakingSpace         [optional] <p>Set to true, to keep non-breaking-spaces.</p>
     * @param bool   $keepBidiUnicodeControls      [optional] <p>Set to true, to keep non-printable (for the web)
     *                                             bidirectional text chars.</p>
     * @param bool   $normalize_control_characters [optional] <p>Set to true, to convert e.g. LINE-, PARAGRAPH-SEPARATOR with "\n" and LINE TABULATION with "\t".</p>
     *
     * @psalm-pure
     *
     * @return string
     *                <p>A string with normalized whitespace.</p>
     */
    public static function normalize_whitespace(
        string $str,
        bool $keepNonBreakingSpace = false,
        bool $keepBidiUnicodeControls = false,
        bool $normalize_control_characters = false
    ): string {
        if ($str === '') {
            return '';
        }

        static $WHITESPACE_CACHE = [];
        $cacheKey = (int) $keepNonBreakingSpace;

        if ($normalize_control_characters) {
            $str = \str_replace(
                [
                    "\x0d\x0c",     // 'END OF LINE'
                    "\xe2\x80\xa8", // 'LINE SEPARATOR'
                    "\xe2\x80\xa9", // 'PARAGRAPH SEPARATOR'
                    "\x0c",         // 'FORM FEED' // "\f"
                    "\x0b",         // 'VERTICAL TAB' // "\v"
                ],
                [
                    "\n",
                    "\n",
                    "\n",
                    "\n",
                    "\t",
                ],
                $str
            );
        }

        if (!isset($WHITESPACE_CACHE[$cacheKey])) {
            self::prepareAsciiMaps();

            $WHITESPACE_CACHE[$cacheKey] = self::$ASCII_MAPS[self::EXTRA_WHITESPACE_CHARS_LANGUAGE_CODE] ?? [];

            if ($keepNonBreakingSpace) {
                unset($WHITESPACE_CACHE[$cacheKey]["\xc2\xa0"]);
            }

            $WHITESPACE_CACHE[$cacheKey] = array_keys($WHITESPACE_CACHE[$cacheKey]);
        }

        if (!$keepBidiUnicodeControls) {
            static $BIDI_UNICODE_CONTROLS_CACHE = null;

            if ($BIDI_UNICODE_CONTROLS_CACHE === null) {
                $BIDI_UNICODE_CONTROLS_CACHE = self::$BIDI_UNI_CODE_CONTROLS_TABLE;
            }

            $str = \str_replace($BIDI_UNICODE_CONTROLS_CACHE, '', $str);
        }

        return \str_replace($WHITESPACE_CACHE[$cacheKey], ' ', $str);
    }

    /**
     * Remove invisible characters from a string.
     *
     * This prevents malicious code injection through null bytes or other control characters.
     *
     * copy&past from https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/Common.php
     *
     * @param string $str
     * @param bool   $url_encoded
     * @param string $replacement
     * @param bool   $keep_basic_control_characters
     *
     * @psalm-pure
     *
     * @return string
     */
    public static function remove_invisible_characters(
        string $str,
        bool $url_encoded = false,
        string $replacement = '',
        bool $keep_basic_control_characters = true
    ): string {
        // init
        $non_displayables = [];

        // every control character except:
        // - newline (dec 10),
        // - carriage return (dec 13),
        // - horizontal tab (dec 09)
        if ($url_encoded) {
            $non_displayables[] = '/%0[0-8bcefBCEF]/'; // url encoded 00-08, 11, 12, 14, 15
            $non_displayables[] = '/%1[0-9a-fA-F]/'; // url encoded 16-31
        }

        if ($keep_basic_control_characters) {
            $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
        } else {
            $str = self::normalize_whitespace($str, false, false, true);
            $non_displayables[] = '/[^\P{C}\s]/u';
        }

        do {
            $str = (string) \preg_replace($non_displayables, $replacement, $str, -1, $count);
        } while ($count !== 0);

        return $str;
    }

    /**
     * WARNING: This method will return broken characters and is only for special cases.
     *
     * Convert two UTF-8 encoded strings to a single-byte strings suitable for
     * functions that need the same string length after the conversion.
     *
     * The function simply uses (and updates) a tailored dynamic encoding
     * (in/out map parameter) where non-ascii characters are remapped to
     * the range [128-255] in order of appearance.
     *
     * @return array{0: string, 1: string}
     */
    public static function to_ascii_remap(string $str1, string $str2): array
    {
        $charMap = [];
        $str1 = self::to_ascii_remap_intern($str1, $charMap);
        $str2 = self::to_ascii_remap_intern($str2, $charMap);

        return [$str1, $str2];
    }

    /**
     * Returns an ASCII version of the string. A set of non-ASCII characters are
     * replaced with their closest ASCII counterparts, and the rest are removed
     * by default. The language or locale of the source string can be supplied
     * for language-specific transliteration in any of the following formats:
     * en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
     * to "aeoeue" rather than "aou" as in other languages.
     *
     * EXAMPLE: <code>
     * ASCII::to_ascii('�Düsseldorf�', 'en'); // Dusseldorf
     * </code>
     *
     * @param string    $str                       <p>The input string.</p>
     * @param string    $language                  [optional] <p>Language of the source string.
     *                                             (default is 'en') | ASCII::*_LANGUAGE_CODE</p>
     * @param bool      $remove_unsupported_chars  [optional] <p>Whether to remove the
     *                                             unsupported characters.</p>
     * @param bool      $replace_extra_symbols     [optional]  <p>Add some more replacements e.g. "£" with " pound
     *                                             ".</p>
     * @param bool      $use_transliterate         [optional]  <p>Use ASCII::to_transliterate() for unknown chars.</p>
     * @param bool      $replace_single_chars_only [optional]  <p>Single char replacement is better for the
     *                                             performance, but some languages need to replace more than one char
     *                                             at the same time. If FALSE === auto-setting, depended on the
     *                                             language</p>
     *
     * @psalm-pure
     *
     * @return string
     *                <p>A string that contains only ASCII characters.</p>
     *
     * @phpstan-param ASCII::*_LANGUAGE_CODE $language
     */
    public static function to_ascii(
        string $str,
        string $language = self::ENGLISH_LANGUAGE_CODE,
        bool $remove_unsupported_chars = true,
        bool $replace_extra_symbols = false,
        bool $use_transliterate = false,
        bool $replace_single_chars_only = false
    ): string {
        if ($str === '') {
            return '';
        }

        // fast path: pure printable ASCII — single regex covers is_ascii + no-control-chars
        if (
            !$replace_extra_symbols
            &&
            !\preg_match('/' . self::REGEX_PRINTABLE_ASCII . '/', $str)
        ) {
            return $str;
        }

        $language = self::get_language($language);
        /** @phpstan-var ASCII::*_LANGUAGE_CODE $language - hack for phpstan */

        if (
            !$replace_extra_symbols
            &&
            \strlen($str) <= 64
        ) {
            $isValidUtf8 = true;
            $str = self::to_ascii_replace($str, $language, $replace_extra_symbols, $replace_single_chars_only, $isValidUtf8);

            if ($isValidUtf8) {
                self::prepareAsciiMaps();
                if (!isset(self::$ASCII_MAPS[$language])) {
                    $use_transliterate = true;
                }

                if ($use_transliterate) {
                    $str = self::to_transliterate($str, null, false);
                }

                if ($remove_unsupported_chars) {
                    if (!\preg_match('/' . self::REGEX_PRINTABLE_ASCII . '/', $str)) {
                        return $str;
                    }

                    $str = (string) \str_replace(["\r\n", "\n", "\r", "\t"], ' ', $str);
                    $str = (string) \preg_replace('/' . self::$REGEX_ASCII . '/', '', $str);
                }

                return $str;
            }
        }

        // secondary fast path: only 7-bit bytes (no multibyte UTF-8).
        // Strings with control chars (\x00-\x1F, \x7F) but no high bytes
        // still need $remove_unsupported_chars cleanup, but never need the
        // strtr replacement map because all replaceable characters are ≥ 0x80.
        if (
            !$replace_extra_symbols
            &&
            !\preg_match('/[\x80-\xFF]/', $str)
        ) {
            if ($remove_unsupported_chars) {
                $str = (string) \str_replace(["\r\n", "\n", "\r", "\t"], ' ', $str);
                $str = (string) \preg_replace('/' . self::$REGEX_ASCII . '/', '', $str);
            }

            return $str;
        }

        // invalid UTF-8: apply replacement map first, then clean up.
        // strtr() can match partial byte sequences from malformed UTF-8 against
        // valid lookup keys, producing incorrect output, so we must fall back to
        // the clean-then-transliterate path for invalid input.
        if (\preg_match('//u', $str) !== 1) {
            self::prepareAsciiMaps();

            if (!isset(self::$ASCII_MAPS[$language])) {
                $use_transliterate = true;
            }

            if ($use_transliterate) {
                $str = self::to_transliterate($str, null, false);
            }

            if ($remove_unsupported_chars) {
                if (!\preg_match('/' . self::REGEX_PRINTABLE_ASCII . '/', $str)) {
                    return $str;
                }

                $str = (string) \str_replace(["\r\n", "\n", "\r", "\t"], ' ', $str);
                $str = (string) \preg_replace('/' . self::$REGEX_ASCII . '/', '', $str);
            }

            return $str;
        }

        self::prepareAsciiMaps();
        if (!isset(self::$ASCII_MAPS[$language])) {
            $use_transliterate = true;
        }

        // For English transliteration mode, going directly through
        // to_transliterate() avoids an expensive replacement-map pass that
        // rarely contributes useful substitutions for non-Latin long strings.
        if (
            $use_transliterate
            &&
            !$replace_extra_symbols
            &&
            !$replace_single_chars_only
            &&
            $language === self::ENGLISH_LANGUAGE_CODE
        ) {
            $str = self::to_transliterate($str, null, false);
        } else {
            // Apply the ASCII replacement map via strtr().
            $str = self::to_ascii_replace($str, $language, $replace_extra_symbols, $replace_single_chars_only);

            if ($use_transliterate) {
                $str = self::to_transliterate($str, null, false);
            }
        }

        if ($remove_unsupported_chars) {
            if (!\preg_match('/' . self::REGEX_PRINTABLE_ASCII . '/', $str)) {
                return $str;
            }

            $str = (string) \str_replace(["\r\n", "\n", "\r", "\t"], ' ', $str);
            $str = (string) \preg_replace('/' . self::$REGEX_ASCII . '/', '', $str);
        }

        return $str;
    }

    /**
     * Convert given string to safe filename (and keep string case).
     *
     * EXAMPLE: <code>
     * ASCII::to_filename('שדגשדג.png', true)); // 'shdgshdg.png'
     * </code>
     *
     * @param string $str               <p>The string input.</p>
     * @param bool   $use_transliterate <p>ASCII::to_transliterate() is used by default - unsafe characters are
     *                                  simply replaced with hyphen otherwise.</p>
     * @param string $fallback_char     <p>The fallback character. - "-" is the default</p>
     *
     * @psalm-pure
     *
     * @return string
     *                <p>A string that contains only safe characters for a filename.</p>
     */
    public static function to_filename(
        string $str,
        bool $use_transliterate = true,
        string $fallback_char = '-'
    ): string {
        if ($use_transliterate) {
            $str = self::to_transliterate($str, $fallback_char);
        }

        $fallback_char_escaped = \preg_quote($fallback_char, '/');

        $str = (string) \preg_replace(
            [
                '/[^' . $fallback_char_escaped . '.\\-a-zA-Z\d\\s]/', // 1) remove un-needed chars
                '/\s+/u',                                             // 2) convert spaces to $fallback_char
                '/[' . $fallback_char_escaped . ']+/u',               // 3) remove double $fallback_char's
            ],
            [
                '',
                $fallback_char,
                $fallback_char,
            ],
            $str
        );

        return \trim($str, $fallback_char);
    }

    /**
     * Converts a string into a URL-friendly slug.
     *
     * - This includes replacing non-ASCII characters with their closest ASCII equivalents, removing remaining
     *   non-ASCII and non-alphanumeric characters, and replacing whitespace with $separator.
     * - The separator defaults to a single dash, and the string is also converted to lowercase.
     * - The language of the source string can also be supplied for language-specific transliteration.
     *
     * @param string                $str                   <p>The string input.</p>
     * @param string                $separator             [optional] <p>The string used to replace whitespace.</p>
     * @param string                $language              [optional] <p>Language of the source string.
     *                                                     (default is 'en') | ASCII::*_LANGUAGE_CODE</p>
     * @param array<string, string> $replacements          [optional] <p>A map of replaceable strings.</p>
     * @param bool                  $replace_extra_symbols [optional] <p>Add some more replacements e.g. "£" with "
     *                                                     pound ".</p>
     * @param bool                  $use_str_to_lower      [optional] <p>Use "string to lower" for the input.</p>
     * @param bool                  $use_transliterate     [optional] <p>Use ASCII::to_transliterate() for unknown
     *                                                     chars.</p>
     * @psalm-pure
     *
     * @return string
     *                <p>The URL-friendly slug.</p>
     *
     * @phpstan-param ASCII::*_LANGUAGE_CODE $language
     */
    public static function to_slugify(
        string $str,
        string $separator = '-',
        string $language = self::ENGLISH_LANGUAGE_CODE,
        array $replacements = [],
        bool $replace_extra_symbols = false,
        bool $use_str_to_lower = true,
        bool $use_transliterate = false
    ): string {
        if ($str === '') {
            return '';
        }

        foreach ($replacements as $from => $to) {
            $str = \str_replace($from, $to, $str);
        }

        if (
            !$replace_extra_symbols
            &&
            !$use_transliterate
            &&
            self::get_language($language) === self::ENGLISH_LANGUAGE_CODE
            &&
            !\preg_match('/' . self::REGEX_PRINTABLE_ASCII . '/', $str)
        ) {
            // Pure printable ASCII does not need transliteration or remapping.
        } else {
            $str = self::to_ascii(
                $str,
                $language,
                false,
                $replace_extra_symbols,
                $use_transliterate
            );
        }

        $str = \str_replace('@', $separator, $str);

        if ($use_str_to_lower) {
            $str = \strtolower($str);
            $str = (string) \preg_replace(
                '/[^a-z\\d\\s\\-_' . \preg_quote($separator, '/') . ']/',
                '',
                $str
            );
        } else {
            $str = (string) \preg_replace(
                '/[^a-zA-Z\\d\\s\\-_' . \preg_quote($separator, '/') . ']/',
                '',
                $str
            );
            $str = (string) \preg_replace('/\\B([A-Z])/', '-\1', $str);
        }

        $str = (string) \preg_replace('/^[\'\\s]+|[\'\\s]+$/', '', $str);
        $str = (string) \preg_replace('/[\\-_\\s]+/', $separator, $str);

        $l = \strlen($separator);
        if ($l && \strpos($str, $separator) === 0) {
            $str = (string) \substr($str, $l);
        }

        if (\substr($str, -$l) === $separator) {
            $str = (string) \substr($str, 0, \strlen($str) - $l);
        }

        return $str;
    }

    /**
     * Returns an ASCII version of the string. A set of non-ASCII characters are
     * replaced with their closest ASCII counterparts, and the rest are removed
     * unless instructed otherwise.
     *
     * EXAMPLE: <code>
     * ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
     * </code>
     *
     * @param string      $str     <p>The input string.</p>
     * @param string|null $unknown [optional] <p>Character use if character unknown. (default is '?')
     *                             But you can also use NULL to keep the unknown chars.</p>
     * @param bool        $strict  [optional] <p>Use "transliterator_transliterate()" from PHP-Intl
     *
     * @psalm-pure
     *
     * @return string
     *                <p>A String that contains only ASCII characters.</p>
     */
    public static function to_transliterate(
        string $str,
        $unknown = '?',
        bool $strict = false
    ): string {
        static $UTF8_TO_TRANSLIT = null;

        static $TRANSLITERATOR = null;

        static $SUPPORT_INTL = null;

        /** @var array<string, string|false> */
        static $TRANSLIT_CHAR_CACHE = [];
        /** @var array<string, array<string, string>> */
        static $WARM_MAPS = [];

        if ($str === '') {
            return '';
        }

        // Long pure printable ASCII strings are common in benchmarks and can
        // skip the broader ASCII/control-character validator entirely.
        if (
            isset($str[63])
            &&
            !\preg_match('/' . self::REGEX_PRINTABLE_ASCII . '/', $str)
        ) {
            return $str;
        }

        // check if we only have ASCII, first (better performance)
        if (\preg_match('/' . self::$REGEX_ASCII . '/', $str) === 0) {
            return $str;
        }

        // Prefix the cache key so unknown=null does not collide with an
        // explicit fallback string such as "\x00".
        $unknownCacheKey = $unknown === null
            ? "\x00null"
            : "\x01" . $unknown;

        if ($SUPPORT_INTL === null) {
            $SUPPORT_INTL = \extension_loaded('intl');
        }

        $warmPathAlreadyApplied = false;
        if (
            $unknown !== '?'
            &&
            isset($WARM_MAPS[$unknownCacheKey])
            &&
            \preg_match('//u', $str) === 1
        ) {
            $warmStr = \strtr($str, $WARM_MAPS[$unknownCacheKey]);
            if (!\preg_match('/[\x80-\xFF\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', $warmStr)) {
                return $warmStr;
            }

            $str = $warmStr;
            $warmPathAlreadyApplied = true;
        }

        // only run the heavy clean() regex when the string has invalid UTF-8
        if (\preg_match('//u', $str) === 1) {
            if (
                $unknown === '?'
                ||
                \strpos($str, "\xC2") !== false
                ||
                \strpos($str, "\xE2") !== false
                ||
                \preg_match('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', $str) === 1
            ) {
                $str_before_clean = $str;
                $str = self::normalize_whitespace($str);
                $str = self::normalize_msword($str);
                $str = self::remove_invisible_characters($str);
                $str = self::clean(
                    $str,
                    true,
                    false,
                    true,
                    false
                );
                if (
                    $str !== $str_before_clean
                    &&
                    \preg_match('/' . self::$REGEX_ASCII . '/', $str) === 0
                ) {
                    return $str;
                }
            }
        } else {
            $str_before_clean = $str;
            $str = self::clean($str);
            if (
                $str !== $str_before_clean
                &&
                \preg_match('/' . self::$REGEX_ASCII . '/', $str) === 0
            ) {
                return $str;
            }
        }

        if (
            $strict
            &&
            $SUPPORT_INTL === true
        ) {
            if (!isset($TRANSLITERATOR)) {
                // INFO: see "*-Latin" rules via "transliterator_list_ids()"
                $TRANSLITERATOR = \transliterator_create('NFKC; [:Nonspacing Mark:] Remove; NFKC; Any-Latin; Latin-ASCII;');
            }

            // INFO: https://unicode.org/cldr/utility/character.jsp
            $str_tmp = \transliterator_transliterate($TRANSLITERATOR, $str);

            if ($str_tmp !== false) {
                if (
                    $str_tmp !== $str
                    &&
                    \preg_match('/' . self::$REGEX_ASCII . '/', $str_tmp) === 0
                ) {
                    return $str_tmp;
                }

                $str = $str_tmp;
            }
        }

        if (self::$ORD === null) {
            self::$ORD = self::getData('ascii_ord');
        }

        // Copy the memoized ORD table into a local non-null alias so the hot
        // callback can read it without repeated nullable static-property checks.
        /** @var array<string, int> $ordMap */
        $ordMap = self::$ORD;

        // warm path: if we already built a map for this $unknown value, try it first
        if (
            !$warmPathAlreadyApplied
            &&
            isset($WARM_MAPS[$unknownCacheKey])
        ) {
            $str = \strtr($str, $WARM_MAPS[$unknownCacheKey]);

            if (!\preg_match('/[\x80-\xFF]/', $str)) {
                return $str;
            }
        }

        // collect unique non-ASCII characters and build a strtr map
        if (\preg_match_all(self::UTF8_MULTIBYTE_SEQUENCE_RX, $str, $nonAsciiMatches)) {
            $charMap = [];
            $seen = [];

            foreach ($nonAsciiMatches[0] as $c) {
                if (isset($seen[$c])) {
                    continue;
                }
                $seen[$c] = true;

                if (!\array_key_exists($c, $TRANSLIT_CHAR_CACHE)) {
                    $ordC0 = $ordMap[$c[0]];
                    $ordC1 = $ordMap[$c[1]];

                    if ($ordC0 <= 223) {
                        $ord = ($ordC0 - 192) * 64 + ($ordC1 - 128);
                    } elseif ($ordC0 <= 239) {
                        $ord = ($ordC0 - 224) * 4096 + ($ordC1 - 128) * 64 + ($ordMap[$c[2]] - 128);
                    } else {
                        $ord = ($ordC0 - 240) * 262144 + ($ordC1 - 128) * 4096 + ($ordMap[$c[2]] - 128) * 64 + ($ordMap[$c[3]] - 128);
                    }

                    $bank = $ord >> 8;
                    if (!isset($UTF8_TO_TRANSLIT[$bank])) {
                        $UTF8_TO_TRANSLIT[$bank] = self::getDataIfExists(\sprintf('x%03x', $bank));
                    }

                    $bankPos = $ord & 255;

                    if (
                        isset($UTF8_TO_TRANSLIT[$bank][$bankPos])
                        &&
                        !isset(self::UNKNOWN_TRANSLITERATION_MARKERS[$UTF8_TO_TRANSLIT[$bank][$bankPos]])
                    ) {
                        $TRANSLIT_CHAR_CACHE[$c] = $UTF8_TO_TRANSLIT[$bank][$bankPos];
                    } else {
                        $TRANSLIT_CHAR_CACHE[$c] = false;
                    }
                }

                $cached = $TRANSLIT_CHAR_CACHE[$c];

                if ($cached === false) {
                    if ($unknown !== null) {
                        $charMap[$c] = $unknown;
                    }
                } elseif ($cached === '' && $unknown === null) {
                    // keep original char
                } else {
                    $charMap[$c] = $cached;
                }
            }

            // merge new entries into the warm map for future calls
            if ($charMap !== []) {
                if (isset($WARM_MAPS[$unknownCacheKey])) {
                    foreach ($charMap as $k => $v) {
                        $WARM_MAPS[$unknownCacheKey][$k] = $v;
                    }
                } else {
                    $WARM_MAPS[$unknownCacheKey] = $charMap;
                }

                return \strtr($str, $WARM_MAPS[$unknownCacheKey]);
            }
        }

        return $str;
    }

    /**
     * WARNING: This method will return broken characters and is only for special cases.
     *
     * Convert a UTF-8 encoded string to a single-byte string suitable for
     * functions that need the same string length after the conversion.
     *
     * The function simply uses (and updates) a tailored dynamic encoding
     * (in/out map parameter) where non-ascii characters are remapped to
     * the range [128-255] in order of appearance.
     *
     * Thus, it supports up to 128 different multibyte code points max over
     * the whole set of strings sharing this encoding.
     *
     * Source: https://github.com/KEINOS/mb_levenshtein
     *
     * @param string $str <p>UTF-8 string to be converted to extended ASCII.</p>
     * @param array  $map <p>Internal-Map of code points to ASCII characters.</p>
     *
     * @return string
     *                <p>Mapped broken string.</p>
     *
     * @phpstan-param array<string, string> $map
     */
    private static function to_ascii_remap_intern(string $str, array &$map): string
    {
        // find all utf-8 characters
        $matches = [];
        if (!\preg_match_all('/[\xC0-\xF7][\x80-\xBF]+/', $str, $matches)) {
            return $str; // plain ascii string
        }

        // update the encoding map with the characters not already met
        $mapCount = \count($map);
        foreach ($matches[0] as $mbc) {
            if (!isset($map[$mbc])) {
                $map[$mbc] = \chr(128 + $mapCount);
                ++$mapCount;
            }
        }

        // finally, remap non-ascii characters
        return \strtr($str, $map);
    }


    /**
     * Apply the cached ASCII replacement map to a string via strtr().
     *
     * For medium and long UTF-8 inputs, filtering the replacement table by bytes
     * present in the input avoids feeding the full replacement table to strtr()
     * without introducing per-input cache growth.
     *
     * @phpstan-param ASCII::*_LANGUAGE_CODE $language
     * @param-out bool $isValidUtf8
     */
    private static function to_ascii_replace(
        string $str,
        string $language,
        bool $replace_extra_symbols,
        bool $replace_single_chars_only,
        ?bool &$isValidUtf8 = null
    ): string {
        static $REPLACE_HELPER_CACHE = [];
        static $MAP_BY_FIRST_BYTE = [];
        static $SHORT_FILTERED_MAP_CACHE = [];
        static $SHORT_FILTERED_MAP_CACHE_QUEUE = [];
        $cacheKey = $language . '-' . (int) $replace_extra_symbols . '-' . (int) $replace_single_chars_only;

        if (!isset($REPLACE_HELPER_CACHE[$cacheKey])) {
            $langAll = self::getAsciiAllReplacementMap($replace_extra_symbols, $replace_single_chars_only);

            $langSpecific = self::getAsciiLanguageReplacementMap($language, $replace_extra_symbols, $replace_single_chars_only);

            if ($langSpecific === []) {
                $REPLACE_HELPER_CACHE[$cacheKey] = $langAll;
            } else {
                $REPLACE_HELPER_CACHE[$cacheKey] = \array_merge([], $langAll, $langSpecific);
            }

            // Pre-index by first byte so long-string calls can cheaply skip most of
            // the replacement table instead of feeding the full language map to strtr().
            $MAP_BY_FIRST_BYTE[$cacheKey] = [];
            foreach ($REPLACE_HELPER_CACHE[$cacheKey] as $key => $val) {
                $MAP_BY_FIRST_BYTE[$cacheKey][$key[0]][$key] = $val;
            }
        }

        if (
            !$replace_extra_symbols
            &&
            \strlen($str) <= 64
        ) {
            $matchResult = \preg_match_all('/' . self::REGEX_PRINTABLE_ASCII . '/u', $str, $matches);
            if ($matchResult === false) {
                $isValidUtf8 = false;

                return $str;
            }

            $isValidUtf8 = true;

            if (!$matchResult) {
                return $str;
            }

            $cache = $REPLACE_HELPER_CACHE[$cacheKey];
            $chars = $matches[0];
            $charCount = \count($chars);

            if ($charCount === 1 && isset($cache[$chars[0]])) {
                return \str_replace($chars[0], $cache[$chars[0]], $str);
            }

            $shortCacheKey = $cacheKey . ':' . \implode('|', $chars);

            if (isset($SHORT_FILTERED_MAP_CACHE[$shortCacheKey])) {
                return \strtr($str, $SHORT_FILTERED_MAP_CACHE[$shortCacheKey]);
            }

            $filteredMap = [];

            if (
                !$replace_single_chars_only
                &&
                $charCount >= 2
            ) {
                // Mixed keys like "A̧" (ASCII + combining mark) are rare; let
                // strtr handle those with the full map to preserve correctness.
                if (\preg_match('/[A-Za-z][\x{0300}-\x{036F}]/u', $str) === 1) {
                    return \strtr($str, $cache);
                }

                for ($span = 5; $span >= 2; --$span) {
                    if ($charCount < $span) {
                        continue;
                    }

                    $lastIndex = $charCount - $span;
                    for ($idx = 0; $idx <= $lastIndex; ++$idx) {
                        $candidate = '';
                        for ($offset = 0; $offset < $span; ++$offset) {
                            $candidate .= $chars[$idx + $offset];
                        }

                        if (isset($cache[$candidate])) {
                            $filteredMap[$candidate] = $cache[$candidate];
                        }
                    }
                }
            }

            foreach ($chars as $char) {
                if (isset($cache[$char])) {
                    $filteredMap[$char] = $cache[$char];
                }
            }

            if ($filteredMap !== []) {
                $SHORT_FILTERED_MAP_CACHE[$shortCacheKey] = $filteredMap;
                $SHORT_FILTERED_MAP_CACHE_QUEUE[] = $shortCacheKey;
                if (\count($SHORT_FILTERED_MAP_CACHE_QUEUE) > 256) {
                    $oldestKey = \array_shift($SHORT_FILTERED_MAP_CACHE_QUEUE);
                    if ($oldestKey !== null) {
                        unset($SHORT_FILTERED_MAP_CACHE[$oldestKey]);
                    }
                }

                return \strtr($str, $filteredMap);
            }

            return $str;
        }

        $isValidUtf8 = true;

        // Build a filtered map containing only entries whose
        // leading byte is present in this specific input string.
        $indexedMap = &$MAP_BY_FIRST_BYTE[$cacheKey];
        $filteredMap = [];
        foreach (\count_chars($str, 1) as $byte => $count) {
            $fb = \chr($byte);
            if (isset($indexedMap[$fb])) {
                foreach ($indexedMap[$fb] as $k => $v) {
                    $filteredMap[$k] = $v;
                }
            }
        }

        if ($filteredMap !== []) {
            $str = \strtr($str, $filteredMap);
        }

        return $str;
    }

    /**
     * Get the language from a string.
     *
     * e.g.: de_at -> de_at
     *       de_DE -> de
     *       DE_DE -> de
     *       de-de -> de
     *
     * @return string
     */
    private static function get_language(string $language)
    {
        if ($language === '') {
            return '';
        }

        static $LANGUAGE_CACHE = [];
        if (isset($LANGUAGE_CACHE[$language])) {
            return $LANGUAGE_CACHE[$language];
        }

        if (
            \strpos($language, '_') === false
            &&
            \strpos($language, '-') === false
        ) {
            return $LANGUAGE_CACHE[$language] = \strtolower($language);
        }

        $language_tmp = \str_replace('-', '_', \strtolower($language));

        $regex = '/(?<first>[a-z]+)_\g{first}/';

        return $LANGUAGE_CACHE[$language] = (string) \preg_replace($regex, '$1', $language_tmp);
    }

    /**
     * @return array<string, string>
     */
    private static function getAsciiAllReplacementMap(
        bool $replace_extra_symbols,
        bool $replace_single_chars_only
    ): array {
        static $CACHE = [];
        $cacheKey = (int) $replace_extra_symbols . '-' . (int) $replace_single_chars_only;

        if (isset($CACHE[$cacheKey])) {
            return $CACHE[$cacheKey];
        }

        $CACHE[$cacheKey] = self::filterAsciiReplacementMap(
            self::charsArrayWithSingleLanguageValues($replace_extra_symbols, false),
            $replace_single_chars_only
        );

        return $CACHE[$cacheKey];
    }

    /**
     * @phpstan-param ASCII::*_LANGUAGE_CODE $language
     *
     * @return array<string, string>
     */
    private static function getAsciiLanguageReplacementMap(
        string $language,
        bool $replace_extra_symbols,
        bool $replace_single_chars_only
    ): array {
        static $CACHE = [];
        $cacheKey = $language . '-' . (int) $replace_extra_symbols . '-' . (int) $replace_single_chars_only;

        if (isset($CACHE[$cacheKey])) {
            return $CACHE[$cacheKey];
        }

        $CACHE[$cacheKey] = self::filterAsciiReplacementMap(
            self::charsArrayWithOneLanguage($language, $replace_extra_symbols, false),
            $replace_single_chars_only
        );

        return $CACHE[$cacheKey];
    }

    /**
     * Get data from "/data/*.php".
     *
     * @return array<array-key,mixed>
     */
    private static function getData(string $file)
    {
        return include __DIR__ . '/data/' . $file . '.php';
    }

    /**
     * Get data from "/data/*.php".
     *
     * @return array<array-key,mixed>
     */
    private static function getDataIfExists(string $file): array
    {
        $file = __DIR__ . '/data/' . $file . '.php';
        if (\is_file($file)) {
            return include $file;
        }

        return [];
    }

    /**
     * @param array<string, string> $map
     *
     * @return array<string, string>
     */
    private static function filterAsciiReplacementMap(array $map, bool $replace_single_chars_only): array
    {
        if ($replace_single_chars_only === false) {
            return $map;
        }

        foreach ($map as $char => $replacement) {
            // Single UTF-8 code points are at most 4 bytes, so 5+ bytes
            // can be rejected without the regex check.
            if (
                isset($char[4])
                ||
                \preg_match('/^.$/us', $char) !== 1
            ) {
                unset($map[$char]);
            }
        }

        return $map;
    }

    /**
     * @return void
     */
    private static function prepareAsciiAndExtrasMaps()
    {
        if (self::$ASCII_MAPS_AND_EXTRAS === null) {
            self::prepareAsciiMaps();
            self::prepareAsciiExtras();

            self::$ASCII_MAPS_AND_EXTRAS = \array_merge_recursive(
                self::$ASCII_MAPS ?? [],
                self::$ASCII_EXTRAS ?? []
            );
        }
    }

    /**
     * @return void
     */
    private static function prepareAsciiMaps()
    {
        if (self::$ASCII_MAPS === null) {
            self::$ASCII_MAPS = self::getData('ascii_by_languages');
        }
    }

    /**
     * @return void
     */
    private static function prepareAsciiExtras()
    {
        if (self::$ASCII_EXTRAS === null) {
            self::$ASCII_EXTRAS = self::getData('ascii_extras_by_languages');
        }
    }
}
<?php return ['jeo', 'jeog', 'jeogg', 'jeogs', 'jeon', 'jeonj', 'jeonh', 'jeod', 'jeol', 'jeolg', 'jeolm', 'jeolb', 'jeols', 'jeolt', 'jeolp', 'jeolh', 'jeom', 'jeob', 'jeobs', 'jeos', 'jeoss', 'jeong', 'jeoj', 'jeoc', 'jeok', 'jeot', 'jeop', 'jeoh', 'je', 'jeg', 'jegg', 'jegs', 'jen', 'jenj', 'jenh', 'jed', 'jel', 'jelg', 'jelm', 'jelb', 'jels', 'jelt', 'jelp', 'jelh', 'jem', 'jeb', 'jebs', 'jes', 'jess', 'jeng', 'jej', 'jec', 'jek', 'jet', 'jep', 'jeh', 'jyeo', 'jyeog', 'jyeogg', 'jyeogs', 'jyeon', 'jyeonj', 'jyeonh', 'jyeod', 'jyeol', 'jyeolg', 'jyeolm', 'jyeolb', 'jyeols', 'jyeolt', 'jyeolp', 'jyeolh', 'jyeom', 'jyeob', 'jyeobs', 'jyeos', 'jyeoss', 'jyeong', 'jyeoj', 'jyeoc', 'jyeok', 'jyeot', 'jyeop', 'jyeoh', 'jye', 'jyeg', 'jyegg', 'jyegs', 'jyen', 'jyenj', 'jyenh', 'jyed', 'jyel', 'jyelg', 'jyelm', 'jyelb', 'jyels', 'jyelt', 'jyelp', 'jyelh', 'jyem', 'jyeb', 'jyebs', 'jyes', 'jyess', 'jyeng', 'jyej', 'jyec', 'jyek', 'jyet', 'jyep', 'jyeh', 'jo', 'jog', 'jogg', 'jogs', 'jon', 'jonj', 'jonh', 'jod', 'jol', 'jolg', 'jolm', 'jolb', 'jols', 'jolt', 'jolp', 'jolh', 'jom', 'job', 'jobs', 'jos', 'joss', 'jong', 'joj', 'joc', 'jok', 'jot', 'jop', 'joh', 'jwa', 'jwag', 'jwagg', 'jwags', 'jwan', 'jwanj', 'jwanh', 'jwad', 'jwal', 'jwalg', 'jwalm', 'jwalb', 'jwals', 'jwalt', 'jwalp', 'jwalh', 'jwam', 'jwab', 'jwabs', 'jwas', 'jwass', 'jwang', 'jwaj', 'jwac', 'jwak', 'jwat', 'jwap', 'jwah', 'jwae', 'jwaeg', 'jwaegg', 'jwaegs', 'jwaen', 'jwaenj', 'jwaenh', 'jwaed', 'jwael', 'jwaelg', 'jwaelm', 'jwaelb', 'jwaels', 'jwaelt', 'jwaelp', 'jwaelh', 'jwaem', 'jwaeb', 'jwaebs', 'jwaes', 'jwaess', 'jwaeng', 'jwaej', 'jwaec', 'jwaek', 'jwaet', 'jwaep', 'jwaeh', 'joe', 'joeg', 'joegg', 'joegs', 'joen', 'joenj', 'joenh', 'joed', 'joel', 'joelg', 'joelm', 'joelb', 'joels', 'joelt', 'joelp', 'joelh', 'joem', 'joeb', 'joebs', 'joes', 'joess', 'joeng', 'joej', 'joec', 'joek', 'joet', 'joep', 'joeh', 'jyo', 'jyog', 'jyogg', 'jyogs', 'jyon', 'jyonj', 'jyonh', 'jyod', 'jyol', 'jyolg', 'jyolm', 'jyolb', 'jyols', 'jyolt', 'jyolp', 'jyolh', 'jyom', 'jyob', 'jyobs', 'jyos', 'jyoss', 'jyong', 'jyoj', 'jyoc', 'jyok', 'jyot', 'jyop', 'jyoh', 'ju', 'jug', 'jugg', 'jugs'];
<?php return ['-', '-', '|', '|', '-', '-', '|', '|', '-', '-', '|', '|', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '-', '-', '|', '|', '-', '|', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '/', '\\', 'X', '-', '|', '-', '|', '-', '|', '-', '|', '-', '|', '-', '|', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '-', '|', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '^', '^', '^', '^', '>', '>', '>', '>', '>', '>', 'V', 'V', 'V', 'V', '<', '<', '<', '<', '<', '<', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '*', '#', '#', '#', '#', '#', '^', '^', '^', 'O', '#', '#', '#', '#', 'O', 'O', 'O', 'O', '/', '\\\\', '\\\\', '#', '#', '#', '#', '/'];
<?php return ['Xiang ', 'Nong ', 'Bo ', 'Chan ', 'Lan ', 'Ju ', 'Shuang ', 'She ', 'Wei ', 'Cong ', 'Quan ', 'Qu ', 'Cang ', '[?] ', 'Yu ', 'Luo ', 'Li ', 'Zan ', 'Luan ', 'Dang ', 'Jue ', 'Em ', 'Lan ', 'Lan ', 'Zhu ', 'Lei ', 'Li ', 'Ba ', 'Nang ', 'Yu ', 'Ling ', 'Tsuki ', 'Qian ', 'Ci ', 'Huan ', 'Xin ', 'Yu ', 'Yu ', 'Qian ', 'Ou ', 'Xu ', 'Chao ', 'Chu ', 'Chi ', 'Kai ', 'Yi ', 'Jue ', 'Xi ', 'Xu ', 'Xia ', 'Yu ', 'Kuai ', 'Lang ', 'Kuan ', 'Shuo ', 'Xi ', 'Ai ', 'Yi ', 'Qi ', 'Hu ', 'Chi ', 'Qin ', 'Kuan ', 'Kan ', 'Kuan ', 'Kan ', 'Chuan ', 'Sha ', 'Gua ', 'Yin ', 'Xin ', 'Xie ', 'Yu ', 'Qian ', 'Xiao ', 'Yi ', 'Ge ', 'Wu ', 'Tan ', 'Jin ', 'Ou ', 'Hu ', 'Ti ', 'Huan ', 'Xu ', 'Pen ', 'Xi ', 'Xiao ', 'Xu ', 'Xi ', 'Sen ', 'Lian ', 'Chu ', 'Yi ', 'Kan ', 'Yu ', 'Chuo ', 'Huan ', 'Zhi ', 'Zheng ', 'Ci ', 'Bu ', 'Wu ', 'Qi ', 'Bu ', 'Bu ', 'Wai ', 'Ju ', 'Qian ', 'Chi ', 'Se ', 'Chi ', 'Se ', 'Zhong ', 'Sui ', 'Sui ', 'Li ', 'Cuo ', 'Yu ', 'Li ', 'Gui ', 'Dai ', 'Dai ', 'Si ', 'Jian ', 'Zhe ', 'Mo ', 'Mo ', 'Yao ', 'Mo ', 'Cu ', 'Yang ', 'Tian ', 'Sheng ', 'Dai ', 'Shang ', 'Xu ', 'Xun ', 'Shu ', 'Can ', 'Jue ', 'Piao ', 'Qia ', 'Qiu ', 'Su ', 'Qing ', 'Yun ', 'Lian ', 'Yi ', 'Fou ', 'Zhi ', 'Ye ', 'Can ', 'Hun ', 'Dan ', 'Ji ', 'Ye ', 'Zhen ', 'Yun ', 'Wen ', 'Chou ', 'Bin ', 'Ti ', 'Jin ', 'Shang ', 'Yin ', 'Diao ', 'Cu ', 'Hui ', 'Cuan ', 'Yi ', 'Dan ', 'Du ', 'Jiang ', 'Lian ', 'Bin ', 'Du ', 'Tsukusu ', 'Jian ', 'Shu ', 'Ou ', 'Duan ', 'Zhu ', 'Yin ', 'Qing ', 'Yi ', 'Sha ', 'Que ', 'Ke ', 'Yao ', 'Jun ', 'Dian ', 'Hui ', 'Hui ', 'Gu ', 'Que ', 'Ji ', 'Yi ', 'Ou ', 'Hui ', 'Duan ', 'Yi ', 'Xiao ', 'Wu ', 'Guan ', 'Mu ', 'Mei ', 'Mei ', 'Ai ', 'Zuo ', 'Du ', 'Yu ', 'Bi ', 'Bi ', 'Bi ', 'Pi ', 'Pi ', 'Bi ', 'Chan ', 'Mao ', '[?] ', '[?] ', 'Pu ', 'Mushiru ', 'Jia ', 'Zhan ', 'Sai ', 'Mu ', 'Tuo ', 'Xun ', 'Er ', 'Rong ', 'Xian ', 'Ju ', 'Mu ', 'Hao ', 'Qiu ', 'Dou ', 'Mushiru ', 'Tan ', 'Pei ', 'Ju ', 'Duo ', 'Cui ', 'Bi ', 'San ', '[?] ', 'Mao ', 'Sui ', 'Yu ', 'Yu ', 'Tuo ', 'He ', 'Jian ', 'Ta ', 'San '];
<?php return ['k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'nny', 'tt', 'tth', 'dd', 'ddh', 'nn', 'tt', 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'l', 'w', 's', 'h', 'll', 'a', '[?]', 'i', 'ii', 'u', 'uu', 'e', '[?]', 'o', 'au', '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'e', 'ai', '[?]', '[?]', '[?]', 'N', '\'', ':', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' / ', ' // ', 'n*', 'r*', 'l*', 'e*', 'sh', 'ss', 'R', 'RR', 'L', 'LL', 'R', 'RR', 'L', 'LL', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'A', 'B', 'G', 'D', 'E', 'V', 'Z', 'T`', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Zh', 'R', 'S', 'T', 'U', 'P`', 'K`', 'G\'', 'Q', 'Sh', 'Ch`', 'C`', 'Z\'', 'C', 'Ch', 'X', 'J', 'H', 'E', 'Y', 'W', 'Xh', 'OE', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'a', 'b', 'g', 'd', 'e', 'v', 'z', 't`', 'i', 'k', 'l', 'm', 'n', 'o', 'p', 'zh', 'r', 's', 't', 'u', 'p`', 'k`', 'g\'', 'q', 'sh', 'ch`', 'c`', 'z\'', 'c', 'ch', 'x', 'j', 'h', 'e', 'y', 'w', 'xh', 'oe', 'f', '[?]', '[?]', '[?]', '[?]', ' // ', '[?]', '[?]', '[?]'];
<?php return ['[?]', '[?]', '[?]', '^', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '<', '> ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Zhi ', 'Liu ', 'Mei ', 'Hoy ', 'Rong ', 'Zha ', '[?] ', 'Biao ', 'Zhan ', 'Jie ', 'Long ', 'Dong ', 'Lu ', 'Sayng ', 'Li ', 'Lan ', 'Yong ', 'Shu ', 'Xun ', 'Shuan ', 'Qi ', 'Zhen ', 'Qi ', 'Li ', 'Yi ', 'Xiang ', 'Zhen ', 'Li ', 'Su ', 'Gua ', 'Kan ', 'Bing ', 'Ren ', 'Xiao ', 'Bo ', 'Ren ', 'Bing ', 'Zi ', 'Chou ', 'Yi ', 'Jie ', 'Xu ', 'Zhu ', 'Jian ', 'Zui ', 'Er ', 'Er ', 'You ', 'Fa ', 'Gong ', 'Kao ', 'Lao ', 'Zhan ', 'Li ', 'Yin ', 'Yang ', 'He ', 'Gen ', 'Zhi ', 'Chi ', 'Ge ', 'Zai ', 'Luan ', 'Fu ', 'Jie ', 'Hang ', 'Gui ', 'Tao ', 'Guang ', 'Wei ', 'Kuang ', 'Ru ', 'An ', 'An ', 'Juan ', 'Yi ', 'Zhuo ', 'Ku ', 'Zhi ', 'Qiong ', 'Tong ', 'Sang ', 'Sang ', 'Huan ', 'Jie ', 'Jiu ', 'Xue ', 'Duo ', 'Zhui ', 'Yu ', 'Zan ', 'Kasei ', 'Ying ', 'Masu ', '[?] ', 'Zhan ', 'Ya ', 'Nao ', 'Zhen ', 'Dang ', 'Qi ', 'Qiao ', 'Hua ', 'Kuai ', 'Jiang ', 'Zhuang ', 'Xun ', 'Suo ', 'Sha ', 'Zhen ', 'Bei ', 'Ting ', 'Gua ', 'Jing ', 'Bo ', 'Ben ', 'Fu ', 'Rui ', 'Tong ', 'Jue ', 'Xi ', 'Lang ', 'Liu ', 'Feng ', 'Qi ', 'Wen ', 'Jun ', 'Gan ', 'Cu ', 'Liang ', 'Qiu ', 'Ting ', 'You ', 'Mei ', 'Bang ', 'Long ', 'Peng ', 'Zhuang ', 'Di ', 'Xuan ', 'Tu ', 'Zao ', 'Ao ', 'Gu ', 'Bi ', 'Di ', 'Han ', 'Zi ', 'Zhi ', 'Ren ', 'Bei ', 'Geng ', 'Jian ', 'Huan ', 'Wan ', 'Nuo ', 'Jia ', 'Tiao ', 'Ji ', 'Xiao ', 'Lu ', 'Huan ', 'Shao ', 'Cen ', 'Fen ', 'Song ', 'Meng ', 'Wu ', 'Li ', 'Li ', 'Dou ', 'Cen ', 'Ying ', 'Suo ', 'Ju ', 'Ti ', 'Jie ', 'Kun ', 'Zhuo ', 'Shu ', 'Chan ', 'Fan ', 'Wei ', 'Jing ', 'Li ', 'Bing ', 'Fumoto ', 'Shikimi ', 'Tao ', 'Zhi ', 'Lai ', 'Lian ', 'Jian ', 'Zhuo ', 'Ling ', 'Li ', 'Qi ', 'Bing ', 'Zhun ', 'Cong ', 'Qian ', 'Mian ', 'Qi ', 'Qi ', 'Cai ', 'Gun ', 'Chan ', 'Te ', 'Fei ', 'Pai ', 'Bang ', 'Pou ', 'Hun ', 'Zong ', 'Cheng ', 'Zao ', 'Ji ', 'Li ', 'Peng ', 'Yu ', 'Yu ', 'Gu ', 'Hun ', 'Dong ', 'Tang ', 'Gang ', 'Wang ', 'Di ', 'Xi ', 'Fan ', 'Cheng ', 'Zhan ', 'Qi ', 'Yuan ', 'Yan ', 'Yu ', 'Quan ', 'Yi ', 'Sen ', 'Ren ', 'Chui ', 'Leng ', 'Qi ', 'Zhuo ', 'Fu ', 'Ke ', 'Lai ', 'Zou ', 'Zou ', 'Zhuo ', 'Guan ', 'Fen ', 'Fen ', 'Chen ', 'Qiong ', 'Nie '];
<?php return ['[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Lang ', 'Kan ', 'Lao ', 'Lai ', 'Xian ', 'Que ', 'Kong ', 'Chong ', 'Chong ', 'Ta ', 'Lin ', 'Hua ', 'Ju ', 'Lai ', 'Qi ', 'Min ', 'Kun ', 'Kun ', 'Zu ', 'Gu ', 'Cui ', 'Ya ', 'Ya ', 'Gang ', 'Lun ', 'Lun ', 'Leng ', 'Jue ', 'Duo ', 'Zheng ', 'Guo ', 'Yin ', 'Dong ', 'Han ', 'Zheng ', 'Wei ', 'Yao ', 'Pi ', 'Yan ', 'Song ', 'Jie ', 'Beng ', 'Zu ', 'Jue ', 'Dong ', 'Zhan ', 'Gu ', 'Yin ', '[?] ', 'Ze ', 'Huang ', 'Yu ', 'Wei ', 'Yang ', 'Feng ', 'Qiu ', 'Dun ', 'Ti ', 'Yi ', 'Zhi ', 'Shi ', 'Zai ', 'Yao ', 'E ', 'Zhu ', 'Kan ', 'Lu ', 'Yan ', 'Mei ', 'Gan ', 'Ji ', 'Ji ', 'Huan ', 'Ting ', 'Sheng ', 'Mei ', 'Qian ', 'Wu ', 'Yu ', 'Zong ', 'Lan ', 'Jue ', 'Yan ', 'Yan ', 'Wei ', 'Zong ', 'Cha ', 'Sui ', 'Rong ', 'Yamashina ', 'Qin ', 'Yu ', 'Kewashii ', 'Lou ', 'Tu ', 'Dui ', 'Xi ', 'Weng ', 'Cang ', 'Dang ', 'Hong ', 'Jie ', 'Ai ', 'Liu ', 'Wu ', 'Song ', 'Qiao ', 'Zi ', 'Wei ', 'Beng ', 'Dian ', 'Cuo ', 'Qian ', 'Yong ', 'Nie ', 'Cuo ', 'Ji ', '[?] ', 'Tao ', 'Song ', 'Zong ', 'Jiang ', 'Liao ', 'Kang ', 'Chan ', 'Die ', 'Cen ', 'Ding ', 'Tu ', 'Lou ', 'Zhang ', 'Zhan ', 'Zhan ', 'Ao ', 'Cao ', 'Qu ', 'Qiang ', 'Zui ', 'Zui ', 'Dao ', 'Dao ', 'Xi ', 'Yu ', 'Bo ', 'Long ', 'Xiang ', 'Ceng ', 'Bo ', 'Qin ', 'Jiao ', 'Yan ', 'Lao ', 'Zhan ', 'Lin ', 'Liao ', 'Liao ', 'Jin ', 'Deng ', 'Duo ', 'Zun ', 'Jiao ', 'Gui ', 'Yao ', 'Qiao ', 'Yao ', 'Jue ', 'Zhan ', 'Yi ', 'Xue ', 'Nao ', 'Ye ', 'Ye ', 'Yi ', 'E ', 'Xian ', 'Ji ', 'Xie ', 'Ke ', 'Xi ', 'Di ', 'Ao ', 'Zui ', '[?] ', 'Ni ', 'Rong ', 'Dao ', 'Ling ', 'Za ', 'Yu ', 'Yue ', 'Yin ', '[?] ', 'Jie ', 'Li ', 'Sui ', 'Long ', 'Long ', 'Dian ', 'Ying ', 'Xi ', 'Ju ', 'Chan ', 'Ying ', 'Kui ', 'Yan ', 'Wei ', 'Nao ', 'Quan ', 'Chao ', 'Cuan ', 'Luan ', 'Dian ', 'Dian ', '[?] ', 'Yan ', 'Yan ', 'Yan ', 'Nao ', 'Yan ', 'Chuan ', 'Gui ', 'Chuan ', 'Zhou ', 'Huang ', 'Jing ', 'Xun ', 'Chao ', 'Chao ', 'Lie ', 'Gong ', 'Zuo ', 'Qiao ', 'Ju ', 'Gong ', 'Kek ', 'Wu ', 'Pwu ', 'Pwu ', 'Chai ', 'Qiu ', 'Qiu ', 'Ji ', 'Yi ', 'Si ', 'Ba ', 'Zhi ', 'Zhao ', 'Xiang ', 'Yi ', 'Jin ', 'Xun ', 'Juan ', 'Phas ', 'Xun ', 'Jin ', 'Fu '];
<?php return ['AUM', '', '', '', '', '', '', '', ' // ', ' * ', '', '-', ' / ', ' / ', ' // ', ' -/ ', ' +/ ', ' X/ ', ' /XX/ ', ' /X/ ', ', ', '', '', '', '', '', '', '', '', '', '', '', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.5', '1.5', '2.5', '3.5', '4.5', '5.5', '6.5', '7.5', '8.5', '-.5', '+', '*', '^', '_', '', '~', '[?]', ']', '[[', ']]', '', '', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', '[?]', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'ts', 'tsh', 'dz', 'dzh', 'w', 'zh', 'z', '\'', 'y', 'r', 'l', 'sh', 'ssh', 's', 'h', 'a', 'kss', 'r', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'L', 'LL', 'e', 'ee', 'o', 'oo', 'M', 'H', 'i', 'ii', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', '[?]', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'ts', 'tsh', 'dz', 'dzh', 'w', 'zh', 'z', '\'', 'y', 'r', 'l', 'sh', 'ss', 's', 'h', 'a', 'kss', 'w', 'y', 'r', '[?]', 'X', ' :X: ', ' /O/ ', ' /o/ ', ' \\o\\ ', ' (O) ', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['jun', 'junj', 'junh', 'jud', 'jul', 'julg', 'julm', 'julb', 'juls', 'jult', 'julp', 'julh', 'jum', 'jub', 'jubs', 'jus', 'juss', 'jung', 'juj', 'juc', 'juk', 'jut', 'jup', 'juh', 'jweo', 'jweog', 'jweogg', 'jweogs', 'jweon', 'jweonj', 'jweonh', 'jweod', 'jweol', 'jweolg', 'jweolm', 'jweolb', 'jweols', 'jweolt', 'jweolp', 'jweolh', 'jweom', 'jweob', 'jweobs', 'jweos', 'jweoss', 'jweong', 'jweoj', 'jweoc', 'jweok', 'jweot', 'jweop', 'jweoh', 'jwe', 'jweg', 'jwegg', 'jwegs', 'jwen', 'jwenj', 'jwenh', 'jwed', 'jwel', 'jwelg', 'jwelm', 'jwelb', 'jwels', 'jwelt', 'jwelp', 'jwelh', 'jwem', 'jweb', 'jwebs', 'jwes', 'jwess', 'jweng', 'jwej', 'jwec', 'jwek', 'jwet', 'jwep', 'jweh', 'jwi', 'jwig', 'jwigg', 'jwigs', 'jwin', 'jwinj', 'jwinh', 'jwid', 'jwil', 'jwilg', 'jwilm', 'jwilb', 'jwils', 'jwilt', 'jwilp', 'jwilh', 'jwim', 'jwib', 'jwibs', 'jwis', 'jwiss', 'jwing', 'jwij', 'jwic', 'jwik', 'jwit', 'jwip', 'jwih', 'jyu', 'jyug', 'jyugg', 'jyugs', 'jyun', 'jyunj', 'jyunh', 'jyud', 'jyul', 'jyulg', 'jyulm', 'jyulb', 'jyuls', 'jyult', 'jyulp', 'jyulh', 'jyum', 'jyub', 'jyubs', 'jyus', 'jyuss', 'jyung', 'jyuj', 'jyuc', 'jyuk', 'jyut', 'jyup', 'jyuh', 'jeu', 'jeug', 'jeugg', 'jeugs', 'jeun', 'jeunj', 'jeunh', 'jeud', 'jeul', 'jeulg', 'jeulm', 'jeulb', 'jeuls', 'jeult', 'jeulp', 'jeulh', 'jeum', 'jeub', 'jeubs', 'jeus', 'jeuss', 'jeung', 'jeuj', 'jeuc', 'jeuk', 'jeut', 'jeup', 'jeuh', 'jyi', 'jyig', 'jyigg', 'jyigs', 'jyin', 'jyinj', 'jyinh', 'jyid', 'jyil', 'jyilg', 'jyilm', 'jyilb', 'jyils', 'jyilt', 'jyilp', 'jyilh', 'jyim', 'jyib', 'jyibs', 'jyis', 'jyiss', 'jying', 'jyij', 'jyic', 'jyik', 'jyit', 'jyip', 'jyih', 'ji', 'jig', 'jigg', 'jigs', 'jin', 'jinj', 'jinh', 'jid', 'jil', 'jilg', 'jilm', 'jilb', 'jils', 'jilt', 'jilp', 'jilh', 'jim', 'jib', 'jibs', 'jis', 'jiss', 'jing', 'jij', 'jic', 'jik', 'jit', 'jip', 'jih', 'jja', 'jjag', 'jjagg', 'jjags', 'jjan', 'jjanj', 'jjanh', 'jjad', 'jjal', 'jjalg', 'jjalm', 'jjalb', 'jjals', 'jjalt', 'jjalp', 'jjalh', 'jjam', 'jjab', 'jjabs', 'jjas', 'jjass', 'jjang', 'jjaj', 'jjac', 'jjak', 'jjat', 'jjap', 'jjah', 'jjae', 'jjaeg', 'jjaegg', 'jjaegs', 'jjaen', 'jjaenj', 'jjaenh', 'jjaed'];
<?php

// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes

return [
    // Dutch (Flemish)
    'nl' => [
        'Á' => 'A',
        'á' => 'a',
        'Ä' => 'A',
        'ä' => 'a',
        'À' => 'A',
        'à' => 'a',
        'Â' => 'A',
        'â' => 'a',
        'É' => 'E',
        'é' => 'e',
        'Ë' => 'E',
        'ë' => 'e',
        'È' => 'E',
        'è' => 'e',
        'Ê' => 'E',
        'ê' => 'e',
        'Í' => 'I',
        'í' => 'i',
        'Ï' => 'I',
        'ï' => 'i',
        'Ì' => 'I',
        'ì' => 'i',
        'Î' => 'I',
        'î' => 'i',
        'Ó' => 'O',
        'ó' => 'o',
        'Ö' => 'O',
        'ö' => 'o',
        'Ò' => 'O',
        'ò' => 'o',
        'Ô' => 'O',
        'ô' => 'o',
        'Ú' => 'U',
        'ú' => 'u',
        'Ü' => 'U',
        'ü' => 'u',
        'Ù' => 'U',
        'ù' => 'u',
        'Û' => 'U',
        'û' => 'u',
        'Ý' => 'Y',
        'ý' => 'y',
        'Ÿ' => 'Y',
    ],
    // Italian
    'it' => [
        'à' => 'a',
        'À' => 'A',
        'é' => 'e',
        'É' => 'E',
        'è' => 'e',
        'È' => 'E',
        'ì' => 'i',
        'Ì' => 'I',
        'Ò' => 'O',
        'ò' => 'o',
        'ù' => 'u',
        'Ù' => 'U',
    ],
    // Macedonian
    'mk' => [
        'А' => 'A',
        'Б' => 'B',
        'В' => 'V',
        'Г' => 'G',
        'Д' => 'D',
        'Ѓ' => 'Gj',
        'Е' => 'E',
        'Ж' => 'Zh',
        'З' => 'Z',
        'Ѕ' => 'Dz',
        'И' => 'I',
        'Ј' => 'J',
        'К' => 'K',
        'Л' => 'L',
        'Љ' => 'Lj',
        'М' => 'M',
        'Н' => 'N',
        'Њ' => 'Nj',
        'О' => 'O',
        'П' => 'P',
        'Р' => 'R',
        'С' => 'S',
        'Т' => 'T',
        'Ќ' => 'Kj',
        'У' => 'U',
        'Ф' => 'F',
        'Х' => 'H',
        'Ц' => 'C',
        'Ч' => 'Ch',
        'Џ' => 'Dj',
        'Ш' => 'Sh',
        'а' => 'a',
        'б' => 'b',
        'в' => 'v',
        'г' => 'g',
        'д' => 'd',
        'ѓ' => 'gj',
        'е' => 'e',
        'ж' => 'zh',
        'з' => 'z',
        'ѕ' => 'dz',
        'и' => 'i',
        'ј' => 'j',
        'к' => 'k',
        'л' => 'l',
        'љ' => 'lj',
        'м' => 'm',
        'н' => 'n',
        'њ' => 'nj',
        'о' => 'o',
        'п' => 'p',
        'р' => 'r',
        'с' => 's',
        'т' => 't',
        'ќ' => 'kj',
        'у' => 'u',
        'ф' => 'f',
        'х' => 'h',
        'ц' => 'c',
        'ч' => 'ch',
        'џ' => 'dj',
        'ш' => 'sh',
    ],
    // Portuguese (Brazil)
    'pt' => [
        'æ' => 'ae',
        'ǽ' => 'ae',
        'À' => 'A',
        'Á' => 'A',
        'Â' => 'A',
        'Ã' => 'A',
        'Å' => 'AA',
        'Ǻ' => 'A',
        'Ă' => 'A',
        'Ǎ' => 'A',
        'Æ' => 'AE',
        'Ǽ' => 'AE',
        'à' => 'a',
        'á' => 'a',
        'â' => 'a',
        'ã' => 'a',
        'å' => 'aa',
        'ǻ' => 'a',
        'ă' => 'a',
        'ǎ' => 'a',
        'ª' => 'a',
        'Ĉ' => 'C',
        'Ċ' => 'C',
        'Ç' => 'C',
        'ç' => 'c',
        'ĉ' => 'c',
        'ċ' => 'c',
        'Ð' => 'Dj',
        'Đ' => 'D',
        'ð' => 'dj',
        'đ' => 'd',
        'È' => 'E',
        'É' => 'E',
        'Ê' => 'E',
        'Ë' => 'E',
        'Ĕ' => 'E',
        'Ė' => 'E',
        'è' => 'e',
        'é' => 'e',
        'ê' => 'e',
        'ë' => 'e',
        'ĕ' => 'e',
        'ė' => 'e',
        'ƒ' => 'f',
        'Ĝ' => 'G',
        'Ġ' => 'G',
        'ĝ' => 'g',
        'ġ' => 'g',
        'Ĥ' => 'H',
        'Ħ' => 'H',
        'ĥ' => 'h',
        'ħ' => 'h',
        'Ì' => 'I',
        'Í' => 'I',
        'Î' => 'I',
        'Ï' => 'I',
        'Ĩ' => 'I',
        'Ĭ' => 'I',
        'Ǐ' => 'I',
        'Į' => 'I',
        'Ĳ' => 'IJ',
        'ì' => 'i',
        'í' => 'i',
        'î' => 'i',
        'ï' => 'i',
        'ĩ' => 'i',
        'ĭ' => 'i',
        'ǐ' => 'i',
        'į' => 'i',
        'ĳ' => 'ij',
        'Ĵ' => 'J',
        'ĵ' => 'j',
        'Ĺ' => 'L',
        'Ľ' => 'L',
        'Ŀ' => 'L',
        'ĺ' => 'l',
        'ľ' => 'l',
        'ŀ' => 'l',
        'Ñ' => 'N',
        'ñ' => 'n',
        'ŉ' => 'n',
        'Ò' => 'O',
        'Ó' => 'O',
        'Ô' => 'O',
        'Õ' => 'O',
        'Ō' => 'O',
        'Ŏ' => 'O',
        'Ǒ' => 'O',
        'Ő' => 'O',
        'Ơ' => 'O',
        'Ø' => 'OE',
        'Ǿ' => 'O',
        'Œ' => 'OE',
        'ò' => 'o',
        'ó' => 'o',
        'ô' => 'o',
        'õ' => 'o',
        'ō' => 'o',
        'ŏ' => 'o',
        'ǒ' => 'o',
        'ő' => 'o',
        'ơ' => 'o',
        'ø' => 'oe',
        'ǿ' => 'o',
        'º' => 'o',
        'œ' => 'oe',
        'Ŕ' => 'R',
        'Ŗ' => 'R',
        'ŕ' => 'r',
        'ŗ' => 'r',
        'Ŝ' => 'S',
        'Ș' => 'S',
        'ŝ' => 's',
        'ș' => 's',
        'ſ' => 's',
        'Ţ' => 'T',
        'Ț' => 'T',
        'Ŧ' => 'T',
        'Þ' => 'TH',
        'ţ' => 't',
        'ț' => 't',
        'ŧ' => 't',
        'þ' => 'th',
        'Ù' => 'U',
        'Ú' => 'U',
        'Û' => 'U',
        'Ü' => 'U',
        'Ũ' => 'U',
        'Ŭ' => 'U',
        'Ű' => 'U',
        'Ų' => 'U',
        'Ư' => 'U',
        'Ǔ' => 'U',
        'Ǖ' => 'U',
        'Ǘ' => 'U',
        'Ǚ' => 'U',
        'Ǜ' => 'U',
        'ù' => 'u',
        'ú' => 'u',
        'û' => 'u',
        'ü' => 'u',
        'ũ' => 'u',
        'ŭ' => 'u',
        'ű' => 'u',
        'ų' => 'u',
        'ư' => 'u',
        'ǔ' => 'u',
        'ǖ' => 'u',
        'ǘ' => 'u',
        'ǚ' => 'u',
        'ǜ' => 'u',
        'Ŵ' => 'W',
        'ŵ' => 'w',
        'Ý' => 'Y',
        'Ÿ' => 'Y',
        'Ŷ' => 'Y',
        'ý' => 'y',
        'ÿ' => 'y',
        'ŷ' => 'y',
    ],
    // Greek(lish) (Elláda)
    'el__greeklish' => [
        'ΑΥ' => 'AU',
        'ΑΎ' => 'AU',
        'Αυ' => 'Au',
        'Αύ' => 'Au',
        'ΕΊ' => 'EI',
        'ΕΙ' => 'EI',
        'Ει' => 'EI',
        'ΕΥ' => 'EU',
        'ΕΎ' => 'EU',
        'Εί' => 'Ei',
        'Ευ' => 'Eu',
        'Εύ' => 'Eu',
        'ΟΙ' => 'OI',
        'ΟΊ' => 'OI',
        'ΟΥ' => 'OU',
        'ΟΎ' => 'OU',
        'Οι' => 'Oi',
        'Οί' => 'Oi',
        'Ου' => 'Ou',
        'Ού' => 'Ou',
        'ΥΙ' => 'YI',
        'ΎΙ' => 'YI',
        'Υι' => 'Yi',
        'Ύι' => 'Yi',
        'ΥΊ' => 'Yi',
        'Υί' => 'Yi',
        'αυ' => 'au',
        'αύ' => 'au',
        'εί' => 'ei',
        'ει' => 'ei',
        'ευ' => 'eu',
        'εύ' => 'eu',
        'οι' => 'oi',
        'οί' => 'oi',
        'ου' => 'ou',
        'ού' => 'ou',
        'υι' => 'yi',
        'ύι' => 'yi',
        'υί' => 'yi',
        'Α'  => 'A',
        'Ά'  => 'A',
        'Β'  => 'B',
        'Δ'  => 'D',
        'Ε'  => 'E',
        'Έ'  => 'E',
        'Φ'  => 'F',
        'Γ'  => 'G',
        'Η'  => 'H',
        'Ή'  => 'H',
        'Ι'  => 'I',
        'Ί'  => 'I',
        'Ϊ'  => 'I',
        'Κ'  => 'K',
        'Ξ'  => 'Ks',
        'Λ'  => 'L',
        'Μ'  => 'M',
        'Ν'  => 'N',
        'Π'  => 'N',
        'Ο'  => 'O',
        'Ό'  => 'O',
        'Ψ'  => 'Ps',
        'Ρ'  => 'R',
        'Σ'  => 'S',
        'Τ'  => 'T',
        'Θ'  => 'Th',
        'Ω'  => 'W',
        'Ώ'  => 'W',
        'Χ'  => 'X',
        'ϒ'  => 'Y',
        'Υ'  => 'Y',
        'Ύ'  => 'Y',
        'Ϋ'  => 'Y',
        'Ζ'  => 'Z',
        'α'  => 'a',
        'ά'  => 'a',
        'β'  => 'b',
        'δ'  => 'd',
        'ε'  => 'e',
        'έ'  => 'e',
        'φ'  => 'f',
        'γ'  => 'g',
        'η'  => 'h',
        'ή'  => 'h',
        'ι'  => 'i',
        'ί'  => 'i',
        'ϊ'  => 'i',
        'ΐ'  => 'i',
        'κ'  => 'k',
        'ξ'  => 'ks',
        'λ'  => 'l',
        'μ'  => 'm',
        'ν'  => 'n',
        'ο'  => 'o',
        'ό'  => 'o',
        'π'  => 'p',
        'ψ'  => 'ps',
        'ρ'  => 'r',
        'σ'  => 's',
        'ς'  => 's',
        'τ'  => 't',
        'ϑ'  => 'th',
        'θ'  => 'th',
        'ϐ'  => 'v',
        'ω'  => 'w',
        'ώ'  => 'w',
        'χ'  => 'x',
        'υ'  => 'y',
        'ύ'  => 'y',
        'ΰ'  => 'y',
        'ϋ'  => 'y',
        'ζ'  => 'z',
    ],
    // Greek (Elláda)
    'el' => [
        'ΑΥ' => 'AU',
        'Αυ' => 'Au',
        'ΟΥ' => 'U',
        'Ου' => 'u',
        'ΕΥ' => 'EF',
        'Ευ' => 'Ef',
        'ΕΙ' => 'I',
        'Ει' => 'I',
        'ΟΙ' => 'I',
        'Οι' => 'I',
        'ΥΙ' => 'I',
        'Υι' => 'I',
        'ΑΎ' => 'AU',
        'Αύ' => 'Au',
        'ΟΎ' => 'OU',
        'Ού' => 'Ou',
        'ΕΎ' => 'EU',
        'Εύ' => 'Eu',
        'ΕΊ' => 'I',
        'Εί' => 'I',
        'ΟΊ' => 'I',
        'Οί' => 'I',
        'ΎΙ' => 'I',
        'Ύι' => 'I',
        'ΥΊ' => 'I',
        'Υί' => 'I',
        'αυ' => 'au',
        'ου' => 'u',
        'ευ' => 'ef',
        'ει' => 'i',
        'οι' => 'i',
        'υι' => 'i',
        'αύ' => 'au',
        'ού' => 'ou',
        'εύ' => 'eu',
        'εί' => 'i',
        'οί' => 'i',
        'ύι' => 'i',
        'υί' => 'i',
        'α'  => 'a',
        'β'  => 'v',
        'γ'  => 'gh',
        'δ'  => 'd',
        'ε'  => 'e',
        'ζ'  => 'z',
        'η'  => 'i',
        'θ'  => 'th',
        'ι'  => 'i',
        'κ'  => 'k',
        'λ'  => 'l',
        'μ'  => 'm',
        'ν'  => 'n',
        'ξ'  => 'ks',
        'ο'  => 'o',
        'π'  => 'p',
        'ρ'  => 'r',
        'σ'  => 's',
        'τ'  => 't',
        'υ'  => 'i',
        'φ'  => 'f',
        'χ'  => 'kh',
        'ψ'  => 'ps',
        'ω'  => 'o',
        'ά'  => 'a',
        'έ'  => 'e',
        'ί'  => 'i',
        'ό'  => 'o',
        'ϒ'  => 'Y',
        'ύ'  => 'y',
        'ή'  => 'i',
        'ώ'  => 'w',
        'ς'  => 's',
        'ϊ'  => 'i',
        'ΰ'  => 'y',
        'ϋ'  => 'y',
        'ΐ'  => 'i',
        'Α'  => 'A',
        'Β'  => 'B',
        'Γ'  => 'G',
        'Δ'  => 'D',
        'Ε'  => 'E',
        'Ζ'  => 'Z',
        'Η'  => 'H',
        'Θ'  => 'Th',
        'Ι'  => 'I',
        'Κ'  => 'K',
        'Λ'  => 'L',
        'Μ'  => 'M',
        'Ν'  => 'N',
        'Ξ'  => 'Ks',
        'Ο'  => 'O',
        'Π'  => 'P',
        'Ρ'  => 'R',
        'Σ'  => 'S',
        'Τ'  => 'T',
        'Υ'  => 'Y',
        'Φ'  => 'F',
        'Χ'  => 'X',
        'Ψ'  => 'Ps',
        'Ω'  => 'O',
        'Ά'  => 'A',
        'Έ'  => 'E',
        'Ί'  => 'I',
        'Ό'  => 'O',
        'Ύ'  => 'Y',
        'Ή'  => 'I',
        'Ώ'  => 'W',
        'Ϊ'  => 'I',
        'Ϋ'  => 'Y',
        'ϐ'  => 'v',
        'ϑ'  => 'th',
    ],
    // Hindi
    'hi' => [
        'अ'  => 'a',
        'आ'  => 'aa',
        'ए'  => 'e',
        'ई'  => 'ii',
        'ऍ'  => 'ei',
        'ऎ'  => 'ae',
        'ऐ'  => 'ai',
        'इ'  => 'i',
        'ओ'  => 'o',
        'ऑ'  => 'oi',
        'ऒ'  => 'oii',
        'ऊ'  => 'uu',
        'औ'  => 'ou',
        'उ'  => 'u',
        'ब'  => 'B',
        'भ'  => 'Bha',
        'च'  => 'Ca',
        'छ'  => 'Chha',
        'ड'  => 'Da',
        'ढ'  => 'Dha',
        'फ'  => 'Fa',
        'फ़' => 'Fi',
        'ग'  => 'Ga',
        'घ'  => 'Gha',
        'ग़' => 'Ghi',
        'ह'  => 'Ha',
        'ज'  => 'Ja',
        'झ'  => 'Jha',
        'क'  => 'Ka',
        'ख'  => 'Kha',
        'ख़' => 'Khi',
        'ल'  => 'L',
        'ळ'  => 'Li',
        'ऌ'  => 'Li',
        'ऴ'  => 'Lii',
        'ॡ'  => 'Lii',
        'म'  => 'Ma',
        'न'  => 'Na',
        'ङ'  => 'Na',
        'ञ'  => 'Nia',
        'ण'  => 'Nae',
        'ऩ'  => 'Ni',
        'ॐ'  => 'oms',
        'प'  => 'Pa',
        'क़' => 'Qi',
        'र'  => 'Ra',
        'ऋ'  => 'Ri',
        'ॠ'  => 'Ri',
        'ऱ'  => 'Ri',
        'स'  => 'Sa',
        'श'  => 'Sha',
        'ष'  => 'Shha',
        'ट'  => 'Ta',
        'त'  => 'Ta',
        'ठ'  => 'Tha',
        'द'  => 'Tha',
        'थ'  => 'Tha',
        'ध'  => 'Thha',
        'ड़' => 'ugDha',
        'ढ़' => 'ugDhha',
        'व'  => 'Va',
        'य'  => 'Ya',
        'य़' => 'Yi',
        'ज़' => 'Za',
    ],
    // Armenian
    'hy' => [
        'Ա' => 'A',
        'Բ' => 'B',
        'Գ' => 'G',
        'Դ' => 'D',
        'Ե' => 'E',
        'Զ' => 'Z',
        'Է' => 'E',
        'Ը' => 'Y',
        'Թ' => 'Th',
        'Ժ' => 'Zh',
        'Ի' => 'I',
        'Լ' => 'L',
        'Խ' => 'Kh',
        'Ծ' => 'Ts',
        'Կ' => 'K',
        'Հ' => 'H',
        'Ձ' => 'Dz',
        'Ղ' => 'Gh',
        'Ճ' => 'Tch',
        'Մ' => 'M',
        'Յ' => 'Y',
        'Ն' => 'N',
        'Շ' => 'Sh',
        'Ո' => 'Vo',
        'Չ' => 'Ch',
        'Պ' => 'P',
        'Ջ' => 'J',
        'Ռ' => 'R',
        'Ս' => 'S',
        'Վ' => 'V',
        'Տ' => 'T',
        'Ր' => 'R',
        'Ց' => 'C',
        'Ւ' => 'u',
        'Փ' => 'Ph',
        'Ք' => 'Q',
        'և' => 'ev',
        'Օ' => 'O',
        'Ֆ' => 'F',
        'ա' => 'a',
        'բ' => 'b',
        'գ' => 'g',
        'դ' => 'd',
        'ե' => 'e',
        'զ' => 'z',
        'է' => 'e',
        'ը' => 'y',
        'թ' => 'th',
        'ժ' => 'zh',
        'ի' => 'i',
        'լ' => 'l',
        'խ' => 'kh',
        'ծ' => 'ts',
        'կ' => 'k',
        'հ' => 'h',
        'ձ' => 'dz',
        'ղ' => 'gh',
        'ճ' => 'tch',
        'մ' => 'm',
        'յ' => 'y',
        'ն' => 'n',
        'շ' => 'sh',
        'ո' => 'vo',
        'չ' => 'ch',
        'պ' => 'p',
        'ջ' => 'j',
        'ռ' => 'r',
        'ս' => 's',
        'վ' => 'v',
        'տ' => 't',
        'ր' => 'r',
        'ց' => 'c',
        'ւ' => 'u',
        'փ' => 'ph',
        'ք' => 'q',
        'օ' => 'o',
        'ֆ' => 'f',
    ],
    // Swedish
    'sv' => [
        'Ä' => 'A',
        'ä' => 'a',
        'Å' => 'A',
        'å' => 'a',
        'Ö' => 'O',
        'ö' => 'o',
    ],
    // Turkmen
    'tk' => [
        'Ç' => 'C',
        'Ä' => 'A',
        'Ž' => 'Z',
        'Ň' => 'N',
        'Ö' => 'O',
        'Ş' => 'S',
        'Ü' => 'U',
        'Ý' => 'Y',
        'ç' => 'c',
        'ä' => 'a',
        'ž' => 'z',
        'ň' => 'n',
        'ö' => 'o',
        'ş' => 's',
        'ü' => 'u',
        'ý' => 'y',
    ],
    // Turkish
    'tr' => [
        'ň' => 'n',
        'Ň' => 'N',
        'ş' => 's',
        'Ş' => 'S',
        'ı' => 'i',
        'İ' => 'I',
        'ç' => 'c',
        'Ç' => 'C',
        'ä' => 'a',
        'Ä' => 'A',
        'ü' => 'u',
        'Ü' => 'U',
        'ö' => 'o',
        'Ö' => 'O',
        'ğ' => 'g',
        'Ğ' => 'G',
        'ý' => 'y',
        'Ý' => 'Y',
        'ž' => 'z',
        'Ž' => 'Z',
    ],
    // Bulgarian
    'bg' => [
        'ьо' => 'yo',
        'А'  => 'A',
        'Б'  => 'B',
        'В'  => 'V',
        'Г'  => 'G',
        'Д'  => 'D',
        'Е'  => 'E',
        'Ж'  => 'Zh',
        'З'  => 'Z',
        'И'  => 'I',
        'Й'  => 'Y',
        'К'  => 'K',
        'Л'  => 'L',
        'М'  => 'M',
        'Н'  => 'N',
        'О'  => 'O',
        'П'  => 'P',
        'Р'  => 'R',
        'С'  => 'S',
        'Т'  => 'T',
        'У'  => 'U',
        'Ф'  => 'F',
        'Х'  => 'H',
        'Ц'  => 'C',
        'Ч'  => 'Ch',
        'Ш'  => 'Sh',
        'Щ'  => 'Sht',
        'Ъ'  => 'A',
        'Ь'  => '',
        'Ю'  => 'Yu',
        'Я'  => 'Ya',
        'а'  => 'a',
        'б'  => 'b',
        'в'  => 'v',
        'г'  => 'g',
        'д'  => 'd',
        'е'  => 'e',
        'ж'  => 'zh',
        'з'  => 'z',
        'и'  => 'i',
        'й'  => 'y',
        'к'  => 'k',
        'л'  => 'l',
        'м'  => 'm',
        'н'  => 'n',
        'о'  => 'o',
        'п'  => 'p',
        'р'  => 'r',
        'с'  => 's',
        'т'  => 't',
        'у'  => 'u',
        'ф'  => 'f',
        'х'  => 'h',
        'ц'  => 'c',
        'ч'  => 'ch',
        'ш'  => 'sh',
        'щ'  => 'sht',
        'ъ'  => 'a',
        'ь'  => '',
        'ю'  => 'yu',
        'я'  => 'ya',
    ],
    // Hungarian
    'hu' => [
        'Á' => 'A',
        'Ē' => 'E',
        'É' => 'E',
        'Í' => 'I',
        'Ó' => 'O',
        'Ö' => 'O',
        'Ő' => 'O',
        'Ú' => 'U',
        'Ü' => 'U',
        'Ű' => 'U',
        'á' => 'a',
        'ē' => 'e',
        'é' => 'e',
        'í' => 'i',
        'ó' => 'o',
        'ö' => 'o',
        'ő' => 'o',
        'ú' => 'u',
        'ü' => 'u',
        'ű' => 'u',
    ],
    // Myanmar (Burmese)
    'my' => [
        'န်ုပ်' => 'nub',
        'ောင်'  => 'aung',
        'ိုက်'  => 'aik',
        'ိုဒ်'  => 'ok',
        'ိုင်'  => 'aing',
        'ိုလ်'  => 'ol',
        'ေါင်'  => 'aung',
        'သြော'  => 'aw',
        'ောက်'  => 'auk',
        'ိတ်'   => 'eik',
        'ုတ်'   => 'ok',
        'ုန်'   => 'on',
        'ေတ်'   => 'it',
        'ုဒ်'   => 'ait',
        'ာန်'   => 'an',
        'ိန်'   => 'ein',
        'ွတ်'   => 'ut',
        'ေါ်'   => 'aw',
        'ွန်'   => 'un',
        'ိပ်'   => 'eik',
        'ုပ်'   => 'ok',
        'ွပ်'   => 'ut',
        'ိမ်'   => 'ein',
        'ုမ်'   => 'on',
        'ော်'   => 'aw',
        'ွမ်'   => 'un',
        'က်'    => 'et',
        'ေါ'    => 'aw',
        'ော'    => 'aw',
        'ျွ'    => 'ywa',
        'ြွ'    => 'yw',
        'ို'    => 'o',
        'ုံ'    => 'on',
        'တ်'    => 'at',
        'င်'    => 'in',
        'ည်'    => 'i',
        'ဒ်'    => 'd',
        'န်'    => 'an',
        'ပ်'    => 'at',
        'မ်'    => 'an',
        'စျ'    => 'za',
        'ယ်'    => 'e',
        'ဉ်'    => 'in',
        'စ်'    => 'it',
        'ိံ'    => 'ein',
        'ဲ'     => 'e',
        'း'     => '',
        'ာ'     => 'a',
        'ါ'     => 'a',
        'ေ'     => 'e',
        'ံ'     => 'an',
        'ိ'     => 'i',
        'ီ'     => 'i',
        'ု'     => 'u',
        'ူ'     => 'u',
        '်'     => 'at',
        '္'     => '',
        '့'     => '',
        'က'     => 'k',
        '၉'     => '9',
        'တ'     => 't',
        'ရ'     => 'ya',
        'ယ'     => 'y',
        'မ'     => 'm',
        'ဘ'     => 'ba',
        'ဗ'     => 'b',
        'ဖ'     => 'pa',
        'ပ'     => 'p',
        'န'     => 'n',
        'ဓ'     => 'da',
        'ဒ'     => 'd',
        'ထ'     => 'ta',
        'ဏ'     => 'na',
        'ဝ'     => 'w',
        'ဎ'     => 'da',
        'ဍ'     => 'd',
        'ဌ'     => 'ta',
        'ဋ'     => 't',
        'ည'     => 'ny',
        'ဇ'     => 'z',
        'ဆ'     => 'sa',
        'စ'     => 's',
        'င'     => 'ng',
        'ဃ'     => 'ga',
        'ဂ'     => 'g',
        'လ'     => 'l',
        'သ'     => 'th',
        '၈'     => '8',
        'ဩ'     => 'aw',
        'ခ'     => 'kh',
        '၆'     => '6',
        '၅'     => '5',
        '၄'     => '4',
        '၃'     => '3',
        '၂'     => '2',
        '၁'     => '1',
        '၀'     => '0',
        '၌'     => 'hnaik',
        '၍'     => 'ywae',
        'ဪ'     => 'aw',
        'ဦ'     => '-u',
        'ဟ'     => 'h',
        'ဉ'     => 'u',
        'ဤ'     => '-i',
        'ဣ'     => 'i',
        '၏'     => '-e',
        'ဧ'     => 'e',
        'ှ'     => 'h',
        'ွ'     => 'w',
        'ျ'     => 'ya',
        'ြ'     => 'y',
        'အ'     => 'a',
        'ဠ'     => 'la',
        '၇'     => '7',
    ],
    // Croatian (Hrvatska)
    'hr' => [
        'DŽ' => 'DZ',
        'Dž' => 'Dz',
        'dž' => 'dz',
        'Ǳ'  => 'DZ',
        'ǲ'  => 'Dz',
        'ǳ'  => 'dz',
        'Ĳ'  => 'IJ',
        'ĳ'  => 'ij',
        'Ǉ'  => 'LJ',
        'ǈ'  => 'Lj',
        'ǉ'  => 'lj',
        'Ǌ'  => 'NJ',
        'ǋ'  => 'Nj',
        'ǌ'  => 'nj',
        'ž'  => 'z',
        'Ž'  => 'Z',
        'đ'  => 'dj',
        'Đ'  => 'Dj',
        'č'  => 'c',
        'Č'  => 'C',
        'ć'  => 'c',
        'Ć'  => 'C',
        'š'  => 's',
        'Š'  => 'S',
    ],
    // Finnish
    'fi' => [
        'Ä' => 'A',
        'Ö' => 'O',
        'ä' => 'a',
        'ö' => 'o',
    ],
    // Georgian (Kartvelian)
    'ka' => [
        'ა' => 'a',
        'ბ' => 'b',
        'გ' => 'g',
        'დ' => 'd',
        'ე' => 'e',
        'ვ' => 'v',
        'ზ' => 'z',
        'თ' => 't',
        'ი' => 'i',
        'კ' => 'k',
        'ლ' => 'l',
        'მ' => 'm',
        'ნ' => 'n',
        'ო' => 'o',
        'პ' => 'p',
        'ჟ' => 'zh',
        'რ' => 'r',
        'ს' => 's',
        'ტ' => 't',
        'უ' => 'u',
        'ფ' => 'f',
        'ქ' => 'q',
        'ღ' => 'gh',
        'ყ' => 'y',
        'შ' => 'sh',
        'ჩ' => 'ch',
        'ც' => 'ts',
        'ძ' => 'dz',
        'წ' => 'ts',
        'ჭ' => 'ch',
        'ხ' => 'kh',
        'ჯ' => 'j',
        'ჰ' => 'h',
    ],
    // Russian
    'ru' => [
        'А' => 'A',
        'а' => 'a',
        'Б' => 'B',
        'б' => 'b',
        'В' => 'V',
        'в' => 'v',
        'Г' => 'G',
        'г' => 'g',
        'Д' => 'D',
        'д' => 'd',
        'Е' => 'E',
        'е' => 'e',
        'Ё' => 'Yo',
        'ё' => 'yo',
        'Ж' => 'Zh',
        'ж' => 'zh',
        'З' => 'Z',
        'з' => 'z',
        'И' => 'I',
        'и' => 'i',
        'Й' => 'Y',
        'й' => 'y',
        'К' => 'K',
        'к' => 'k',
        'Л' => 'L',
        'л' => 'l',
        'М' => 'M',
        'м' => 'm',
        'Н' => 'N',
        'н' => 'n',
        'О' => 'O',
        'о' => 'o',
        'П' => 'P',
        'п' => 'p',
        'Р' => 'R',
        'р' => 'r',
        'С' => 'S',
        'с' => 's',
        'Т' => 'T',
        'т' => 't',
        'У' => 'U',
        'у' => 'u',
        'Ф' => 'F',
        'ф' => 'f',
        'Х' => 'H',
        'х' => 'h',
        'Ц' => 'Ts',
        'ц' => 'ts',
        'Ч' => 'Ch',
        'ч' => 'ch',
        'ш' => 'sh',
        'Ш' => 'Sh',
        'Щ' => 'Sch',
        'щ' => 'sch',
        'Ъ' => '',
        'ъ' => '',
        'Ы' => 'Y',
        'ы' => 'y',
        'Ь' => '',
        'ь' => '',
        'Э' => 'E',
        'э' => 'e',
        'Ю' => 'Yu',
        'ю' => 'yu',
        'Я' => 'Ya',
        'я' => 'ya',
    ],
    // Russian - GOST 7.79-2000(B)
    // -> https://en.m.wikipedia.org/wiki/Romanization_of_Russian#content-collapsible-block-1
    'ru__gost_2000_b' => [
        'А' => 'A',
        'а' => 'a',
        'Б' => 'B',
        'б' => 'b',
        'В' => 'V',
        'в' => 'v',
        'Г' => 'G',
        'г' => 'g',
        'Д' => 'D',
        'д' => 'd',
        'Е' => 'E',
        'е' => 'e',
        'Ё' => 'Yo',
        'ё' => 'yo',
        'Ж' => 'Zh',
        'ж' => 'zh',
        'З' => 'Z',
        'з' => 'z',
        'И' => 'i',
        'и' => 'i',
        'Й' => 'i',
        'й' => 'i',
        'К' => 'K',
        'к' => 'k',
        'Л' => 'L',
        'л' => 'l',
        'М' => 'M',
        'м' => 'm',
        'Н' => 'N',
        'н' => 'n',
        'О' => 'O',
        'о' => 'o',
        'П' => 'P',
        'п' => 'p',
        'Р' => 'R',
        'р' => 'r',
        'С' => 'S',
        'с' => 's',
        'Т' => 'T',
        'т' => 't',
        'У' => 'U',
        'у' => 'u',
        'Ф' => 'F',
        'ф' => 'f',
        'Х' => 'X',
        'х' => 'x',
        'Ц' => 'Cz',
        'ц' => 'cz',
        'Ч' => 'Ch',
        'ч' => 'ch',
        'ш' => 'sh',
        'Ш' => 'Sh',
        'Щ' => 'Shh',
        'щ' => 'shh',
        'Ъ' => '',
        'ъ' => '',
        'Ы' => 'Y\'',
        'ы' => 'y\'',
        'Ь' => '',
        'ь' => '',
        'Э' => 'E\'',
        'э' => 'e\'',
        'Ю' => 'Yu',
        'ю' => 'yu',
        'Я' => 'Ya',
        'я' => 'ya',
        'І' => 'I',
        'і' => 'i',
        'Ѳ' => 'Fh',
        'ѳ' => 'fh',
        'Ѣ' => 'Ye',
        'ѣ' => 'ye',
        'Ѵ' => 'Yh',
        'ѵ' => 'yh',
        'Є' => '',
        'є' => '',
        'Ѥ' => '',
        'ѥ' => '',
        'Ѕ' => 'Js',
        'ѕ' => 'js',
        'Ꙋ' => '',
        'ꙋ' => '',
        'Ѡ' => '',
        'ѡ' => '',
        'Ѿ' => '',
        'ѿ' => '',
        'Ѫ' => '',
        'ѫ' => '',
        'Ѧ' => '',
        'ѧ' => '',
        'Ѭ' => '',
        'ѭ' => '',
        'Ѩ' => '',
        'ѩ' => '',
        'Ѯ' => '',
        'ѯ' => '',
        'Ѱ' => '',
        'ѱ' => '',
    ],
    // Russian - Passport (2013), ICAO
    // -> https://en.m.wikipedia.org/wiki/Romanization_of_Russian#content-collapsible-block-1
    'ru__passport_2013' => [
        'А' => 'A',
        'а' => 'a',
        'Б' => 'B',
        'б' => 'b',
        'В' => 'V',
        'в' => 'v',
        'Г' => 'G',
        'г' => 'g',
        'Д' => 'D',
        'д' => 'd',
        'Е' => 'E',
        'е' => 'e',
        'Ё' => 'E',
        'ё' => 'e',
        'Ж' => 'Zh',
        'ж' => 'zh',
        'З' => 'Z',
        'з' => 'z',
        'И' => 'i',
        'и' => 'i',
        'Й' => 'i',
        'й' => 'i',
        'К' => 'K',
        'к' => 'k',
        'Л' => 'L',
        'л' => 'l',
        'М' => 'M',
        'м' => 'm',
        'Н' => 'N',
        'н' => 'n',
        'О' => 'O',
        'о' => 'o',
        'П' => 'P',
        'п' => 'p',
        'Р' => 'R',
        'р' => 'r',
        'С' => 'S',
        'с' => 's',
        'Т' => 'T',
        'т' => 't',
        'У' => 'U',
        'у' => 'u',
        'Ф' => 'F',
        'ф' => 'f',
        'Х' => 'Kh',
        'х' => 'kh',
        'Ц' => 'Ts',
        'ц' => 'ts',
        'Ч' => 'Ch',
        'ч' => 'ch',
        'ш' => 'sh',
        'Ш' => 'Sh',
        'Щ' => 'Shch',
        'щ' => 'shch',
        'Ъ' => 'Ie',
        'ъ' => 'ie',
        'Ы' => 'Y',
        'ы' => 'y',
        'Ь' => '',
        'ь' => '',
        'Э' => 'E',
        'э' => 'e',
        'Ю' => 'Iu',
        'ю' => 'iu',
        'Я' => 'Ia',
        'я' => 'ia',
        'І' => '',
        'і' => '',
        'Ѳ' => '',
        'ѳ' => '',
        'Ѣ' => '',
        'ѣ' => '',
        'Ѵ' => '',
        'ѵ' => '',
        'Є' => '',
        'є' => '',
        'Ѥ' => '',
        'ѥ' => '',
        'Ѕ' => '',
        'ѕ' => '',
        'Ꙋ' => '',
        'ꙋ' => '',
        'Ѡ' => '',
        'ѡ' => '',
        'Ѿ' => '',
        'ѿ' => '',
        'Ѫ' => '',
        'ѫ' => '',
        'Ѧ' => '',
        'ѧ' => '',
        'Ѭ' => '',
        'ѭ' => '',
        'Ѩ' => '',
        'ѩ' => '',
        'Ѯ' => '',
        'ѯ' => '',
        'Ѱ' => '',
        'ѱ' => '',
    ],
    // Ukrainian
    // -> https://zakon.rada.gov.ua/laws/show/55-2010-%D0%BF?lang=en
    'uk' => [
        'Г' => 'H',
        'г' => 'h',
        'Ґ' => 'G',
        'ґ' => 'g',
        'Є' => 'Ye',
        'є' => 'ye',
        'И' => 'Y',
        'и' => 'y',
        'І' => 'I',
        'і' => 'i',
        'Ї' => 'Yi',
        'ї' => 'yi',
        'Й' => 'Y',
        'й' => 'y',
        'Х' => 'Kh',
        'х' => 'kh',
        'Ц' => 'Ts',
        'ц' => 'ts',
        'Ч' => 'Ch',
        'ч' => 'ch',
        'Ш' => 'Sh',
        'ш' => 'sh',
        'Щ' => 'Shch',
        'щ' => 'shch',
    ],
    // Kazakh
    'kk' => [
        'Ә' => 'A',
        'Ғ' => 'G',
        'Қ' => 'Q',
        'Ң' => 'N',
        'Ө' => 'O',
        'Ұ' => 'U',
        'Ү' => 'U',
        'Һ' => 'H',
        'ә' => 'a',
        'ғ' => 'g',
        'қ' => 'q',
        'ң' => 'n',
        'ө' => 'o',
        'ұ' => 'u',
        'ү' => 'u',
        'һ' => 'h',
    ],
    // Czech
    'cs' => [
        'á' => 'a',
        'Á' => 'A',
        'č' => 'c',
        'Č' => 'C',
        'ď' => 'd',
        'Ď' => 'D',
        'é' => 'e',
        'É' => 'E',
        'ě' => 'e',
        'Ě' => 'E',
        'í' => 'i',
        'Í' => 'I',
        'ň' => 'n',
        'Ň' => 'N',
        'ó' => 'o',
        'Ó' => 'O',
        'ř' => 'r',
        'Ř' => 'R',
        'š' => 's',
        'Š' => 'S',
        'ť' => 't',
        'Ť' => 'T',
        'ú' => 'u',
        'Ú' => 'U',
        'ů' => 'u',
        'Ů' => 'U',
        'ý' => 'y',
        'Ý' => 'Y',
        'ž' => 'z',
        'Ž' => 'Z',
    ],
    // Danish
    'da' => [
        'Æ' => 'Ae',
        'æ' => 'ae',
        'Ø' => 'Oe',
        'ø' => 'oe',
        'Å' => 'Aa',
        'å' => 'aa',
        'É' => 'E',
        'é' => 'e',
    ],
    // Polish
    'pl' => [
        'ą' => 'a',
        'ć' => 'c',
        'ę' => 'e',
        'ł' => 'l',
        'ń' => 'n',
        'ó' => 'o',
        'ś' => 's',
        'ź' => 'z',
        'ż' => 'z',
        'Ą' => 'A',
        'Ć' => 'C',
        'Ę' => 'E',
        'Ł' => 'L',
        'Ń' => 'N',
        'Ó' => 'O',
        'Ś' => 'S',
        'Ź' => 'Z',
        'Ż' => 'Z',
    ],
    // Romanian
    'ro' => [
        'ă' => 'a',
        'â' => 'a',
        'Ă' => 'A',
        'Â' => 'A',
        'î' => 'i',
        'Î' => 'I',
        'ș' => 's',
        'ş' => 's',
        'Ş' => 'S',
        'Ș' => 'S',
        'ț' => 't',
        'ţ' => 't',
        'Ţ' => 'T',
        'Ț' => 'T',
    ],
    // Esperanto
    'eo' => [
        'ĉ' => 'cx',
        'ĝ' => 'gx',
        'ĥ' => 'hx',
        'ĵ' => 'jx',
        'ŝ' => 'sx',
        'ŭ' => 'ux',
        'Ĉ' => 'CX',
        'Ĝ' => 'GX',
        'Ĥ' => 'HX',
        'Ĵ' => 'JX',
        'Ŝ' => 'SX',
        'Ŭ' => 'UX',
    ],
    // Estonian
    'et' => [
        'Š' => 'S',
        'Ž' => 'Z',
        'Õ' => 'O',
        'Ä' => 'A',
        'Ö' => 'O',
        'Ü' => 'U',
        'š' => 's',
        'ž' => 'z',
        'õ' => 'o',
        'ä' => 'a',
        'ö' => 'o',
        'ü' => 'u',
    ],
    // Latvian
    'lv' => [
        'ā' => 'a',
        'č' => 'c',
        'ē' => 'e',
        'ģ' => 'g',
        'ī' => 'i',
        'ķ' => 'k',
        'ļ' => 'l',
        'ņ' => 'n',
        'š' => 's',
        'ū' => 'u',
        'ž' => 'z',
        'Ā' => 'A',
        'Č' => 'C',
        'Ē' => 'E',
        'Ģ' => 'G',
        'Ī' => 'i',
        'Ķ' => 'k',
        'Ļ' => 'L',
        'Ņ' => 'N',
        'Š' => 'S',
        'Ū' => 'u',
        'Ž' => 'Z',
    ],
    // Lithuanian
    'lt' => [
        'ą' => 'a',
        'č' => 'c',
        'ę' => 'e',
        'ė' => 'e',
        'į' => 'i',
        'š' => 's',
        'ų' => 'u',
        'ū' => 'u',
        'ž' => 'z',
        'Ą' => 'A',
        'Č' => 'C',
        'Ę' => 'E',
        'Ė' => 'E',
        'Į' => 'I',
        'Š' => 'S',
        'Ų' => 'U',
        'Ū' => 'U',
        'Ž' => 'Z',
    ],
    // Norwegian
    'no' => [
        'Æ' => 'AE',
        'æ' => 'ae',
        'Ø' => 'OE',
        'ø' => 'oe',
        'Å' => 'AA',
        'å' => 'aa',
    ],
    // Vietnamese
    'vi' => [
        'Á' => 'A',
        'À' => 'A',
        'Ả' => 'A',
        'Ã' => 'A',
        'Ạ' => 'A',
        'Ă' => 'A',
        'Ắ' => 'A',
        'Ằ' => 'A',
        'Ẳ' => 'A',
        'Ẵ' => 'A',
        'Ặ' => 'A',
        'Â' => 'A',
        'Ấ' => 'A',
        'Ầ' => 'A',
        'Ẩ' => 'A',
        'Ẫ' => 'A',
        'Ậ' => 'A',
        'á' => 'a',
        'à' => 'a',
        'ả' => 'a',
        'ã' => 'a',
        'ạ' => 'a',
        'ă' => 'a',
        'ắ' => 'a',
        'ằ' => 'a',
        'ẳ' => 'a',
        'ẵ' => 'a',
        'ặ' => 'a',
        'â' => 'a',
        'ấ' => 'a',
        'ầ' => 'a',
        'ẩ' => 'a',
        'ẫ' => 'a',
        'ậ' => 'a',
        'É' => 'E',
        'È' => 'E',
        'Ẻ' => 'E',
        'Ẽ' => 'E',
        'Ẹ' => 'E',
        'Ê' => 'E',
        'Ế' => 'E',
        'Ề' => 'E',
        'Ể' => 'E',
        'Ễ' => 'E',
        'Ệ' => 'E',
        'é' => 'e',
        'è' => 'e',
        'ẻ' => 'e',
        'ẽ' => 'e',
        'ẹ' => 'e',
        'ê' => 'e',
        'ế' => 'e',
        'ề' => 'e',
        'ể' => 'e',
        'ễ' => 'e',
        'ệ' => 'e',
        'Í' => 'I',
        'Ì' => 'I',
        'Ỉ' => 'I',
        'Ĩ' => 'I',
        'Ị' => 'I',
        'í' => 'i',
        'ì' => 'i',
        'ỉ' => 'i',
        'ĩ' => 'i',
        'ị' => 'i',
        'Ó' => 'O',
        'Ò' => 'O',
        'Ỏ' => 'O',
        'Õ' => 'O',
        'Ọ' => 'O',
        'Ô' => 'O',
        'Ố' => 'O',
        'Ồ' => 'O',
        'Ổ' => 'O',
        'Ỗ' => 'O',
        'Ộ' => 'O',
        'Ơ' => 'O',
        'Ớ' => 'O',
        'Ờ' => 'O',
        'Ở' => 'O',
        'Ỡ' => 'O',
        'Ợ' => 'O',
        'ó' => 'o',
        'ò' => 'o',
        'ỏ' => 'o',
        'õ' => 'o',
        'ọ' => 'o',
        'ô' => 'o',
        'ố' => 'o',
        'ồ' => 'o',
        'ổ' => 'o',
        'ỗ' => 'o',
        'ộ' => 'o',
        'ơ' => 'o',
        'ớ' => 'o',
        'ờ' => 'o',
        'ở' => 'o',
        'ỡ' => 'o',
        'ợ' => 'o',
        'Ú' => 'U',
        'Ù' => 'U',
        'Ủ' => 'U',
        'Ũ' => 'U',
        'Ụ' => 'U',
        'Ư' => 'U',
        'Ứ' => 'U',
        'Ừ' => 'U',
        'Ử' => 'U',
        'Ữ' => 'U',
        'Ự' => 'U',
        'ú' => 'u',
        'ù' => 'u',
        'ủ' => 'u',
        'ũ' => 'u',
        'ụ' => 'u',
        'ư' => 'u',
        'ứ' => 'u',
        'ừ' => 'u',
        'ử' => 'u',
        'ữ' => 'u',
        'ự' => 'u',
        'Ý' => 'Y',
        'Ỳ' => 'Y',
        'Ỷ' => 'Y',
        'Ỹ' => 'Y',
        'Ỵ' => 'Y',
        'ý' => 'y',
        'ỳ' => 'y',
        'ỷ' => 'y',
        'ỹ' => 'y',
        'ỵ' => 'y',
        'Đ' => 'D',
        'đ' => 'd',
    ],
    // Persian (Farsi)
    'fa' => [
        'ا' => 'a',
        'ب' => 'b',
        'پ' => 'p',
        'ت' => 't',
        'ث' => 's',
        'ج' => 'j',
        'چ' => 'ch',
        'ح' => 'h',
        'خ' => 'kh',
        'د' => 'd',
        'ذ' => 'z',
        'ر' => 'r',
        'ز' => 'z',
        'س' => 's',
        'ش' => 'sh',
        'ص' => 's',
        'ض' => 'z',
        'ط' => 't',
        'ظ' => 'z',
        'ع' => 'a',
        'غ' => 'gh',
        'ف' => 'f',
        'ق' => 'gh',
        'ک' => 'k',
        'گ' => 'g',
        'ل' => 'l',
        'ژ' => 'zh',
        'ك' => 'k',
        'م' => 'm',
        'ن' => 'n',
        'ه' => 'h',
        'و' => 'o',
        'ی' => 'y',
        'آ' => 'a',
        '٠' => '0',
        '١' => '1',
        '٢' => '2',
        '٣' => '3',
        '٤' => '4',
        '٥' => '5',
        '٦' => '6',
        '٧' => '7',
        '٨' => '8',
        '٩' => '9',
    ],
    // Arabic
    'ar' => [
        'أ' => 'a',
        'ب' => 'b',
        'ت' => 't',
        'ث' => 'th',
        'ج' => 'g',
        'ح' => 'h',
        'خ' => 'kh',
        'د' => 'd',
        'ذ' => 'th',
        'ر' => 'r',
        'ز' => 'z',
        'س' => 's',
        'ش' => 'sh',
        'ص' => 's',
        'ض' => 'd',
        'ط' => 't',
        'ظ' => 'th',
        'ع' => 'aa',
        'غ' => 'gh',
        'ف' => 'f',
        'ق' => 'k',
        'ك' => 'k',
        'ل' => 'l',
        'م' => 'm',
        'ن' => 'n',
        'ه' => 'h',
        'و' => 'o',
        'ي' => 'y',
        'ا' => 'a',
        'إ' => 'a',
        'آ' => 'a',
        'ؤ' => 'o',
        'ئ' => 'y',
        'ء' => 'aa',
        '٠' => '0',
        '١' => '1',
        '٢' => '2',
        '٣' => '3',
        '٤' => '4',
        '٥' => '5',
        '٦' => '6',
        '٧' => '7',
        '٨' => '8',
        '٩' => '9',
    ],
    // Serbian
    'sr' => [
        'đ' => 'dj',
        'ž' => 'z',
        'ć' => 'c',
        'č' => 'c',
        'š' => 's',
        'Đ' => 'Dj',
        'Ž' => 'Z',
        'Ć' => 'C',
        'Č' => 'C',
        'Š' => 'S',
        'а' => 'a',
        'б' => 'b',
        'в' => 'v',
        'г' => 'g',
        'д' => 'd',
        'ђ' => 'dj',
        'е' => 'e',
        'ж' => 'z',
        'з' => 'z',
        'и' => 'i',
        'ј' => 'j',
        'к' => 'k',
        'л' => 'l',
        'љ' => 'lj',
        'м' => 'm',
        'н' => 'n',
        'њ' => 'nj',
        'о' => 'o',
        'п' => 'p',
        'р' => 'r',
        'с' => 's',
        'т' => 't',
        'ћ' => 'c',
        'у' => 'u',
        'ф' => 'f',
        'х' => 'h',
        'ц' => 'c',
        'ч' => 'c',
        'џ' => 'dz',
        'ш' => 's',
        'А' => 'A',
        'Б' => 'B',
        'В' => 'V',
        'Г' => 'G',
        'Д' => 'D',
        'Ђ' => 'Dj',
        'Е' => 'E',
        'Ж' => 'Z',
        'З' => 'Z',
        'И' => 'I',
        'Ј' => 'j',
        'К' => 'K',
        'Л' => 'L',
        'Љ' => 'Lj',
        'М' => 'M',
        'Н' => 'N',
        'Њ' => 'Nj',
        'О' => 'O',
        'П' => 'P',
        'Р' => 'R',
        'С' => 'S',
        'Т' => 'T',
        'Ћ' => 'C',
        'У' => 'U',
        'Ф' => 'F',
        'Х' => 'H',
        'Ц' => 'C',
        'Ч' => 'C',
        'Џ' => 'Dz',
        'Ш' => 'S',
    ],
    // Serbian - Cyrillic
    'sr__cyr' => [
        'а' => 'a',
        'б' => 'b',
        'в' => 'v',
        'г' => 'g',
        'д' => 'd',
        'ђ' => 'dj',
        'е' => 'e',
        'ж' => 'z',
        'з' => 'z',
        'и' => 'i',
        'ј' => 'j',
        'к' => 'k',
        'л' => 'l',
        'љ' => 'lj',
        'м' => 'm',
        'н' => 'n',
        'њ' => 'nj',
        'о' => 'o',
        'п' => 'p',
        'р' => 'r',
        'с' => 's',
        'т' => 't',
        'ћ' => 'c',
        'у' => 'u',
        'ф' => 'f',
        'х' => 'h',
        'ц' => 'c',
        'ч' => 'c',
        'џ' => 'dz',
        'ш' => 's',
        'А' => 'A',
        'Б' => 'B',
        'В' => 'V',
        'Г' => 'G',
        'Д' => 'D',
        'Ђ' => 'Dj',
        'Е' => 'E',
        'Ж' => 'Z',
        'З' => 'Z',
        'И' => 'I',
        'Ј' => 'j',
        'К' => 'K',
        'Л' => 'L',
        'Љ' => 'Lj',
        'М' => 'M',
        'Н' => 'N',
        'Њ' => 'Nj',
        'О' => 'O',
        'П' => 'P',
        'Р' => 'R',
        'С' => 'S',
        'Т' => 'T',
        'Ћ' => 'C',
        'У' => 'U',
        'Ф' => 'F',
        'Х' => 'H',
        'Ц' => 'C',
        'Ч' => 'C',
        'Џ' => 'Dz',
        'Ш' => 'S',
    ],
    // Serbian - Latin
    'sr__lat' => [
        'đ' => 'dj',
        'ž' => 'z',
        'ć' => 'c',
        'č' => 'c',
        'š' => 's',
        'Đ' => 'Dj',
        'Ž' => 'Z',
        'Ć' => 'C',
        'Č' => 'C',
        'Š' => 'S',
    ],
    // Azerbaijani
    'az' => [
        'ç' => 'c',
        'ə' => 'e',
        'ğ' => 'g',
        'ı' => 'i',
        'ö' => 'o',
        'ş' => 's',
        'ü' => 'u',
        'Ç' => 'C',
        'Ə' => 'E',
        'Ğ' => 'G',
        'İ' => 'I',
        'Ö' => 'O',
        'Ş' => 'S',
        'Ü' => 'U',
    ],
    // Slovak
    'sk' => [
        'á' => 'a',
        'ä' => 'a',
        'č' => 'c',
        'ď' => 'd',
        'é' => 'e',
        'í' => 'i',
        'ľ' => 'l',
        'ĺ' => 'l',
        'ň' => 'n',
        'ó' => 'o',
        'ô' => 'o',
        'ŕ' => 'r',
        'š' => 's',
        'ť' => 't',
        'ú' => 'u',
        'ý' => 'y',
        'ž' => 'z',
        'Á' => 'A',
        'Ä' => 'A',
        'Č' => 'C',
        'Ď' => 'D',
        'É' => 'E',
        'Í' => 'I',
        'Ľ' => 'L',
        'Ĺ' => 'L',
        'Ň' => 'N',
        'Ó' => 'O',
        'Ô' => 'O',
        'Ŕ' => 'R',
        'Š' => 'S',
        'Ť' => 'T',
        'Ú' => 'U',
        'Ý' => 'Y',
        'Ž' => 'Z',
    ],
    // French
    'fr' => [
        'Æ' => 'AE',
        'æ' => 'ae',
        'Œ' => 'OE',
        'œ' => 'oe',
        'â' => 'a',
        'Â' => 'A',
        'à' => 'a',
        'À' => 'A',
        'ä' => 'a',
        'Ä' => 'A',
        'ç' => 'c',
        'Ç' => 'C',
        'é' => 'e',
        'É' => 'E',
        'ê' => 'e',
        'Ê' => 'E',
        'ë' => 'e',
        'Ë' => 'E',
        'è' => 'e',
        'È' => 'E',
        'ï' => 'i',
        'î' => 'i',
        'Ï' => 'I',
        'Î' => 'I',
        'ÿ' => 'y',
        'Ÿ' => 'Y',
        'ô' => 'o',
        'Ô' => 'O',
        'ö' => 'o',
        'Ö' => 'O',
        'û' => 'u',
        'Û' => 'U',
        'ù' => 'u',
        'Ù' => 'U',
        'ü' => 'u',
        'Ü' => 'U',
    ],
    // Austrian (French)
    'fr_at' => [
        'ß' => 'sz',
        'ẞ' => 'SZ',
        'Æ' => 'AE',
        'æ' => 'ae',
        'Œ' => 'OE',
        'œ' => 'oe',
        'â' => 'a',
        'Â' => 'A',
        'à' => 'a',
        'À' => 'A',
        'ä' => 'a',
        'Ä' => 'A',
        'ç' => 'c',
        'Ç' => 'C',
        'é' => 'e',
        'É' => 'E',
        'ê' => 'e',
        'Ê' => 'E',
        'ë' => 'e',
        'Ë' => 'E',
        'è' => 'e',
        'È' => 'E',
        'ï' => 'i',
        'î' => 'i',
        'Ï' => 'I',
        'Î' => 'I',
        'ÿ' => 'y',
        'Ÿ' => 'Y',
        'ô' => 'o',
        'Ô' => 'O',
        'ö' => 'o',
        'Ö' => 'O',
        'û' => 'u',
        'Û' => 'U',
        'ù' => 'u',
        'Ù' => 'U',
        'ü' => 'u',
        'Ü' => 'U',
    ],
    // Switzerland (French)
    'fr_ch' => [
        'ß' => 'ss',
        'ẞ' => 'SS',
        'Æ' => 'AE',
        'æ' => 'ae',
        'Œ' => 'OE',
        'œ' => 'oe',
        'â' => 'a',
        'Â' => 'A',
        'à' => 'a',
        'À' => 'A',
        'ä' => 'a',
        'Ä' => 'A',
        'ç' => 'c',
        'Ç' => 'C',
        'é' => 'e',
        'É' => 'E',
        'ê' => 'e',
        'Ê' => 'E',
        'ë' => 'e',
        'Ë' => 'E',
        'è' => 'e',
        'È' => 'E',
        'ï' => 'i',
        'î' => 'i',
        'Ï' => 'I',
        'Î' => 'I',
        'ÿ' => 'y',
        'Ÿ' => 'Y',
        'ô' => 'o',
        'Ô' => 'O',
        'ö' => 'o',
        'Ö' => 'O',
        'û' => 'u',
        'Û' => 'U',
        'ù' => 'u',
        'Ù' => 'U',
        'ü' => 'u',
        'Ü' => 'U',
    ],
    // German
    'de' => [
        'Ä' => 'Ae',
        'Ö' => 'Oe',
        'Ü' => 'Ue',
        'ä' => 'ae',
        'ö' => 'oe',
        'ü' => 'ue',
        'ß' => 'ss',
        'ẞ' => 'SS',
    ],
    // Austrian (German)
    'de_at' => [
        'Ä' => 'Ae',
        'Ö' => 'Oe',
        'Ü' => 'Ue',
        'ä' => 'ae',
        'ö' => 'oe',
        'ü' => 'ue',
        'ß' => 'sz',
        'ẞ' => 'SZ',
    ],
    // Switzerland (German)
    'de_ch' => [
        'Ä' => 'Ae',
        'Ö' => 'Oe',
        'Ü' => 'Ue',
        'ä' => 'ae',
        'ö' => 'oe',
        'ü' => 'ue',
        'ß' => 'ss',
        'ẞ' => 'SS',
    ],
    // Bengali (Bangla)
    'bn' => [
        'ভ্ল'   => 'vl',
        'পশ'    => 'psh',
        'ব্ধ'   => 'bdh',
        'ব্জ'   => 'bj',
        'ব্দ'   => 'bd',
        'ব্ব'   => 'bb',
        'ব্ল'   => 'bl',
        'ভ'     => 'v',
        'ব'     => 'b',
        'চ্ঞ'   => 'cNG',
        'চ্ছ'   => 'cch',
        'চ্চ'   => 'cc',
        'ছ'     => 'ch',
        'চ'     => 'c',
        'ধ্ন'   => 'dhn',
        'ধ্ম'   => 'dhm',
        'দ্ঘ'   => 'dgh',
        'দ্ধ'   => 'ddh',
        'দ্ভ'   => 'dv',
        'দ্ম'   => 'dm',
        'ড্ড'   => 'DD',
        'ঢ'     => 'Dh',
        'ধ'     => 'dh',
        'দ্গ'   => 'dg',
        'দ্দ'   => 'dd',
        'ড'     => 'D',
        'দ'     => 'd',
        '।'     => '.',
        'ঘ্ন'   => 'Ghn',
        'গ্ধ'   => 'Gdh',
        'গ্ণ'   => 'GN',
        'গ্ন'   => 'Gn',
        'গ্ম'   => 'Gm',
        'গ্ল'   => 'Gl',
        'জ্ঞ'   => 'jNG',
        'ঘ'     => 'Gh',
        'গ'     => 'g',
        'হ্ণ'   => 'hN',
        'হ্ন'   => 'hn',
        'হ্ম'   => 'hm',
        'হ্ল'   => 'hl',
        'হ'     => 'h',
        'জ্ঝ'   => 'jjh',
        'ঝ'     => 'jh',
        'জ্জ'   => 'jj',
        'জ'     => 'j',
        'ক্ষ্ণ' => 'kxN',
        'ক্ষ্ম' => 'kxm',
        'ক্ষ'   => 'ksh',
        'কশ'    => 'ksh',
        'ক্ক'   => 'kk',
        'ক্ট'   => 'kT',
        'ক্ত'   => 'kt',
        'ক্ল'   => 'kl',
        'ক্স'   => 'ks',
        'খ'     => 'kh',
        'ক'     => 'k',
        'ল্ভ'   => 'lv',
        'ল্ধ'   => 'ldh',
        'লখ'    => 'lkh',
        'লঘ'    => 'lgh',
        'লফ'    => 'lph',
        'ল্ক'   => 'lk',
        'ল্গ'   => 'lg',
        'ল্ট'   => 'lT',
        'ল্ড'   => 'lD',
        'ল্প'   => 'lp',
        'ল্ম'   => 'lm',
        'ল্ল'   => 'll',
        'ল্ব'   => 'lb',
        'ল'     => 'l',
        'ম্থ'   => 'mth',
        'ম্ফ'   => 'mf',
        'ম্ভ'   => 'mv',
        'মপ্ল'  => 'mpl',
        'ম্ন'   => 'mn',
        'ম্প'   => 'mp',
        'ম্ম'   => 'mm',
        'ম্ল'   => 'ml',
        'ম্ব'   => 'mb',
        'ম'     => 'm',
        '০'     => '0',
        '১'     => '1',
        '২'     => '2',
        '৩'     => '3',
        '৪'     => '4',
        '৫'     => '5',
        '৬'     => '6',
        '৭'     => '7',
        '৮'     => '8',
        '৯'     => '9',
        'ঙ্ক্ষ' => 'Ngkx',
        'ঞ্ছ'   => 'nch',
        'ঙ্ঘ'   => 'ngh',
        'ঙ্খ'   => 'nkh',
        'ঞ্ঝ'   => 'njh',
        'ঙ্গৌ'  => 'ngOU',
        'ঙ্গৈ'  => 'ngOI',
        'ঞ্চ'   => 'nc',
        'ঙ্ক'   => 'nk',
        'ঙ্ষ'   => 'Ngx',
        'ঙ্গ'   => 'ngo',
        'ঙ্ম'   => 'Ngm',
        'ঞ্জ'   => 'nj',
        'ন্ধ'   => 'ndh',
        'ন্ঠ'   => 'nTh',
        'ণ্ঠ'   => 'NTh',
        'ন্থ'   => 'nth',
        'ঙ্গা'  => 'nga',
        'ঙ্গি'  => 'ngi',
        'ঙ্গী'  => 'ngI',
        'ঙ্গু'  => 'ngu',
        'ঙ্গূ'  => 'ngU',
        'ঙ্গে'  => 'nge',
        'ঙ্গো'  => 'ngO',
        'ণ্ঢ'   => 'NDh',
        'নশ'    => 'nsh',
        'ঙর'    => 'Ngr',
        'ঞর'    => 'NGr',
        'ংর'    => 'ngr',
        'ঙ'     => 'Ng',
        'ঞ'     => 'NG',
        'ং'     => 'ng',
        'ন্ন'   => 'nn',
        'ণ্ণ'   => 'NN',
        'ণ্ন'   => 'Nn',
        'ন্ম'   => 'nm',
        'ণ্ম'   => 'Nm',
        'ন্দ'   => 'nd',
        'ন্ট'   => 'nT',
        'ণ্ট'   => 'NT',
        'ন্ড'   => 'nD',
        'ণ্ড'   => 'ND',
        'ন্ত'   => 'nt',
        'ন্স'   => 'ns',
        'ন'     => 'n',
        'ণ'     => 'N',
        'ৈ'     => 'OI',
        'ৌ'     => 'OU',
        'ো'     => 'O',
        'ঐ'     => 'OI',
        'ঔ'     => 'OU',
        'অ'     => 'o',
        'ও'     => 'oo',
        'ফ্ল'   => 'fl',
        'প্ট'   => 'pT',
        'প্ত'   => 'pt',
        'প্ন'   => 'pn',
        'প্প'   => 'pp',
        'প্ল'   => 'pl',
        'প্স'   => 'ps',
        'ফ'     => 'f',
        'প'     => 'p',
        'ৃ'     => 'rri',
        'ঋ'     => 'rri',
        'রর‍্য' => 'rry',
        '্র্য'  => 'ry',
        '্রর'   => 'rr',
        'ড়্গ'   => 'Rg',
        'ঢ়'     => 'Rh',
        'ড়'     => 'R',
        'র'     => 'r',
        '্র'    => 'r',
        'শ্ছ'   => 'Sch',
        'ষ্ঠ'   => 'ShTh',
        'ষ্ফ'   => 'Shf',
        'স্ক্ল' => 'skl',
        'স্খ'   => 'skh',
        'স্থ'   => 'sth',
        'স্ফ'   => 'sf',
        'শ্চ'   => 'Sc',
        'শ্ত'   => 'St',
        'শ্ন'   => 'Sn',
        'শ্ম'   => 'Sm',
        'শ্ল'   => 'Sl',
        'ষ্ক'   => 'Shk',
        'ষ্ট'   => 'ShT',
        'ষ্ণ'   => 'ShN',
        'ষ্প'   => 'Shp',
        'ষ্ম'   => 'Shm',
        'স্প্ল' => 'spl',
        'স্ক'   => 'sk',
        'স্ট'   => 'sT',
        'স্ত'   => 'st',
        'স্ন'   => 'sn',
        'স্প'   => 'sp',
        'স্ম'   => 'sm',
        'স্ল'   => 'sl',
        'শ'     => 'S',
        'ষ'     => 'Sh',
        'স'     => 's',
        'ু'     => 'u',
        'উ'     => 'u',
        'অ্য'   => 'oZ',
        'ত্থ'   => 'tth',
        'ৎ'     => 'tt',
        'ট্ট'   => 'TT',
        'ট্ম'   => 'Tm',
        'ঠ'     => 'Th',
        'ত্ন'   => 'tn',
        'ত্ম'   => 'tm',
        'থ'     => 'th',
        'ত্ত'   => 'tt',
        'ট'     => 'T',
        'ত'     => 't',
        'অ্যা'  => 'AZ',
        'া'     => 'a',
        'আ'     => 'a',
        'য়া'    => 'ya',
        'য়'     => 'y',
        'ি'     => 'i',
        'ই'     => 'i',
        'ী'     => 'ee',
        'ঈ'     => 'ee',
        'ূ'     => 'uu',
        'ঊ'     => 'uu',
        'ে'     => 'e',
        'এ'     => 'e',
        'য'     => 'z',
        '্য'    => 'Z',
        'ইয়'    => 'y',
        'ওয়'    => 'w',
        '্ব'    => 'w',
        'এক্স'  => 'x',
        'ঃ'     => ':',
        'ঁ'     => 'nn',
        '্‌'    => '',
    ],
    // English
    'en' => [
    ],
    // Latin (+ Cyrillic ?) chars
    //
    // -> Mix of languages, but we need to keep this here, so that different languages can handle there own behavior.
    'latin' => [
        '˚'   => '0',
        '¹'   => '1',
        '²'   => '2',
        '³'   => '3',
        '⁴'   => '4',
        '⁵'   => '5',
        '⁶'   => '6',
        '⁷'   => '7',
        '⁸'   => '8',
        '⁹'   => '9',
        '₀'   => '0',
        '₁'   => '1',
        '₂'   => '2',
        '₃'   => '3',
        '₄'   => '4',
        '₅'   => '5',
        '₆'   => '6',
        '₇'   => '7',
        '₈'   => '8',
        '₉'   => '9',
        '௦'   => '0',
        '௧'   => '1',
        '௨'   => '2',
        '௩'   => '3',
        '௪'   => '4',
        '௫'   => '5',
        '௬'   => '6',
        '௭'   => '7',
        '௮'   => '8',
        '௯'   => '9',
        '௰'   => '10',
        '௱'   => '100',
        '௲'   => '1000',
        'Ꜳ'   => 'AA',
        'ꜳ'   => 'aa',
        'Æ'   => 'AE',
        'æ'   => 'ae',
        'Ǽ'   => 'AE',
        'ǽ'   => 'ae',
        'Ꜵ'   => 'AO',
        'ꜵ'   => 'ao',
        'Ꜷ'   => 'AU',
        'ꜷ'   => 'au',
        'Ꜹ'   => 'AV',
        'ꜹ'   => 'av',
        'Ꜻ'   => 'av',
        'ꜻ'   => 'av',
        'Ꜽ'   => 'AY',
        'ꜽ'   => 'ay',
        'ȸ'   => 'db',
        'ʣ'   => 'dz',
        'ʥ'   => 'dz',
        'ʤ'   => 'dezh',
        '🙰'   => 'et',
        'ﬀ'   => 'ff',
        'ﬃ'   => 'ffi',
        'ﬄ'   => 'ffl',
        'ﬁ'   => 'fi',
        'ﬂ'   => 'fl',
        'ʩ'   => 'feng',
        'Ĳ'   => 'IJ',
        'ĳ'   => 'ij',
        'ʪ'   => 'ls',
        'ʫ'   => 'lz',
        'ɮ'   => 'lezh',
        'ȹ'   => 'qp',
        'ʨ'   => 'tc',
        'ʦ'   => 'ts',
        'ʧ'   => 'tesh',
        'Œ'   => 'OE',
        'œ'   => 'oe',
        'Ꝏ'   => 'OO',
        'ꝏ'   => 'oo',
        'ẞ'   => 'SS',
        'ß'   => 'ss',
        'ﬆ'   => 'st',
        'ﬅ'   => 'st',
        'Ꜩ'   => 'TZ',
        'ꜩ'   => 'tz',
        'ᵫ'   => 'ue',
        'Aι'  => 'Ai',
        'αι'  => 'ai',
        'Ει'  => 'Ei',
        'ει'  => 'ei',
        'Οι'  => 'Oi',
        'οι'  => 'oi',
        'Ου'  => 'Oy',
        'ου'  => 'oy',
        'Υι'  => 'Yi',
        'υι'  => 'yi',
        'ἀ'   => 'a',
        'ἁ'   => 'a',
        'ἂ'   => 'a',
        'ἃ'   => 'a',
        'ἄ'   => 'a',
        'ἅ'   => 'a',
        'ἆ'   => 'a',
        'ἇ'   => 'a',
        'Ἀ'   => 'A',
        'Ἁ'   => 'A',
        'Ἂ'   => 'A',
        'Ἃ'   => 'A',
        'Ἄ'   => 'A',
        'Ἅ'   => 'A',
        'Ἆ'   => 'A',
        'Ἇ'   => 'A',
        'ᾰ'   => 'a',
        'ᾱ'   => 'a',
        'ᾲ'   => 'a',
        'ᾳ'   => 'a',
        'ᾴ'   => 'a',
        'ᾶ'   => 'a',
        'ᾷ'   => 'a',
        'Ᾰ'   => 'A',
        'Ᾱ'   => 'A',
        'Ὰ'   => 'A',
        'Ά'   => 'A',
        'ᾼ'   => 'A',
        'Ä'   => 'A',
        'ä'   => 'a',
        'À'   => 'A',
        'à'   => 'a',
        'Á'   => 'A',
        'á'   => 'a',
        'Â'   => 'A',
        'â'   => 'a',
        'Ã'   => 'A',
        'ã'   => 'a',
        'A̧'  => 'A',
        'a̧'  => 'a',
        'Ą'   => 'A',
        'ą'   => 'a',
        'Ⱥ'   => 'A',
        'ⱥ'   => 'a',
        'Å'   => 'A',
        'å'   => 'a',
        'Ǻ'   => 'A',
        'ǻ'   => 'a',
        'Ă'   => 'A',
        'ă'   => 'a',
        'Ǎ'   => 'A',
        'ǎ'   => 'a',
        'Ȧ'   => 'A',
        'ȧ'   => 'a',
        'Ạ'   => 'A',
        'ạ'   => 'a',
        'Ā'   => 'A',
        'ā'   => 'a',
        'ª'   => 'a',
        'Ɓ'   => 'B',
        'Ѣ'   => 'E',
        'ѣ'   => 'e',
        'Ç'   => 'C',
        'ç'   => 'c',
        'Ĉ'   => 'C',
        'ĉ'   => 'c',
        'C̈'  => 'C',
        'c̈'  => 'c',
        'C̨'  => 'C',
        'c̨'  => 'c',
        'Ȼ'   => 'C',
        'ȼ'   => 'c',
        'Č'   => 'C',
        'č'   => 'c',
        'Ć'   => 'C',
        'ć'   => 'c',
        'C̀'  => 'C',
        'c̀'  => 'c',
        'Ċ'   => 'C',
        'ċ'   => 'c',
        'C̣'  => 'C',
        'c̣'  => 'c',
        'C̄'  => 'C',
        'c̄'  => 'c',
        'C̃'  => 'C',
        'c̃'  => 'c',
        'Ð'   => 'D',
        'Đ'   => 'D',
        'ð'   => 'd',
        'đ'   => 'd',
        'È'   => 'E',
        'É'   => 'E',
        'Ê'   => 'E',
        'Ë'   => 'E',
        'Ĕ'   => 'E',
        'Ė'   => 'E',
        'Ȩ'   => 'E',
        'ȩ'   => 'e',
        'Ę'   => 'E',
        'ę'   => 'e',
        'Ɇ'   => 'E',
        'ɇ'   => 'e',
        'Ě'   => 'E',
        'ě'   => 'e',
        'Ẹ'   => 'E',
        'ẹ'   => 'e',
        'Ē'   => 'E',
        'ē'   => 'e',
        'Ẽ'   => 'E',
        'ẽ'   => 'e',
        'è'   => 'e',
        'é'   => 'e',
        'ê'   => 'e',
        'ë'   => 'e',
        'ĕ'   => 'e',
        'ė'   => 'e',
        'ƒ'   => 'f',
        'Ѳ'   => 'F',
        'ѳ'   => 'f',
        'Ĝ'   => 'G',
        'Ġ'   => 'G',
        'ĝ'   => 'g',
        'ġ'   => 'g',
        'Ĥ'   => 'H',
        'Ħ'   => 'H',
        'ĥ'   => 'h',
        'ħ'   => 'h',
        'Ì'   => 'I',
        'Í'   => 'I',
        'Î'   => 'I',
        'Ï'   => 'I',
        'Ĩ'   => 'I',
        'Ĭ'   => 'I',
        'Ǐ'   => 'I',
        'Į'   => 'I',
        'ì'   => 'i',
        'í'   => 'i',
        'î'   => 'i',
        'ï'   => 'i',
        'ĩ'   => 'i',
        'ĭ'   => 'i',
        'ǐ'   => 'i',
        'į'   => 'i',
        'І'   => 'I',
        'і'   => 'i',
        'I̧'  => 'I',
        'i̧'  => 'i',
        'Ɨ'   => 'I',
        'ɨ'   => 'i',
        'İ'   => 'I',
        'i'   => 'i',
        'Ị'   => 'I',
        'ị'   => 'i',
        'Ī'   => 'I',
        'ī'   => 'i',
        'Ĵ'   => 'J',
        'ĵ'   => 'j',
        'J́́' => 'J',
        'j́'  => 'j',
        'J̀̀' => 'J',
        'j̀'  => 'j',
        'J̈'  => 'J',
        'j̈'  => 'j',
        'J̧'  => 'J',
        'j̧'  => 'j',
        'J̨'  => 'J',
        'j̨'  => 'j',
        'Ɉ'   => 'J',
        'ɉ'   => 'j',
        'J̌'  => 'J',
        'ǰ'   => 'j',
        'J̇'  => 'J',
        'j'   => 'j',
        'J̣'  => 'J',
        'j̣'  => 'j',
        'J̄'  => 'J',
        'j̄'  => 'j',
        'J̃'  => 'J',
        'j̃'  => 'j',
        'Й' => 'i',
        'й' => 'i',
        'ĸ'   => 'k',
        'Ĺ'   => 'L',
        'Ľ'   => 'L',
        'Ŀ'   => 'L',
        'ĺ'   => 'l',
        'ľ'   => 'l',
        'ŀ'   => 'l',
        'L̀'  => 'L',
        'l̀'  => 'l',
        'L̂'  => 'L',
        'l̂'  => 'l',
        'L̈'  => 'L',
        'l̈'  => 'l',
        'Ļ'   => 'L',
        'ļ'   => 'l',
        'L̨'  => 'L',
        'l̨'  => 'l',
        'Ł'   => 'L',
        'ł'   => 'l',
        'Ƚ'   => 'L',
        'ƚ'   => 'l',
        'L̇'  => 'L',
        'l̇'  => 'l',
        'Ḷ'   => 'L',
        'ḷ'   => 'l',
        'L̄'  => 'L',
        'l̄'  => 'l',
        'L̃'  => 'L',
        'l̃'  => 'l',
        'Ñ'   => 'N',
        'ñ'   => 'n',
        'Ŋ'   => 'N',
        'ŋ'   => 'n',
        'ŉ'   => 'n',
        'Ń'   => 'N',
        'ń'   => 'n',
        'Ǹ'   => 'N',
        'ǹ'   => 'n',
        'N̂'  => 'N',
        'n̂'  => 'n',
        'N̈'  => 'N',
        'n̈'  => 'n',
        'Ņ'   => 'N',
        'ņ'   => 'n',
        'N̨'  => 'N',
        'n̨'  => 'n',
        'Ꞥ'   => 'N',
        'ꞥ'   => 'n',
        'Ň'   => 'N',
        'ň'   => 'n',
        'Ṅ'   => 'N',
        'ṅ'   => 'n',
        'Ṇ'   => 'N',
        'ṇ'   => 'n',
        'N̄'  => 'N',
        'n̄'  => 'n',
        'Ö'   => 'O',
        'Ò'   => 'O',
        'Ó'   => 'O',
        'Ô'   => 'O',
        'Õ'   => 'O',
        'Ō'   => 'O',
        'Ŏ'   => 'O',
        'Ǒ'   => 'O',
        'Ő'   => 'O',
        'Ơ'   => 'O',
        'Ø'   => 'O',
        'Ǿ'   => 'O',
        'ö'   => 'o',
        'ò'   => 'o',
        'ó'   => 'o',
        'ô'   => 'o',
        'õ'   => 'o',
        'ō'   => 'o',
        'ŏ'   => 'o',
        'ǒ'   => 'o',
        'ő'   => 'o',
        'ơ'   => 'o',
        'ø'   => 'o',
        'ǿ'   => 'o',
        'º'   => 'o',
        'O̧'  => 'O',
        'o̧'  => 'o',
        'Ǫ'   => 'O',
        'ǫ'   => 'o',
        'Ɵ'   => 'O',
        'ɵ'   => 'o',
        'Ȯ'   => 'O',
        'ȯ'   => 'o',
        'Ọ'   => 'O',
        'ọ'   => 'o',
        'Ŕ'   => 'R',
        'Ŗ'   => 'R',
        'ŕ'   => 'r',
        'ŗ'   => 'r',
        'Ŝ'   => 'S',
        'Ș'   => 'S',
        'ș'   => 's',
        'Ś'   => 'S',
        'ś'   => 's',
        'S̀'  => 'S',
        's̀'  => 's',
        'Ŝ̀'  => 'S',
        'ŝ'   => 's',
        'S̈'  => 'S',
        's̈'  => 's',
        'Ş'   => 'S',
        'ş'   => 's',
        'S̨'  => 'S',
        's̨'  => 's',
        'Ꞩ'   => 'S',
        'ꞩ'   => 's',
        'Š'   => 'S',
        'š'   => 's',
        'Ṡ'   => 'S',
        'ṡ'   => 's',
        'Ṣ'   => 'S',
        'ṣ'   => 's',
        'S̄'  => 'S',
        's̄'  => 's',
        'S̃'  => 'S',
        's̃'  => 's',
        'ſ'   => 's',
        'Ţ'   => 'T',
        'Ț'   => 'T',
        'Ŧ'   => 'T',
        'Þ'   => 'TH',
        'ţ'   => 't',
        'ț'   => 't',
        'ŧ'   => 't',
        'þ'   => 'th',
        'T́'  => 'T',
        't́'  => 't',
        'T̀'  => 'T',
        't̀'  => 't',
        'T̂'  => 'T',
        't̂'  => 't',
        'T̈'  => 'T',
        'ẗ'   => 't',
        'T̨'  => 'T',
        't̨'  => 't',
        'Ⱦ'   => 'T',
        'ⱦ'   => 't',
        'Ť'   => 'T',
        'ť'   => 't',
        'Ṫ'   => 'T',
        'ṫ'   => 't',
        'Ṭ'   => 'T',
        'ṭ'   => 't',
        'T̄'  => 'T',
        't̄'  => 't',
        'T̃'  => 'T',
        't̃'  => 't',
        'Ü'   => 'U',
        'Ù'   => 'U',
        'Ú'   => 'U',
        'Û'   => 'U',
        'Ũ'   => 'U',
        'Ŭ'   => 'U',
        'Ű'   => 'U',
        'Ų'   => 'U',
        'Ư'   => 'U',
        'Ǔ'   => 'U',
        'Ǖ'   => 'U',
        'Ǘ'   => 'U',
        'Ǚ'   => 'U',
        'Ǜ'   => 'U',
        'ü'   => 'u',
        'ù'   => 'u',
        'ú'   => 'u',
        'û'   => 'u',
        'ũ'   => 'u',
        'ŭ'   => 'u',
        'ű'   => 'u',
        'ų'   => 'u',
        'ư'   => 'u',
        'ǔ'   => 'u',
        'ǖ'   => 'u',
        'ǘ'   => 'u',
        'ǚ'   => 'u',
        'ǜ'   => 'u',
        'U̧'  => 'U',
        'u̧'  => 'u',
        'Ʉ'   => 'U',
        'ʉ'   => 'u',
        'U̇'  => 'U',
        'u̇'  => 'u',
        'Ụ'   => 'U',
        'ụ'   => 'u',
        'Ū'   => 'U',
        'ū'   => 'u',
        'Ʊ'   => 'U',
        'ʊ'   => 'u',
        'Ŵ'   => 'W',
        'ŵ'   => 'w',
        'Ẁ'   => 'W',
        'ẁ'   => 'w',
        'Ẃ'   => 'W',
        'ẃ'   => 'w',
        'Ẅ'   => 'W',
        'ẅ'   => 'w',
        'Ѵ'   => 'I',
        'ѵ'   => 'i',
        'Ꙗ'   => 'Ja',
        'ꙗ'   => 'ja',
        'Є'   => 'Je',
        'є'   => 'je',
        'Ѥ'   => 'Je',
        'ѥ'   => 'je',
        'Ѕ'   => 'Dz',
        'ѕ'   => 'dz',
        'Ꙋ'   => 'U',
        'ꙋ'   => 'u',
        'Ѡ'   => 'O',
        'ѡ'   => 'o',
        'Ѿ'   => 'Ot',
        'ѿ'   => 'ot',
        'Ѫ'   => 'U',
        'ѫ'   => 'u',
        'Ѧ'   => 'Ja',
        'ѧ'   => 'ja',
        'Ѭ'   => 'Ju',
        'ѭ'   => 'ju',
        'Ѩ'   => 'Ja',
        'ѩ'   => 'Ja',
        'Ѯ'   => 'Ks',
        'ѯ'   => 'ks',
        'Ѱ'   => 'Ps',
        'ѱ'   => 'ps',
        'Х'   => 'X',
        'х'   => 'x',
        'Ý'   => 'Y',
        'Ÿ'   => 'Y',
        'Ŷ'   => 'Y',
        'ý'   => 'y',
        'ÿ'   => 'y',
        'ŷ'   => 'y',
        'Ỳ'   => 'Y',
        'ỳ'   => 'y',
        'Y̧'  => 'Y',
        'y̧'  => 'y',
        'Y̨'  => 'Y',
        'y̨'  => 'y',
        'Ɏ'   => 'Y',
        'ɏ'   => 'y',
        'Y̌'  => 'Y',
        'y̌'  => 'y',
        'Ẏ'   => 'Y',
        'ẏ'   => 'y',
        'Ỵ'   => 'Y',
        'ỵ'   => 'y',
        'Ȳ'   => 'Y',
        'ȳ'   => 'y',
        'Ỹ'   => 'Y',
        'ỹ'   => 'y',
        'Щ' => 'Shh',
        'щ' => 'shh',
        'Ź'   => 'Z',
        'ź'   => 'z',
        'Z̀'  => 'Z',
        'z̀'  => 'z',
        'Ẑ'   => 'Z',
        'ẑ'   => 'z',
        'Z̈'  => 'Z',
        'z̈'  => 'z',
        'Z̧'  => 'Z',
        'z̧'  => 'z',
        'Z̨'  => 'Z',
        'z̨'  => 'z',
        'Ƶ'   => 'Z',
        'ƶ'   => 'z',
        'Ž'   => 'Z',
        'ž'   => 'z',
        'Ż'   => 'Z',
        'ż'   => 'z',
        'Ẓ'   => 'Z',
        'ẓ'   => 'z',
        'Z̄'  => 'Z',
        'z̄'  => 'z',
        'Z̃'  => 'Z',
        'z̃'  => 'z',
    ],
    // whitespace chars
    ' ' => [
        "\xc2\xa0"     => ' ', // 'NO-BREAK SPACE'
        "\xe1\x9a\x80" => ' ', // 'OGHAM SPACE MARK'
        "\xe2\x80\x80" => ' ', // 'EN QUAD'
        "\xe2\x80\x81" => ' ', // 'EM QUAD'
        "\xe2\x80\x82" => ' ', // 'EN SPACE'
        "\xe2\x80\x83" => ' ', // 'EM SPACE'
        "\xe2\x80\x84" => ' ', // 'THREE-PER-EM SPACE'
        "\xe2\x80\x85" => ' ', // 'FOUR-PER-EM SPACE'
        "\xe2\x80\x86" => ' ', // 'SIX-PER-EM SPACE'
        "\xe2\x80\x87" => ' ', // 'FIGURE SPACE'
        "\xe2\x80\x88" => ' ', // 'PUNCTUATION SPACE'
        "\xe2\x80\x89" => ' ', // 'THIN SPACE'
        "\xe2\x80\x8a" => ' ', // 'HAIR SPACE'
        "\xe2\x80\xa8" => ' ', // 'LINE SEPARATOR'
        "\xe2\x80\xa9" => ' ', // 'PARAGRAPH SEPARATOR'
        "\xe2\x80\x8b" => ' ', // 'ZERO WIDTH SPACE'
        "\xe2\x80\xaf" => ' ', // 'NARROW NO-BREAK SPACE'
        "\xe2\x81\x9f" => ' ', // 'MEDIUM MATHEMATICAL SPACE'
        "\xe3\x80\x80" => ' ', // 'IDEOGRAPHIC SPACE'
        "\xef\xbe\xa0" => ' ', // 'HALFWIDTH HANGUL FILLER'
    ],
    // commonly used in Word documents
    'msword' => [
        "\xc2\xab"     => '<<', // « (U+00AB) in UTF-8
        "\xc2\xbb"     => '>>', // » (U+00BB) in UTF-8
        "\xe2\x80\x98" => "'", // ‘ (U+2018) in UTF-8
        "\xe2\x80\x99" => "'", // ’ (U+2019) in UTF-8
        "\xe2\x80\x9a" => "'", // ‚ (U+201A) in UTF-8
        "\xe2\x80\x9b" => "'", // ‛ (U+201B) in UTF-8
        "\xe2\x80\x9c" => '"', // “ (U+201C) in UTF-8
        "\xe2\x80\x9d" => '"', // ” (U+201D) in UTF-8
        "\xe2\x80\x9e" => '"', // „ (U+201E) in UTF-8
        "\xe2\x80\x9f" => '"', // ‟ (U+201F) in UTF-8
        "\xe2\x80\xb9" => "'", // ‹ (U+2039) in UTF-8
        "\xe2\x80\xba" => "'", // › (U+203A) in UTF-8
        "\xe2\x80\x93" => '-', // – (U+2013) in UTF-8
        "\xe2\x80\x94" => '-', // — (U+2014) in UTF-8
        "\xe2\x80\xa6" => '...', // … (U+2026) in UTF-8
    ],
    // Currency
    //
    // url => https://en.wikipedia.org/wiki/Currency_symbol
    'currency_short' => [
        '€'  => 'EUR',
        '$'  => '$',
        '₢'  => 'Cr',
        '₣'  => 'Fr.',
        '£'  => 'PS',
        '₤'  => 'L.',
        'ℳ'  => 'M',
        '₥'  => 'mil',
        '₦'  => 'N',
        '₧'  => 'Pts',
        '₨'  => 'Rs',
        'රු' => 'LKR',
        'ரூ' => 'LKR',
        '௹'  => 'Rs',
        'रू' => 'NPR',
        '₹'  => 'Rs',
        '૱'  => 'Rs',
        '₩'  => 'W',
        '₪'  => 'NS',
        '₸'  => 'KZT',
        '₫'  => 'D',
        '֏'  => 'AMD',
        '₭'  => 'K',
        '₺'  => 'TL',
        '₼'  => 'AZN',
        '₮'  => 'T',
        '₯'  => 'Dr',
        '₲'  => 'PYG',
        '₾'  => 'GEL',
        '₳'  => 'ARA',
        '₴'  => 'UAH',
        '₽'  => 'RUB',
        '₵'  => 'GHS',
        '₡'  => 'CL',
        '¢'  => 'c',
        '¥'  => 'YEN',
        '円'  => 'JPY',
        '৳'  => 'BDT',
        '元'  => 'CNY',
        '﷼'  => 'SAR',
        '៛'  => 'KR',
        '₠'  => 'ECU',
        '¤'  => '$?',
        '฿'  => 'THB',
        '؋'  => 'AFN',
    ],
];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '::=', '==', '===', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'e', 'e', 'e', 'e', 'e', 'e', '[?]', '[?]', 'E', 'E', 'E', 'E', 'E', 'E', '[?]', '[?]', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'o', 'o', 'o', 'o', 'o', 'o', '[?]', '[?]', 'O', 'O', 'O', 'O', 'O', 'O', '[?]', '[?]', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', '[?]', 'U', '[?]', 'U', '[?]', 'U', '[?]', 'U', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'a', 'a', 'e', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'u', 'u', 'o', 'o', '[?]', '[?]', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'a', 'a', 'a', 'a', 'a', '[?]', 'a', 'a', 'A', 'A', 'A', 'A', 'A', '\'', 'i', '\'', '~', '"~', 'e', 'e', 'e', '[?]', 'e', 'e', 'E', 'E', 'E', 'E', 'E', '\'`', '\'\'', '\'~', 'i', 'i', 'i', 'i', '[?]', '[?]', 'i', 'i', 'I', 'I', 'I', 'I', '[?]', '`\'', '`\'', '`~', 'u', 'u', 'u', 'u', 'R', 'R', 'u', 'u', 'U', 'U', 'U', 'U', 'R', '"`', '"\'', '`', '[?]', '[?]', 'o', 'o', 'o', '[?]', 'o', 'o', 'O', 'O', 'O', 'O', 'O', '\'', '`', '[?]'];
<?php return [' a/c ', ' a/s ', 'C', '', '', ' c/o ', ' c/u ', '', '', '', 'g', 'H', 'H', 'H', 'h', '', 'I', 'I', 'L', 'l', '', 'N', 'No. ', '', '', 'P', 'Q', 'R', 'R', 'R', '', '', '(sm)', 'TEL', '(tm)', '', 'Z', '', '', '', 'Z', '', 'K', 'A', 'B', 'C', 'e', 'e', 'E', 'F', 'F', 'M', 'o', '', '', '', '', 'i', '', 'FAX', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', 'D', 'd', 'e', 'i', 'j', '[?]', '[?]', '[?]', '[?]', 'F', '[?]', ' 1/7 ', ' 1/9 ', ' 1/10 ', ' 1/3 ', ' 2/3 ', ' 1/5 ', ' 2/5 ', ' 3/5 ', ' 4/5 ', ' 1/6 ', ' 5/6 ', ' 1/8 ', ' 3/8 ', ' 5/8 ', ' 7/8 ', ' 1/', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'L', 'C', 'D', 'M', 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'x', 'xi', 'xii', 'l', 'c', 'd', 'm', '(D', 'D)', '((|))', ')', '[?]', '[?]', '[?]', '[?]', '[?]', ' 0/3 ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '-', '|', '-', '|', '-', '|', '\\', '/', '\\', '/', '-', '-', '~', '~', '-', '|', '-', '|', '-', '-', '-', '|', '-', '|', '|', '-', '-', '-', '-', '-', '-', '|', '|', '|', '|', '|', '|', '|', '^', 'V', '\\', '=', 'V', '^', '-', '-', '|', '|', '-', '-', '|', '|', '=', '|', '=', '=', '|', '=', '|', '=', '=', '=', '=', '=', '=', '|', '=', '|', '=', '|', '\\', '/', '\\', '/', '=', '=', '~', '~', '|', '|', '-', '|', '-', '|', '-', '-', '-', '|', '-', '|', '|', '|', '|', '|', '|', '|', '-', '\\', '\\', '|', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Yun ', 'Mwun ', 'Nay ', 'Gai ', 'Gai ', 'Bao ', 'Cong ', '[?] ', 'Xiong ', 'Peng ', 'Ju ', 'Tao ', 'Ge ', 'Pu ', 'An ', 'Pao ', 'Fu ', 'Gong ', 'Da ', 'Jiu ', 'Qiong ', 'Bi ', 'Hua ', 'Bei ', 'Nao ', 'Chi ', 'Fang ', 'Jiu ', 'Yi ', 'Za ', 'Jiang ', 'Kang ', 'Jiang ', 'Kuang ', 'Hu ', 'Xia ', 'Qu ', 'Bian ', 'Gui ', 'Qie ', 'Zang ', 'Kuang ', 'Fei ', 'Hu ', 'Tou ', 'Gui ', 'Gui ', 'Hui ', 'Dan ', 'Gui ', 'Lian ', 'Lian ', 'Suan ', 'Du ', 'Jiu ', 'Qu ', 'Xi ', 'Pi ', 'Qu ', 'Yi ', 'Qia ', 'Yan ', 'Bian ', 'Ni ', 'Qu ', 'Shi ', 'Xin ', 'Qian ', 'Nian ', 'Sa ', 'Zu ', 'Sheng ', 'Wu ', 'Hui ', 'Ban ', 'Shi ', 'Xi ', 'Wan ', 'Hua ', 'Xie ', 'Wan ', 'Bei ', 'Zu ', 'Zhuo ', 'Xie ', 'Dan ', 'Mai ', 'Nan ', 'Dan ', 'Ji ', 'Bo ', 'Shuai ', 'Bu ', 'Kuang ', 'Bian ', 'Bu ', 'Zhan ', 'Qia ', 'Lu ', 'You ', 'Lu ', 'Xi ', 'Gua ', 'Wo ', 'Xie ', 'Jie ', 'Jie ', 'Wei ', 'Ang ', 'Qiong ', 'Zhi ', 'Mao ', 'Yin ', 'Wei ', 'Shao ', 'Ji ', 'Que ', 'Luan ', 'Shi ', 'Juan ', 'Xie ', 'Xu ', 'Jin ', 'Que ', 'Wu ', 'Ji ', 'E ', 'Qing ', 'Xi ', '[?] ', 'Han ', 'Zhan ', 'E ', 'Ting ', 'Li ', 'Zhe ', 'Han ', 'Li ', 'Ya ', 'Ya ', 'Yan ', 'She ', 'Zhi ', 'Zha ', 'Pang ', '[?] ', 'He ', 'Ya ', 'Zhi ', 'Ce ', 'Pang ', 'Ti ', 'Li ', 'She ', 'Hou ', 'Ting ', 'Zui ', 'Cuo ', 'Fei ', 'Yuan ', 'Ce ', 'Yuan ', 'Xiang ', 'Yan ', 'Li ', 'Jue ', 'Sha ', 'Dian ', 'Chu ', 'Jiu ', 'Qin ', 'Ao ', 'Gui ', 'Yan ', 'Si ', 'Li ', 'Chang ', 'Lan ', 'Li ', 'Yan ', 'Yan ', 'Yuan ', 'Si ', 'Gong ', 'Lin ', 'Qiu ', 'Qu ', 'Qu ', 'Uk ', 'Lei ', 'Du ', 'Xian ', 'Zhuan ', 'San ', 'Can ', 'Can ', 'Can ', 'Can ', 'Ai ', 'Dai ', 'You ', 'Cha ', 'Ji ', 'You ', 'Shuang ', 'Fan ', 'Shou ', 'Guai ', 'Ba ', 'Fa ', 'Ruo ', 'Shi ', 'Shu ', 'Zhuo ', 'Qu ', 'Shou ', 'Bian ', 'Xu ', 'Jia ', 'Pan ', 'Sou ', 'Gao ', 'Wei ', 'Sou ', 'Die ', 'Rui ', 'Cong ', 'Kou ', 'Gu ', 'Ju ', 'Ling ', 'Gua ', 'Tao ', 'Kou ', 'Zhi ', 'Jiao ', 'Zhao ', 'Ba ', 'Ding ', 'Ke ', 'Tai ', 'Chi ', 'Shi ', 'You ', 'Qiu ', 'Po ', 'Xie ', 'Hao ', 'Si ', 'Tan ', 'Chi ', 'Le ', 'Diao ', 'Ji ', '[?] ', 'Hong '];
<?php return ['s', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'i', 'j', '', '', 'Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta', 'Iota', 'Kappa', 'Lamda', 'Mu', 'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Theta', 'Sigma', 'Tau', 'Upsilon', 'Phi', 'Chi', 'Psi', 'Omega', 'nabla', 'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta', 'eta', 'theta', 'iota', 'kappa', 'lamda', 'mu', 'nu', 'xi', 'omicron', 'pi', 'rho', 'sigma', 'sigma', 'tai', 'upsilon', 'phi', 'chi', 'psi', 'omega', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['bbess', 'bbeng', 'bbej', 'bbec', 'bbek', 'bbet', 'bbep', 'bbeh', 'bbyeo', 'bbyeog', 'bbyeogg', 'bbyeogs', 'bbyeon', 'bbyeonj', 'bbyeonh', 'bbyeod', 'bbyeol', 'bbyeolg', 'bbyeolm', 'bbyeolb', 'bbyeols', 'bbyeolt', 'bbyeolp', 'bbyeolh', 'bbyeom', 'bbyeob', 'bbyeobs', 'bbyeos', 'bbyeoss', 'bbyeong', 'bbyeoj', 'bbyeoc', 'bbyeok', 'bbyeot', 'bbyeop', 'bbyeoh', 'bbye', 'bbyeg', 'bbyegg', 'bbyegs', 'bbyen', 'bbyenj', 'bbyenh', 'bbyed', 'bbyel', 'bbyelg', 'bbyelm', 'bbyelb', 'bbyels', 'bbyelt', 'bbyelp', 'bbyelh', 'bbyem', 'bbyeb', 'bbyebs', 'bbyes', 'bbyess', 'bbyeng', 'bbyej', 'bbyec', 'bbyek', 'bbyet', 'bbyep', 'bbyeh', 'bbo', 'bbog', 'bbogg', 'bbogs', 'bbon', 'bbonj', 'bbonh', 'bbod', 'bbol', 'bbolg', 'bbolm', 'bbolb', 'bbols', 'bbolt', 'bbolp', 'bbolh', 'bbom', 'bbob', 'bbobs', 'bbos', 'bboss', 'bbong', 'bboj', 'bboc', 'bbok', 'bbot', 'bbop', 'bboh', 'bbwa', 'bbwag', 'bbwagg', 'bbwags', 'bbwan', 'bbwanj', 'bbwanh', 'bbwad', 'bbwal', 'bbwalg', 'bbwalm', 'bbwalb', 'bbwals', 'bbwalt', 'bbwalp', 'bbwalh', 'bbwam', 'bbwab', 'bbwabs', 'bbwas', 'bbwass', 'bbwang', 'bbwaj', 'bbwac', 'bbwak', 'bbwat', 'bbwap', 'bbwah', 'bbwae', 'bbwaeg', 'bbwaegg', 'bbwaegs', 'bbwaen', 'bbwaenj', 'bbwaenh', 'bbwaed', 'bbwael', 'bbwaelg', 'bbwaelm', 'bbwaelb', 'bbwaels', 'bbwaelt', 'bbwaelp', 'bbwaelh', 'bbwaem', 'bbwaeb', 'bbwaebs', 'bbwaes', 'bbwaess', 'bbwaeng', 'bbwaej', 'bbwaec', 'bbwaek', 'bbwaet', 'bbwaep', 'bbwaeh', 'bboe', 'bboeg', 'bboegg', 'bboegs', 'bboen', 'bboenj', 'bboenh', 'bboed', 'bboel', 'bboelg', 'bboelm', 'bboelb', 'bboels', 'bboelt', 'bboelp', 'bboelh', 'bboem', 'bboeb', 'bboebs', 'bboes', 'bboess', 'bboeng', 'bboej', 'bboec', 'bboek', 'bboet', 'bboep', 'bboeh', 'bbyo', 'bbyog', 'bbyogg', 'bbyogs', 'bbyon', 'bbyonj', 'bbyonh', 'bbyod', 'bbyol', 'bbyolg', 'bbyolm', 'bbyolb', 'bbyols', 'bbyolt', 'bbyolp', 'bbyolh', 'bbyom', 'bbyob', 'bbyobs', 'bbyos', 'bbyoss', 'bbyong', 'bbyoj', 'bbyoc', 'bbyok', 'bbyot', 'bbyop', 'bbyoh', 'bbu', 'bbug', 'bbugg', 'bbugs', 'bbun', 'bbunj', 'bbunh', 'bbud', 'bbul', 'bbulg', 'bbulm', 'bbulb', 'bbuls', 'bbult', 'bbulp', 'bbulh', 'bbum', 'bbub', 'bbubs', 'bbus', 'bbuss', 'bbung', 'bbuj', 'bbuc', 'bbuk', 'bbut', 'bbup', 'bbuh', 'bbweo', 'bbweog', 'bbweogg', 'bbweogs', 'bbweon', 'bbweonj', 'bbweonh', 'bbweod', 'bbweol', 'bbweolg', 'bbweolm', 'bbweolb', 'bbweols', 'bbweolt', 'bbweolp', 'bbweolh', 'bbweom', 'bbweob', 'bbweobs', 'bbweos', 'bbweoss', 'bbweong', 'bbweoj', 'bbweoc'];
<?php return ['A', 'AE', 'ae', 'B', 'C', 'D', 'D', 'E', 'e', 'i', 'J', 'K', 'L', 'M', 'N', 'O', '', 'O', '', 'O', 'Oe', 'Ou', '', '', 'P', 'R', 'R', 'T', 'U', 'u', 'u', 'm', 'V', 'W', 'Z', '', '', '', '', '', '', '', '', '', 'A', 'AE', 'B', 'B', 'D', 'E', 'E', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'N', 'O', 'Ou', 'P', 'R', 'T', 'U', 'W', 'a', 'a', 'a', 'ae', 'b', 'd', 'e', '', 'e', 'e', 'g', 'i', 'k', 'm', '', 'o', '', '', '', 'p', 't', 'u', 'u', 'm', 'v', '', 'b', 'g', 'd', 'f', '', 'i', 'r', 'u', 'v', 'b', 'g', 'r', 'f', '', '', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'g', '', '', '', '', '', 'p', '', '', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', '', 'v', 'x', 'z', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['Dang ', 'Ma ', 'Sha ', 'Dan ', 'Jue ', 'Li ', 'Fu ', 'Min ', 'Nuo ', 'Huo ', 'Kang ', 'Zhi ', 'Qi ', 'Kan ', 'Jie ', 'Fen ', 'E ', 'Ya ', 'Pi ', 'Zhe ', 'Yan ', 'Sui ', 'Zhuan ', 'Che ', 'Dun ', 'Pan ', 'Yan ', '[?] ', 'Feng ', 'Fa ', 'Mo ', 'Zha ', 'Qu ', 'Yu ', 'Luo ', 'Tuo ', 'Tuo ', 'Di ', 'Zhai ', 'Zhen ', 'Ai ', 'Fei ', 'Mu ', 'Zhu ', 'Li ', 'Bian ', 'Nu ', 'Ping ', 'Peng ', 'Ling ', 'Pao ', 'Le ', 'Po ', 'Bo ', 'Po ', 'Shen ', 'Za ', 'Nuo ', 'Li ', 'Long ', 'Tong ', '[?] ', 'Li ', 'Aragane ', 'Chu ', 'Keng ', 'Quan ', 'Zhu ', 'Kuang ', 'Huo ', 'E ', 'Nao ', 'Jia ', 'Lu ', 'Wei ', 'Ai ', 'Luo ', 'Ken ', 'Xing ', 'Yan ', 'Tong ', 'Peng ', 'Xi ', '[?] ', 'Hong ', 'Shuo ', 'Xia ', 'Qiao ', '[?] ', 'Wei ', 'Qiao ', '[?] ', 'Keng ', 'Xiao ', 'Que ', 'Chan ', 'Lang ', 'Hong ', 'Yu ', 'Xiao ', 'Xia ', 'Mang ', 'Long ', 'Iong ', 'Che ', 'Che ', 'E ', 'Liu ', 'Ying ', 'Mang ', 'Que ', 'Yan ', 'Sha ', 'Kun ', 'Yu ', '[?] ', 'Kaki ', 'Lu ', 'Chen ', 'Jian ', 'Nue ', 'Song ', 'Zhuo ', 'Keng ', 'Peng ', 'Yan ', 'Zhui ', 'Kong ', 'Ceng ', 'Qi ', 'Zong ', 'Qing ', 'Lin ', 'Jun ', 'Bo ', 'Ding ', 'Min ', 'Diao ', 'Jian ', 'He ', 'Lu ', 'Ai ', 'Sui ', 'Que ', 'Ling ', 'Bei ', 'Yin ', 'Dui ', 'Wu ', 'Qi ', 'Lun ', 'Wan ', 'Dian ', 'Gang ', 'Pei ', 'Qi ', 'Chen ', 'Ruan ', 'Yan ', 'Die ', 'Ding ', 'Du ', 'Tuo ', 'Jie ', 'Ying ', 'Bian ', 'Ke ', 'Bi ', 'Wei ', 'Shuo ', 'Zhen ', 'Duan ', 'Xia ', 'Dang ', 'Ti ', 'Nao ', 'Peng ', 'Jian ', 'Di ', 'Tan ', 'Cha ', 'Seki ', 'Qi ', '[?] ', 'Feng ', 'Xuan ', 'Que ', 'Que ', 'Ma ', 'Gong ', 'Nian ', 'Su ', 'E ', 'Ci ', 'Liu ', 'Si ', 'Tang ', 'Bang ', 'Hua ', 'Pi ', 'Wei ', 'Sang ', 'Lei ', 'Cuo ', 'Zhen ', 'Xia ', 'Qi ', 'Lian ', 'Pan ', 'Wei ', 'Yun ', 'Dui ', 'Zhe ', 'Ke ', 'La ', '[?] ', 'Qing ', 'Gun ', 'Zhuan ', 'Chan ', 'Qi ', 'Ao ', 'Peng ', 'Lu ', 'Lu ', 'Kan ', 'Qiang ', 'Chen ', 'Yin ', 'Lei ', 'Biao ', 'Qi ', 'Mo ', 'Qi ', 'Cui ', 'Zong ', 'Qing ', 'Chuo ', '[?] ', 'Ji ', 'Shan ', 'Lao ', 'Qu ', 'Zeng ', 'Deng ', 'Jian ', 'Xi ', 'Lin ', 'Ding ', 'Dian ', 'Huang ', 'Pan ', 'Za ', 'Qiao ', 'Di ', 'Li '];
<?php return ['[?]', '[?]', '[?]', '[?]', '[?]', 'B', 'P', 'M', 'F', 'D', 'T', 'N', 'L', 'G', 'K', 'H', 'J', 'Q', 'X', 'ZH', 'CH', 'SH', 'R', 'Z', 'C', 'S', 'A', 'O', 'E', 'EH', 'AI', 'EI', 'AU', 'OU', 'AN', 'EN', 'ANG', 'ENG', 'ER', 'I', 'U', 'IU', 'V', 'NG', 'GN', '[?]', '[?]', '[?]', '[?]', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', 'a', 'ae', 'ya', 'yae', 'eo', 'e', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', 'yo', 'u', 'weo', 'we', 'wi', 'yu', 'eu', 'yi', 'i', '', 'nn', 'nd', 'ns', 'nZ', 'lgs', 'ld', 'lbs', 'lZ', 'lQ', 'mb', 'ms', 'mZ', 'mN', 'bg', '', 'bsg', 'bst', 'bj', 'bt', 'bN', 'bbN', 'sg', 'sn', 'sd', 'sb', 'sj', 'Z', '', 'N', 'Ns', 'NZ', 'pN', 'hh', 'Q', 'yo-ya', 'yo-yae', 'yo-i', 'yu-yeo', 'yu-ye', 'yu-i', 'U', 'U-i', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'BU', 'ZI', 'JI', 'GU', 'EE', 'ENN', 'OO', 'ONN', 'IR', 'ANN', 'INN', 'UNN', 'IM', 'NGG', 'AINN', 'AUNN', 'AM', 'OM', 'ONG', 'INNN', 'P', 'T', 'K', 'H', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'A', 'B', 'G', 'D', 'E', 'Z', 'E', 'E', 'T`', 'Zh', 'I', 'L', 'Kh', 'Ts', 'K', 'H', 'Dz', 'Gh', 'Ch', 'M', 'Y', 'N', 'Sh', 'O', 'Ch`', 'P', 'J', 'Rh', 'S', 'V', 'T', 'R', 'Ts`', 'W', 'P`', 'K`', 'O', 'F', '[?]', '[?]', '<', '\'', '/', '!', ',', '?', '.', '[?]', 'a', 'b', 'g', 'd', 'e', 'z', 'e', 'e', 't`', 'zh', 'i', 'l', 'kh', 'ts', 'k', 'h', 'dz', 'gh', 'ch', 'm', 'y', 'n', 'sh', 'o', 'ch`', 'p', 'j', 'rh', 's', 'v', 't', 'r', 'ts`', 'w', 'p`', 'k`', 'o', 'f', 'ew', '[?]', ':', '-', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '@', 'e', 'a', 'o', 'i', 'e', 'e', 'a', 'a', 'o', 'o', 'u', '\'', '', '-', '-', '|', '', '', ':', '', '', 'n', 'o', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'A', 'b', 'g', 'd', 'h', 'v', 'z', 'KH', 't', 'y', 'k', 'k', 'l', 'm', 'm', 'n', 'n', 's', '`', 'p', 'p', 'TS', 'TS', 'q', 'r', 'SH', 't', '[?]', '[?]', '[?]', '[?]', '[?]', 'V', 'OY', 'i', '\'', '"', 'v', 'n', 'q', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['ssal', 'ssalg', 'ssalm', 'ssalb', 'ssals', 'ssalt', 'ssalp', 'ssalh', 'ssam', 'ssab', 'ssabs', 'ssas', 'ssass', 'ssang', 'ssaj', 'ssac', 'ssak', 'ssat', 'ssap', 'ssah', 'ssae', 'ssaeg', 'ssaegg', 'ssaegs', 'ssaen', 'ssaenj', 'ssaenh', 'ssaed', 'ssael', 'ssaelg', 'ssaelm', 'ssaelb', 'ssaels', 'ssaelt', 'ssaelp', 'ssaelh', 'ssaem', 'ssaeb', 'ssaebs', 'ssaes', 'ssaess', 'ssaeng', 'ssaej', 'ssaec', 'ssaek', 'ssaet', 'ssaep', 'ssaeh', 'ssya', 'ssyag', 'ssyagg', 'ssyags', 'ssyan', 'ssyanj', 'ssyanh', 'ssyad', 'ssyal', 'ssyalg', 'ssyalm', 'ssyalb', 'ssyals', 'ssyalt', 'ssyalp', 'ssyalh', 'ssyam', 'ssyab', 'ssyabs', 'ssyas', 'ssyass', 'ssyang', 'ssyaj', 'ssyac', 'ssyak', 'ssyat', 'ssyap', 'ssyah', 'ssyae', 'ssyaeg', 'ssyaegg', 'ssyaegs', 'ssyaen', 'ssyaenj', 'ssyaenh', 'ssyaed', 'ssyael', 'ssyaelg', 'ssyaelm', 'ssyaelb', 'ssyaels', 'ssyaelt', 'ssyaelp', 'ssyaelh', 'ssyaem', 'ssyaeb', 'ssyaebs', 'ssyaes', 'ssyaess', 'ssyaeng', 'ssyaej', 'ssyaec', 'ssyaek', 'ssyaet', 'ssyaep', 'ssyaeh', 'sseo', 'sseog', 'sseogg', 'sseogs', 'sseon', 'sseonj', 'sseonh', 'sseod', 'sseol', 'sseolg', 'sseolm', 'sseolb', 'sseols', 'sseolt', 'sseolp', 'sseolh', 'sseom', 'sseob', 'sseobs', 'sseos', 'sseoss', 'sseong', 'sseoj', 'sseoc', 'sseok', 'sseot', 'sseop', 'sseoh', 'sse', 'sseg', 'ssegg', 'ssegs', 'ssen', 'ssenj', 'ssenh', 'ssed', 'ssel', 'sselg', 'sselm', 'sselb', 'ssels', 'sselt', 'sselp', 'sselh', 'ssem', 'sseb', 'ssebs', 'sses', 'ssess', 'sseng', 'ssej', 'ssec', 'ssek', 'sset', 'ssep', 'sseh', 'ssyeo', 'ssyeog', 'ssyeogg', 'ssyeogs', 'ssyeon', 'ssyeonj', 'ssyeonh', 'ssyeod', 'ssyeol', 'ssyeolg', 'ssyeolm', 'ssyeolb', 'ssyeols', 'ssyeolt', 'ssyeolp', 'ssyeolh', 'ssyeom', 'ssyeob', 'ssyeobs', 'ssyeos', 'ssyeoss', 'ssyeong', 'ssyeoj', 'ssyeoc', 'ssyeok', 'ssyeot', 'ssyeop', 'ssyeoh', 'ssye', 'ssyeg', 'ssyegg', 'ssyegs', 'ssyen', 'ssyenj', 'ssyenh', 'ssyed', 'ssyel', 'ssyelg', 'ssyelm', 'ssyelb', 'ssyels', 'ssyelt', 'ssyelp', 'ssyelh', 'ssyem', 'ssyeb', 'ssyebs', 'ssyes', 'ssyess', 'ssyeng', 'ssyej', 'ssyec', 'ssyek', 'ssyet', 'ssyep', 'ssyeh', 'sso', 'ssog', 'ssogg', 'ssogs', 'sson', 'ssonj', 'ssonh', 'ssod', 'ssol', 'ssolg', 'ssolm', 'ssolb', 'ssols', 'ssolt', 'ssolp', 'ssolh', 'ssom', 'ssob', 'ssobs', 'ssos', 'ssoss', 'ssong', 'ssoj', 'ssoc', 'ssok', 'ssot', 'ssop', 'ssoh', 'sswa', 'sswag', 'sswagg', 'sswags', 'sswan', 'sswanj', 'sswanh', 'sswad', 'sswal', 'sswalg', 'sswalm', 'sswalb'];
<?php return ['Ji ', 'Cha ', 'Zhou ', 'Xun ', 'Yue ', 'Hong ', 'Yu ', 'He ', 'Wan ', 'Ren ', 'Wen ', 'Wen ', 'Qiu ', 'Na ', 'Zi ', 'Tou ', 'Niu ', 'Fou ', 'Jie ', 'Shu ', 'Chun ', 'Pi ', 'Yin ', 'Sha ', 'Hong ', 'Zhi ', 'Ji ', 'Fen ', 'Yun ', 'Ren ', 'Dan ', 'Jin ', 'Su ', 'Fang ', 'Suo ', 'Cui ', 'Jiu ', 'Zha ', 'Kinu ', 'Jin ', 'Fu ', 'Zhi ', 'Ci ', 'Zi ', 'Chou ', 'Hong ', 'Zha ', 'Lei ', 'Xi ', 'Fu ', 'Xie ', 'Shen ', 'Bei ', 'Zhu ', 'Qu ', 'Ling ', 'Zhu ', 'Shao ', 'Gan ', 'Yang ', 'Fu ', 'Tuo ', 'Zhen ', 'Dai ', 'Zhuo ', 'Shi ', 'Zhong ', 'Xian ', 'Zu ', 'Jiong ', 'Ban ', 'Ju ', 'Mo ', 'Shu ', 'Zui ', 'Wata ', 'Jing ', 'Ren ', 'Heng ', 'Xie ', 'Jie ', 'Zhu ', 'Chou ', 'Gua ', 'Bai ', 'Jue ', 'Kuang ', 'Hu ', 'Ci ', 'Geng ', 'Geng ', 'Tao ', 'Xie ', 'Ku ', 'Jiao ', 'Quan ', 'Gai ', 'Luo ', 'Xuan ', 'Bing ', 'Xian ', 'Fu ', 'Gei ', 'Tong ', 'Rong ', 'Tiao ', 'Yin ', 'Lei ', 'Xie ', 'Quan ', 'Xu ', 'Lun ', 'Die ', 'Tong ', 'Si ', 'Jiang ', 'Xiang ', 'Hui ', 'Jue ', 'Zhi ', 'Jian ', 'Juan ', 'Chi ', 'Mian ', 'Zhen ', 'Lu ', 'Cheng ', 'Qiu ', 'Shu ', 'Bang ', 'Tong ', 'Xiao ', 'Wan ', 'Qin ', 'Geng ', 'Xiu ', 'Ti ', 'Xiu ', 'Xie ', 'Hong ', 'Xi ', 'Fu ', 'Ting ', 'Sui ', 'Dui ', 'Kun ', 'Fu ', 'Jing ', 'Hu ', 'Zhi ', 'Yan ', 'Jiong ', 'Feng ', 'Ji ', 'Sok ', 'Kase ', 'Zong ', 'Lin ', 'Duo ', 'Li ', 'Lu ', 'Liang ', 'Chou ', 'Quan ', 'Shao ', 'Qi ', 'Qi ', 'Zhun ', 'Qi ', 'Wan ', 'Qian ', 'Xian ', 'Shou ', 'Wei ', 'Qi ', 'Tao ', 'Wan ', 'Gang ', 'Wang ', 'Beng ', 'Zhui ', 'Cai ', 'Guo ', 'Cui ', 'Lun ', 'Liu ', 'Qi ', 'Zhan ', 'Bei ', 'Chuo ', 'Ling ', 'Mian ', 'Qi ', 'Qie ', 'Tan ', 'Zong ', 'Gun ', 'Zou ', 'Yi ', 'Zi ', 'Xing ', 'Liang ', 'Jin ', 'Fei ', 'Rui ', 'Min ', 'Yu ', 'Zong ', 'Fan ', 'Lu ', 'Xu ', 'Yingl ', 'Zhang ', 'Kasuri ', 'Xu ', 'Xiang ', 'Jian ', 'Ke ', 'Xian ', 'Ruan ', 'Mian ', 'Qi ', 'Duan ', 'Zhong ', 'Di ', 'Min ', 'Miao ', 'Yuan ', 'Xie ', 'Bao ', 'Si ', 'Qiu ', 'Bian ', 'Huan ', 'Geng ', 'Cong ', 'Mian ', 'Wei ', 'Fu ', 'Wei ', 'Yu ', 'Gou ', 'Miao ', 'Xie ', 'Lian ', 'Zong ', 'Bian ', 'Yun ', 'Yin ', 'Ti ', 'Gua ', 'Zhi ', 'Yun ', 'Cheng ', 'Chan ', 'Dai '];
<?php return ['Bo ', 'Chi ', 'Gua ', 'Zhi ', 'Kuo ', 'Duo ', 'Duo ', 'Zhi ', 'Qie ', 'An ', 'Nong ', 'Zhen ', 'Ge ', 'Jiao ', 'Ku ', 'Dong ', 'Ru ', 'Tiao ', 'Lie ', 'Zha ', 'Lu ', 'Die ', 'Wa ', 'Jue ', 'Mushiru ', 'Ju ', 'Zhi ', 'Luan ', 'Ya ', 'Zhua ', 'Ta ', 'Xie ', 'Nao ', 'Dang ', 'Jiao ', 'Zheng ', 'Ji ', 'Hui ', 'Xun ', 'Ku ', 'Ai ', 'Tuo ', 'Nuo ', 'Cuo ', 'Bo ', 'Geng ', 'Ti ', 'Zhen ', 'Cheng ', 'Suo ', 'Suo ', 'Keng ', 'Mei ', 'Long ', 'Ju ', 'Peng ', 'Jian ', 'Yi ', 'Ting ', 'Shan ', 'Nuo ', 'Wan ', 'Xie ', 'Cha ', 'Feng ', 'Jiao ', 'Wu ', 'Jun ', 'Jiu ', 'Tong ', 'Kun ', 'Huo ', 'Tu ', 'Zhuo ', 'Pou ', 'Le ', 'Ba ', 'Han ', 'Shao ', 'Nie ', 'Juan ', 'Ze ', 'Song ', 'Ye ', 'Jue ', 'Bu ', 'Huan ', 'Bu ', 'Zun ', 'Yi ', 'Zhai ', 'Lu ', 'Sou ', 'Tuo ', 'Lao ', 'Sun ', 'Bang ', 'Jian ', 'Huan ', 'Dao ', '[?] ', 'Wan ', 'Qin ', 'Peng ', 'She ', 'Lie ', 'Min ', 'Men ', 'Fu ', 'Bai ', 'Ju ', 'Dao ', 'Wo ', 'Ai ', 'Juan ', 'Yue ', 'Zong ', 'Chen ', 'Chui ', 'Jie ', 'Tu ', 'Ben ', 'Na ', 'Nian ', 'Nuo ', 'Zu ', 'Wo ', 'Xi ', 'Xian ', 'Cheng ', 'Dian ', 'Sao ', 'Lun ', 'Qing ', 'Gang ', 'Duo ', 'Shou ', 'Diao ', 'Pou ', 'Di ', 'Zhang ', 'Gun ', 'Ji ', 'Tao ', 'Qia ', 'Qi ', 'Pai ', 'Shu ', 'Qian ', 'Ling ', 'Yi ', 'Ya ', 'Jue ', 'Zheng ', 'Liang ', 'Gua ', 'Yi ', 'Huo ', 'Shan ', 'Zheng ', 'Lue ', 'Cai ', 'Tan ', 'Che ', 'Bing ', 'Jie ', 'Ti ', 'Kong ', 'Tui ', 'Yan ', 'Cuo ', 'Zou ', 'Ju ', 'Tian ', 'Qian ', 'Ken ', 'Bai ', 'Shou ', 'Jie ', 'Lu ', 'Guo ', 'Haba ', '[?] ', 'Zhi ', 'Dan ', 'Mang ', 'Xian ', 'Sao ', 'Guan ', 'Peng ', 'Yuan ', 'Nuo ', 'Jian ', 'Zhen ', 'Jiu ', 'Jian ', 'Yu ', 'Yan ', 'Kui ', 'Nan ', 'Hong ', 'Rou ', 'Pi ', 'Wei ', 'Sai ', 'Zou ', 'Xuan ', 'Miao ', 'Ti ', 'Nie ', 'Cha ', 'Shi ', 'Zong ', 'Zhen ', 'Yi ', 'Shun ', 'Heng ', 'Bian ', 'Yang ', 'Huan ', 'Yan ', 'Zuan ', 'An ', 'Xu ', 'Ya ', 'Wo ', 'Ke ', 'Chuai ', 'Ji ', 'Ti ', 'La ', 'La ', 'Cheng ', 'Kai ', 'Jiu ', 'Jiu ', 'Tu ', 'Jie ', 'Hui ', 'Geng ', 'Chong ', 'Shuo ', 'She ', 'Xie ', 'Yuan ', 'Qian ', 'Ye ', 'Cha ', 'Zha ', 'Bei ', 'Yao ', '[?] ', '[?] ', 'Lan ', 'Wen ', 'Qin '];
<?php return ['Huan ', 'Quan ', 'Ze ', 'Wei ', 'Wei ', 'Yu ', 'Qun ', 'Rou ', 'Die ', 'Huang ', 'Lian ', 'Yan ', 'Qiu ', 'Qiu ', 'Jian ', 'Bi ', 'E ', 'Yang ', 'Fu ', 'Sai ', 'Jian ', 'Xia ', 'Tuo ', 'Hu ', 'Muroaji ', 'Ruo ', 'Haraka ', 'Wen ', 'Jian ', 'Hao ', 'Wu ', 'Fang ', 'Sao ', 'Liu ', 'Ma ', 'Shi ', 'Shi ', 'Yin ', 'Z ', 'Teng ', 'Ta ', 'Yao ', 'Ge ', 'Rong ', 'Qian ', 'Qi ', 'Wen ', 'Ruo ', 'Hatahata ', 'Lian ', 'Ao ', 'Le ', 'Hui ', 'Min ', 'Ji ', 'Tiao ', 'Qu ', 'Jian ', 'Sao ', 'Man ', 'Xi ', 'Qiu ', 'Biao ', 'Ji ', 'Ji ', 'Zhu ', 'Jiang ', 'Qiu ', 'Zhuan ', 'Yong ', 'Zhang ', 'Kang ', 'Xue ', 'Bie ', 'Jue ', 'Qu ', 'Xiang ', 'Bo ', 'Jiao ', 'Xun ', 'Su ', 'Huang ', 'Zun ', 'Shan ', 'Shan ', 'Fan ', 'Jue ', 'Lin ', 'Xun ', 'Miao ', 'Xi ', 'Eso ', 'Kyou ', 'Fen ', 'Guan ', 'Hou ', 'Kuai ', 'Zei ', 'Sao ', 'Zhan ', 'Gan ', 'Gui ', 'Sheng ', 'Li ', 'Chang ', 'Hatahata ', 'Shiira ', 'Mutsu ', 'Ru ', 'Ji ', 'Xu ', 'Huo ', 'Shiira ', 'Li ', 'Lie ', 'Li ', 'Mie ', 'Zhen ', 'Xiang ', 'E ', 'Lu ', 'Guan ', 'Li ', 'Xian ', 'Yu ', 'Dao ', 'Ji ', 'You ', 'Tun ', 'Lu ', 'Fang ', 'Ba ', 'He ', 'Bo ', 'Ping ', 'Nian ', 'Lu ', 'You ', 'Zha ', 'Fu ', 'Bo ', 'Bao ', 'Hou ', 'Pi ', 'Tai ', 'Gui ', 'Jie ', 'Kao ', 'Wei ', 'Er ', 'Tong ', 'Ze ', 'Hou ', 'Kuai ', 'Ji ', 'Jiao ', 'Xian ', 'Za ', 'Xiang ', 'Xun ', 'Geng ', 'Li ', 'Lian ', 'Jian ', 'Li ', 'Shi ', 'Tiao ', 'Gun ', 'Sha ', 'Wan ', 'Jun ', 'Ji ', 'Yong ', 'Qing ', 'Ling ', 'Qi ', 'Zou ', 'Fei ', 'Kun ', 'Chang ', 'Gu ', 'Ni ', 'Nian ', 'Diao ', 'Jing ', 'Shen ', 'Shi ', 'Zi ', 'Fen ', 'Die ', 'Bi ', 'Chang ', 'Shi ', 'Wen ', 'Wei ', 'Sai ', 'E ', 'Qiu ', 'Fu ', 'Huang ', 'Quan ', 'Jiang ', 'Bian ', 'Sao ', 'Ao ', 'Qi ', 'Ta ', 'Yin ', 'Yao ', 'Fang ', 'Jian ', 'Le ', 'Biao ', 'Xue ', 'Bie ', 'Man ', 'Min ', 'Yong ', 'Wei ', 'Xi ', 'Jue ', 'Shan ', 'Lin ', 'Zun ', 'Huo ', 'Gan ', 'Li ', 'Zhan ', 'Guan ', 'Niao ', 'Yi ', 'Fu ', 'Li ', 'Jiu ', 'Bu ', 'Yan ', 'Fu ', 'Diao ', 'Ji ', 'Feng ', 'Nio ', 'Gan ', 'Shi ', 'Feng ', 'Ming ', 'Bao ', 'Yuan ', 'Zhi ', 'Hu ', 'Qin ', 'Fu ', 'Fen ', 'Wen ', 'Jian ', 'Shi ', 'Yu '];
<?php return ['Chang ', 'Chi ', 'Bing ', 'Zan ', 'Yao ', 'Cui ', 'Lia ', 'Wan ', 'Lai ', 'Cang ', 'Zong ', 'Ge ', 'Guan ', 'Bei ', 'Tian ', 'Shu ', 'Shu ', 'Men ', 'Dao ', 'Tan ', 'Jue ', 'Chui ', 'Xing ', 'Peng ', 'Tang ', 'Hou ', 'Yi ', 'Qi ', 'Ti ', 'Gan ', 'Jing ', 'Jie ', 'Sui ', 'Chang ', 'Jie ', 'Fang ', 'Zhi ', 'Kong ', 'Juan ', 'Zong ', 'Ju ', 'Qian ', 'Ni ', 'Lun ', 'Zhuo ', 'Wei ', 'Luo ', 'Song ', 'Leng ', 'Hun ', 'Dong ', 'Zi ', 'Ben ', 'Wu ', 'Ju ', 'Nai ', 'Cai ', 'Jian ', 'Zhai ', 'Ye ', 'Zhi ', 'Sha ', 'Qing ', '[?] ', 'Ying ', 'Cheng ', 'Jian ', 'Yan ', 'Nuan ', 'Zhong ', 'Chun ', 'Jia ', 'Jie ', 'Wei ', 'Yu ', 'Bing ', 'Ruo ', 'Ti ', 'Wei ', 'Pian ', 'Yan ', 'Feng ', 'Tang ', 'Wo ', 'E ', 'Xie ', 'Che ', 'Sheng ', 'Kan ', 'Di ', 'Zuo ', 'Cha ', 'Ting ', 'Bei ', 'Ye ', 'Huang ', 'Yao ', 'Zhan ', 'Chou ', 'Yan ', 'You ', 'Jian ', 'Xu ', 'Zha ', 'Ci ', 'Fu ', 'Bi ', 'Zhi ', 'Zong ', 'Mian ', 'Ji ', 'Yi ', 'Xie ', 'Xun ', 'Si ', 'Duan ', 'Ce ', 'Zhen ', 'Ou ', 'Tou ', 'Tou ', 'Bei ', 'Za ', 'Lu ', 'Jie ', 'Wei ', 'Fen ', 'Chang ', 'Gui ', 'Sou ', 'Zhi ', 'Su ', 'Xia ', 'Fu ', 'Yuan ', 'Rong ', 'Li ', 'Ru ', 'Yun ', 'Gou ', 'Ma ', 'Bang ', 'Dian ', 'Tang ', 'Hao ', 'Jie ', 'Xi ', 'Shan ', 'Qian ', 'Jue ', 'Cang ', 'Chu ', 'San ', 'Bei ', 'Xiao ', 'Yong ', 'Yao ', 'Tan ', 'Suo ', 'Yang ', 'Fa ', 'Bing ', 'Jia ', 'Dai ', 'Zai ', 'Tang ', '[?] ', 'Bin ', 'Chu ', 'Nuo ', 'Can ', 'Lei ', 'Cui ', 'Yong ', 'Zao ', 'Zong ', 'Peng ', 'Song ', 'Ao ', 'Chuan ', 'Yu ', 'Zhai ', 'Cou ', 'Shang ', 'Qiang ', 'Jing ', 'Chi ', 'Sha ', 'Han ', 'Zhang ', 'Qing ', 'Yan ', 'Di ', 'Xi ', 'Lu ', 'Bei ', 'Piao ', 'Jin ', 'Lian ', 'Lu ', 'Man ', 'Qian ', 'Xian ', 'Tan ', 'Ying ', 'Dong ', 'Zhuan ', 'Xiang ', 'Shan ', 'Qiao ', 'Jiong ', 'Tui ', 'Zun ', 'Pu ', 'Xi ', 'Lao ', 'Chang ', 'Guang ', 'Liao ', 'Qi ', 'Deng ', 'Chan ', 'Wei ', 'Ji ', 'Fan ', 'Hui ', 'Chuan ', 'Jian ', 'Dan ', 'Jiao ', 'Jiu ', 'Seng ', 'Fen ', 'Xian ', 'Jue ', 'E ', 'Jiao ', 'Jian ', 'Tong ', 'Lin ', 'Bo ', 'Gu ', '[?] ', 'Su ', 'Xian ', 'Jiang ', 'Min ', 'Ye ', 'Jin ', 'Jia ', 'Qiao ', 'Pi ', 'Feng ', 'Zhou ', 'Ai ', 'Sai '];
<?php return ['qiet', 'qiex', 'qie', 'qiep', 'quot', 'quox', 'quo', 'quop', 'qot', 'qox', 'qo', 'qop', 'qut', 'qux', 'qu', 'qup', 'qurx', 'qur', 'qyt', 'qyx', 'qy', 'qyp', 'qyrx', 'qyr', 'jjit', 'jjix', 'jji', 'jjip', 'jjiet', 'jjiex', 'jjie', 'jjiep', 'jjuox', 'jjuo', 'jjuop', 'jjot', 'jjox', 'jjo', 'jjop', 'jjut', 'jjux', 'jju', 'jjup', 'jjurx', 'jjur', 'jjyt', 'jjyx', 'jjy', 'jjyp', 'njit', 'njix', 'nji', 'njip', 'njiet', 'njiex', 'njie', 'njiep', 'njuox', 'njuo', 'njot', 'njox', 'njo', 'njop', 'njux', 'nju', 'njup', 'njurx', 'njur', 'njyt', 'njyx', 'njy', 'njyp', 'njyrx', 'njyr', 'nyit', 'nyix', 'nyi', 'nyip', 'nyiet', 'nyiex', 'nyie', 'nyiep', 'nyuox', 'nyuo', 'nyuop', 'nyot', 'nyox', 'nyo', 'nyop', 'nyut', 'nyux', 'nyu', 'nyup', 'xit', 'xix', 'xi', 'xip', 'xiet', 'xiex', 'xie', 'xiep', 'xuox', 'xuo', 'xot', 'xox', 'xo', 'xop', 'xyt', 'xyx', 'xy', 'xyp', 'xyrx', 'xyr', 'yit', 'yix', 'yi', 'yip', 'yiet', 'yiex', 'yie', 'yiep', 'yuot', 'yuox', 'yuo', 'yuop', 'yot', 'yox', 'yo', 'yop', 'yut', 'yux', 'yu', 'yup', 'yurx', 'yur', 'yyt', 'yyx', 'yy', 'yyp', 'yyrx', 'yyr', '[?]', '[?]', '[?]', 'Qot', 'Li', 'Kit', 'Nyip', 'Cyp', 'Ssi', 'Ggop', 'Gep', 'Mi', 'Hxit', 'Lyr', 'Bbut', 'Mop', 'Yo', 'Put', 'Hxuo', 'Tat', 'Ga', '[?]', '[?]', 'Ddur', 'Bur', 'Gguo', 'Nyop', 'Tu', 'Op', 'Jjut', 'Zot', 'Pyt', 'Hmo', 'Yit', 'Vur', 'Shy', 'Vep', 'Za', 'Jo', '[?]', 'Jjy', 'Got', 'Jjie', 'Wo', 'Du', 'Shur', 'Lie', 'Cy', 'Cuop', 'Cip', 'Hxop', 'Shat', '[?]', 'Shop', 'Che', 'Zziet', '[?]', 'Ke', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['ruk', 'rut', 'rup', 'ruh', 'rweo', 'rweog', 'rweogg', 'rweogs', 'rweon', 'rweonj', 'rweonh', 'rweod', 'rweol', 'rweolg', 'rweolm', 'rweolb', 'rweols', 'rweolt', 'rweolp', 'rweolh', 'rweom', 'rweob', 'rweobs', 'rweos', 'rweoss', 'rweong', 'rweoj', 'rweoc', 'rweok', 'rweot', 'rweop', 'rweoh', 'rwe', 'rweg', 'rwegg', 'rwegs', 'rwen', 'rwenj', 'rwenh', 'rwed', 'rwel', 'rwelg', 'rwelm', 'rwelb', 'rwels', 'rwelt', 'rwelp', 'rwelh', 'rwem', 'rweb', 'rwebs', 'rwes', 'rwess', 'rweng', 'rwej', 'rwec', 'rwek', 'rwet', 'rwep', 'rweh', 'rwi', 'rwig', 'rwigg', 'rwigs', 'rwin', 'rwinj', 'rwinh', 'rwid', 'rwil', 'rwilg', 'rwilm', 'rwilb', 'rwils', 'rwilt', 'rwilp', 'rwilh', 'rwim', 'rwib', 'rwibs', 'rwis', 'rwiss', 'rwing', 'rwij', 'rwic', 'rwik', 'rwit', 'rwip', 'rwih', 'ryu', 'ryug', 'ryugg', 'ryugs', 'ryun', 'ryunj', 'ryunh', 'ryud', 'ryul', 'ryulg', 'ryulm', 'ryulb', 'ryuls', 'ryult', 'ryulp', 'ryulh', 'ryum', 'ryub', 'ryubs', 'ryus', 'ryuss', 'ryung', 'ryuj', 'ryuc', 'ryuk', 'ryut', 'ryup', 'ryuh', 'reu', 'reug', 'reugg', 'reugs', 'reun', 'reunj', 'reunh', 'reud', 'reul', 'reulg', 'reulm', 'reulb', 'reuls', 'reult', 'reulp', 'reulh', 'reum', 'reub', 'reubs', 'reus', 'reuss', 'reung', 'reuj', 'reuc', 'reuk', 'reut', 'reup', 'reuh', 'ryi', 'ryig', 'ryigg', 'ryigs', 'ryin', 'ryinj', 'ryinh', 'ryid', 'ryil', 'ryilg', 'ryilm', 'ryilb', 'ryils', 'ryilt', 'ryilp', 'ryilh', 'ryim', 'ryib', 'ryibs', 'ryis', 'ryiss', 'rying', 'ryij', 'ryic', 'ryik', 'ryit', 'ryip', 'ryih', 'ri', 'rig', 'rigg', 'rigs', 'rin', 'rinj', 'rinh', 'rid', 'ril', 'rilg', 'rilm', 'rilb', 'rils', 'rilt', 'rilp', 'rilh', 'rim', 'rib', 'ribs', 'ris', 'riss', 'ring', 'rij', 'ric', 'rik', 'rit', 'rip', 'rih', 'ma', 'mag', 'magg', 'mags', 'man', 'manj', 'manh', 'mad', 'mal', 'malg', 'malm', 'malb', 'mals', 'malt', 'malp', 'malh', 'mam', 'mab', 'mabs', 'mas', 'mass', 'mang', 'maj', 'mac', 'mak', 'mat', 'map', 'mah', 'mae', 'maeg', 'maegg', 'maegs', 'maen', 'maenj', 'maenh', 'maed', 'mael', 'maelg', 'maelm', 'maelb', 'maels', 'maelt', 'maelp', 'maelh', 'maem', 'maeb', 'maebs', 'maes', 'maess', 'maeng', 'maej', 'maec', 'maek', 'maet', 'maep', 'maeh'];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'L', 'l', 'L', 'P', 'R', 'a', 't', 'H', 'h', 'K', 'k', 'Z', 'z', '', 'M', 'A', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['[?]', '[?]', 'N', '[?]', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', '[?]', '[?]', '[?]', '[?]', 'ee', 'ai', '[?]', '[?]', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bb', 'm', 'y', 'r', '[?]', 'l', 'll', '[?]', 'v', 'sh', '[?]', 's', 'h', '[?]', '[?]', '\'', '[?]', 'aa', 'i', 'ii', 'u', 'uu', '[?]', '[?]', '[?]', '[?]', 'ee', 'ai', '[?]', '[?]', 'oo', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'khh', 'ghh', 'z', 'rr', '[?]', 'f', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'N', 'H', '', '', 'G.E.O.', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', '[?]', 'eN', '[?]', 'e', 'ai', 'oN', '[?]', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'ya', 'r', '[?]', 'l', 'll', '[?]', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '\'', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'eN', '[?]', 'e', 'ai', 'oN', '[?]', 'o', 'au', '', '[?]', '[?]', 'AUM', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'RR', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['jjael', 'jjaelg', 'jjaelm', 'jjaelb', 'jjaels', 'jjaelt', 'jjaelp', 'jjaelh', 'jjaem', 'jjaeb', 'jjaebs', 'jjaes', 'jjaess', 'jjaeng', 'jjaej', 'jjaec', 'jjaek', 'jjaet', 'jjaep', 'jjaeh', 'jjya', 'jjyag', 'jjyagg', 'jjyags', 'jjyan', 'jjyanj', 'jjyanh', 'jjyad', 'jjyal', 'jjyalg', 'jjyalm', 'jjyalb', 'jjyals', 'jjyalt', 'jjyalp', 'jjyalh', 'jjyam', 'jjyab', 'jjyabs', 'jjyas', 'jjyass', 'jjyang', 'jjyaj', 'jjyac', 'jjyak', 'jjyat', 'jjyap', 'jjyah', 'jjyae', 'jjyaeg', 'jjyaegg', 'jjyaegs', 'jjyaen', 'jjyaenj', 'jjyaenh', 'jjyaed', 'jjyael', 'jjyaelg', 'jjyaelm', 'jjyaelb', 'jjyaels', 'jjyaelt', 'jjyaelp', 'jjyaelh', 'jjyaem', 'jjyaeb', 'jjyaebs', 'jjyaes', 'jjyaess', 'jjyaeng', 'jjyaej', 'jjyaec', 'jjyaek', 'jjyaet', 'jjyaep', 'jjyaeh', 'jjeo', 'jjeog', 'jjeogg', 'jjeogs', 'jjeon', 'jjeonj', 'jjeonh', 'jjeod', 'jjeol', 'jjeolg', 'jjeolm', 'jjeolb', 'jjeols', 'jjeolt', 'jjeolp', 'jjeolh', 'jjeom', 'jjeob', 'jjeobs', 'jjeos', 'jjeoss', 'jjeong', 'jjeoj', 'jjeoc', 'jjeok', 'jjeot', 'jjeop', 'jjeoh', 'jje', 'jjeg', 'jjegg', 'jjegs', 'jjen', 'jjenj', 'jjenh', 'jjed', 'jjel', 'jjelg', 'jjelm', 'jjelb', 'jjels', 'jjelt', 'jjelp', 'jjelh', 'jjem', 'jjeb', 'jjebs', 'jjes', 'jjess', 'jjeng', 'jjej', 'jjec', 'jjek', 'jjet', 'jjep', 'jjeh', 'jjyeo', 'jjyeog', 'jjyeogg', 'jjyeogs', 'jjyeon', 'jjyeonj', 'jjyeonh', 'jjyeod', 'jjyeol', 'jjyeolg', 'jjyeolm', 'jjyeolb', 'jjyeols', 'jjyeolt', 'jjyeolp', 'jjyeolh', 'jjyeom', 'jjyeob', 'jjyeobs', 'jjyeos', 'jjyeoss', 'jjyeong', 'jjyeoj', 'jjyeoc', 'jjyeok', 'jjyeot', 'jjyeop', 'jjyeoh', 'jjye', 'jjyeg', 'jjyegg', 'jjyegs', 'jjyen', 'jjyenj', 'jjyenh', 'jjyed', 'jjyel', 'jjyelg', 'jjyelm', 'jjyelb', 'jjyels', 'jjyelt', 'jjyelp', 'jjyelh', 'jjyem', 'jjyeb', 'jjyebs', 'jjyes', 'jjyess', 'jjyeng', 'jjyej', 'jjyec', 'jjyek', 'jjyet', 'jjyep', 'jjyeh', 'jjo', 'jjog', 'jjogg', 'jjogs', 'jjon', 'jjonj', 'jjonh', 'jjod', 'jjol', 'jjolg', 'jjolm', 'jjolb', 'jjols', 'jjolt', 'jjolp', 'jjolh', 'jjom', 'jjob', 'jjobs', 'jjos', 'jjoss', 'jjong', 'jjoj', 'jjoc', 'jjok', 'jjot', 'jjop', 'jjoh', 'jjwa', 'jjwag', 'jjwagg', 'jjwags', 'jjwan', 'jjwanj', 'jjwanh', 'jjwad', 'jjwal', 'jjwalg', 'jjwalm', 'jjwalb', 'jjwals', 'jjwalt', 'jjwalp', 'jjwalh', 'jjwam', 'jjwab', 'jjwabs', 'jjwas', 'jjwass', 'jjwang', 'jjwaj', 'jjwac', 'jjwak', 'jjwat', 'jjwap', 'jjwah', 'jjwae', 'jjwaeg', 'jjwaegg', 'jjwaegs', 'jjwaen', 'jjwaenj', 'jjwaenh', 'jjwaed', 'jjwael', 'jjwaelg', 'jjwaelm', 'jjwaelb'];
<?php return ['[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'rr', 'l', 'll', '[?]', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'rr', 'l', 'll', '[?]', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'lll', '[?]', 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Tuo ', 'Wu ', 'Rui ', 'Rui ', 'Qi ', 'Heng ', 'Lu ', 'Su ', 'Tui ', 'Mang ', 'Yun ', 'Pin ', 'Yu ', 'Xun ', 'Ji ', 'Jiong ', 'Xian ', 'Mo ', 'Hagi ', 'Su ', 'Jiong ', '[?] ', 'Nie ', 'Bo ', 'Rang ', 'Yi ', 'Xian ', 'Yu ', 'Ju ', 'Lian ', 'Lian ', 'Yin ', 'Qiang ', 'Ying ', 'Long ', 'Tong ', 'Wei ', 'Yue ', 'Ling ', 'Qu ', 'Yao ', 'Fan ', 'Mi ', 'Lan ', 'Kui ', 'Lan ', 'Ji ', 'Dang ', 'Katsura ', 'Lei ', 'Lei ', 'Hua ', 'Feng ', 'Zhi ', 'Wei ', 'Kui ', 'Zhan ', 'Huai ', 'Li ', 'Ji ', 'Mi ', 'Lei ', 'Huai ', 'Luo ', 'Ji ', 'Kui ', 'Lu ', 'Jian ', 'San ', '[?] ', 'Lei ', 'Quan ', 'Xiao ', 'Yi ', 'Luan ', 'Men ', 'Bie ', 'Hu ', 'Hu ', 'Lu ', 'Nue ', 'Lu ', 'Si ', 'Xiao ', 'Qian ', 'Chu ', 'Hu ', 'Xu ', 'Cuo ', 'Fu ', 'Xu ', 'Xu ', 'Lu ', 'Hu ', 'Yu ', 'Hao ', 'Jiao ', 'Ju ', 'Guo ', 'Bao ', 'Yan ', 'Zhan ', 'Zhan ', 'Kui ', 'Ban ', 'Xi ', 'Shu ', 'Chong ', 'Qiu ', 'Diao ', 'Ji ', 'Qiu ', 'Cheng ', 'Shi ', '[?] ', 'Di ', 'Zhe ', 'She ', 'Yu ', 'Gan ', 'Zi ', 'Hong ', 'Hui ', 'Meng ', 'Ge ', 'Sui ', 'Xia ', 'Chai ', 'Shi ', 'Yi ', 'Ma ', 'Xiang ', 'Fang ', 'E ', 'Pa ', 'Chi ', 'Qian ', 'Wen ', 'Wen ', 'Rui ', 'Bang ', 'Bi ', 'Yue ', 'Yue ', 'Jun ', 'Qi ', 'Ran ', 'Yin ', 'Qi ', 'Tian ', 'Yuan ', 'Jue ', 'Hui ', 'Qin ', 'Qi ', 'Zhong ', 'Ya ', 'Ci ', 'Mu ', 'Wang ', 'Fen ', 'Fen ', 'Hang ', 'Gong ', 'Zao ', 'Fu ', 'Ran ', 'Jie ', 'Fu ', 'Chi ', 'Dou ', 'Piao ', 'Xian ', 'Ni ', 'Te ', 'Qiu ', 'You ', 'Zha ', 'Ping ', 'Chi ', 'You ', 'He ', 'Han ', 'Ju ', 'Li ', 'Fu ', 'Ran ', 'Zha ', 'Gou ', 'Pi ', 'Bo ', 'Xian ', 'Zhu ', 'Diao ', 'Bie ', 'Bing ', 'Gu ', 'Ran ', 'Qu ', 'She ', 'Tie ', 'Ling ', 'Gu ', 'Dan ', 'Gu ', 'Ying ', 'Li ', 'Cheng ', 'Qu ', 'Mou ', 'Ge ', 'Ci ', 'Hui ', 'Hui ', 'Mang ', 'Fu ', 'Yang ', 'Wa ', 'Lie ', 'Zhu ', 'Yi ', 'Xian ', 'Kuo ', 'Jiao ', 'Li ', 'Yi ', 'Ping ', 'Ji ', 'Ha ', 'She ', 'Yi ', 'Wang ', 'Mo ', 'Qiong ', 'Qie ', 'Gui ', 'Gong ', 'Zhi ', 'Man ', 'Ebi ', 'Zhi ', 'Jia ', 'Rao ', 'Si ', 'Qi ', 'Xing ', 'Lie ', 'Qiu ', 'Shao ', 'Yong ', 'Jia ', 'Shui ', 'Che ', 'Bai ', 'E ', 'Han '];
<?php return ['ja', 'ju', 'ji', 'jaa', 'jee', 'je', 'jo', 'jwa', 'ga', 'gu', 'gi', 'gaa', 'gee', 'ge', 'go', '[?]', 'gwa', '[?]', 'gwi', 'gwaa', 'gwee', 'gwe', '[?]', '[?]', 'gga', 'ggu', 'ggi', 'ggaa', 'ggee', 'gge', 'ggo', '[?]', 'tha', 'thu', 'thi', 'thaa', 'thee', 'the', 'tho', 'thwa', 'cha', 'chu', 'chi', 'chaa', 'chee', 'che', 'cho', 'chwa', 'pha', 'phu', 'phi', 'phaa', 'phee', 'phe', 'pho', 'phwa', 'tsa', 'tsu', 'tsi', 'tsaa', 'tsee', 'tse', 'tso', 'tswa', 'tza', 'tzu', 'tzi', 'tzaa', 'tzee', 'tze', 'tzo', '[?]', 'fa', 'fu', 'fi', 'faa', 'fee', 'fe', 'fo', 'fwa', 'pa', 'pu', 'pi', 'paa', 'pee', 'pe', 'po', 'pwa', 'rya', 'mya', 'fya', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ' ', '.', ',', ';', ':', ':: ', '?', '//', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10+', '20+', '30+', '40+', '50+', '60+', '70+', '80+', '90+', '100+', '10,000+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'a', 'e', 'i', 'o', 'u', 'v', 'ga', 'ka', 'ge', 'gi', 'go', 'gu', 'gv', 'ha', 'he', 'hi', 'ho', 'hu', 'hv', 'la', 'le', 'li', 'lo', 'lu', 'lv', 'ma', 'me', 'mi', 'mo', 'mu', 'na', 'hna', 'nah', 'ne', 'ni', 'no', 'nu', 'nv', 'qua', 'que', 'qui', 'quo', 'quu', 'quv', 'sa', 's', 'se', 'si', 'so', 'su', 'sv', 'da', 'ta', 'de', 'te', 'di', 'ti', 'do', 'du', 'dv', 'dla', 'tla', 'tle', 'tli', 'tlo', 'tlu', 'tlv', 'tsa', 'tse', 'tsi', 'tso', 'tsu', 'tsv', 'wa', 'we', 'wi', 'wo', 'wu', 'wv', 'ya', 'ye', 'yi', 'yo', 'yu', 'yv', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', 'a', 'e', 'i', 'o', 'u', 'c', 'd', 'h', 'm', 'r', 't', 'v', 'x', '[?]', '[?]', '[?]', '[?]', '\'', ',', '[?]', '[?]', '[?]', '[?]', '', '[?]', '[?]', '[?]', '?', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', 'A', ';', 'E', 'E', 'I', '[?]', 'O', '[?]', 'U', 'O', 'I', 'A', 'B', 'G', 'D', 'E', 'Z', 'E', 'Th', 'I', 'K', 'L', 'M', 'N', 'Ks', 'O', 'P', 'R', '[?]', 'S', 'T', 'U', 'Ph', 'Kh', 'Ps', 'O', 'I', 'U', 'a', 'e', 'e', 'i', 'u', 'a', 'b', 'g', 'd', 'e', 'z', 'e', 'th', 'i', 'k', 'l', 'm', 'n', 'x', 'o', 'p', 'r', 's', 's', 't', 'u', 'ph', 'kh', 'ps', 'o', 'i', 'u', 'o', 'u', 'o', '[?]', 'b', 'th', 'U', 'U', 'U', 'ph', 'p', '&', '[?]', '[?]', 'St', 'st', 'W', 'w', 'Q', 'q', 'Sp', 'sp', 'Sh', 'sh', 'F', 'f', 'Kh', 'kh', 'H', 'h', 'G', 'g', 'CH', 'ch', 'Ti', 'ti', 'k', 'r', 'c', 'j', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['[?]', 'k', 'kh', 'kh', 'kh', 'kh', 'kh', 'ng', 'cch', 'ch', 'ch', 'ch', 'ch', 'y', 'd', 't', 'th', 'th', 'th', 'n', 'd', 't', 'th', 'th', 'th', 'n', 'b', 'p', 'ph', 'f', 'ph', 'f', 'ph', 'm', 'y', 'r', 'R', 'l', 'L', 'w', 's', 's', 's', 'h', 'l', '`', 'h', '~', 'a', 'a', 'aa', 'am', 'i', 'ii', 'ue', 'uue', 'u', 'uu', '\'', '[?]', '[?]', '[?]', '[?]', 'Bh.', 'e', 'ae', 'o', 'ai', 'ai', 'ao', '+', '', '', '', '', '', '', 'M', '', ' * ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' // ', ' /// ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'k', 'kh', '[?]', 'kh', '[?]', '[?]', 'ng', 'ch', '[?]', 's', '[?]', '[?]', 'ny', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'd', 'h', 'th', 'th', '[?]', 'n', 'b', 'p', 'ph', 'f', 'ph', 'f', '[?]', 'm', 'y', 'r', '[?]', 'l', '[?]', 'w', '[?]', '[?]', 's', 'h', '[?]', '`', '', '~', 'a', '', 'aa', 'am', 'i', 'ii', 'y', 'yy', 'u', 'uu', '[?]', 'o', 'l', 'ny', '[?]', '[?]', 'e', 'ei', 'o', 'ay', 'ai', '[?]', '+', '[?]', '', '', '', '', '', 'M', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', 'hn', 'hm', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['bbweok', 'bbweot', 'bbweop', 'bbweoh', 'bbwe', 'bbweg', 'bbwegg', 'bbwegs', 'bbwen', 'bbwenj', 'bbwenh', 'bbwed', 'bbwel', 'bbwelg', 'bbwelm', 'bbwelb', 'bbwels', 'bbwelt', 'bbwelp', 'bbwelh', 'bbwem', 'bbweb', 'bbwebs', 'bbwes', 'bbwess', 'bbweng', 'bbwej', 'bbwec', 'bbwek', 'bbwet', 'bbwep', 'bbweh', 'bbwi', 'bbwig', 'bbwigg', 'bbwigs', 'bbwin', 'bbwinj', 'bbwinh', 'bbwid', 'bbwil', 'bbwilg', 'bbwilm', 'bbwilb', 'bbwils', 'bbwilt', 'bbwilp', 'bbwilh', 'bbwim', 'bbwib', 'bbwibs', 'bbwis', 'bbwiss', 'bbwing', 'bbwij', 'bbwic', 'bbwik', 'bbwit', 'bbwip', 'bbwih', 'bbyu', 'bbyug', 'bbyugg', 'bbyugs', 'bbyun', 'bbyunj', 'bbyunh', 'bbyud', 'bbyul', 'bbyulg', 'bbyulm', 'bbyulb', 'bbyuls', 'bbyult', 'bbyulp', 'bbyulh', 'bbyum', 'bbyub', 'bbyubs', 'bbyus', 'bbyuss', 'bbyung', 'bbyuj', 'bbyuc', 'bbyuk', 'bbyut', 'bbyup', 'bbyuh', 'bbeu', 'bbeug', 'bbeugg', 'bbeugs', 'bbeun', 'bbeunj', 'bbeunh', 'bbeud', 'bbeul', 'bbeulg', 'bbeulm', 'bbeulb', 'bbeuls', 'bbeult', 'bbeulp', 'bbeulh', 'bbeum', 'bbeub', 'bbeubs', 'bbeus', 'bbeuss', 'bbeung', 'bbeuj', 'bbeuc', 'bbeuk', 'bbeut', 'bbeup', 'bbeuh', 'bbyi', 'bbyig', 'bbyigg', 'bbyigs', 'bbyin', 'bbyinj', 'bbyinh', 'bbyid', 'bbyil', 'bbyilg', 'bbyilm', 'bbyilb', 'bbyils', 'bbyilt', 'bbyilp', 'bbyilh', 'bbyim', 'bbyib', 'bbyibs', 'bbyis', 'bbyiss', 'bbying', 'bbyij', 'bbyic', 'bbyik', 'bbyit', 'bbyip', 'bbyih', 'bbi', 'bbig', 'bbigg', 'bbigs', 'bbin', 'bbinj', 'bbinh', 'bbid', 'bbil', 'bbilg', 'bbilm', 'bbilb', 'bbils', 'bbilt', 'bbilp', 'bbilh', 'bbim', 'bbib', 'bbibs', 'bbis', 'bbiss', 'bbing', 'bbij', 'bbic', 'bbik', 'bbit', 'bbip', 'bbih', 'sa', 'sag', 'sagg', 'sags', 'san', 'sanj', 'sanh', 'sad', 'sal', 'salg', 'salm', 'salb', 'sals', 'salt', 'salp', 'salh', 'sam', 'sab', 'sabs', 'sas', 'sass', 'sang', 'saj', 'sac', 'sak', 'sat', 'sap', 'sah', 'sae', 'saeg', 'saegg', 'saegs', 'saen', 'saenj', 'saenh', 'saed', 'sael', 'saelg', 'saelm', 'saelb', 'saels', 'saelt', 'saelp', 'saelh', 'saem', 'saeb', 'saebs', 'saes', 'saess', 'saeng', 'saej', 'saec', 'saek', 'saet', 'saep', 'saeh', 'sya', 'syag', 'syagg', 'syags', 'syan', 'syanj', 'syanh', 'syad', 'syal', 'syalg', 'syalm', 'syalb', 'syals', 'syalt', 'syalp', 'syalh', 'syam', 'syab', 'syabs', 'syas', 'syass', 'syang', 'syaj', 'syac', 'syak', 'syat', 'syap', 'syah'];
<?php return ['Song ', 'Wei ', 'Hong ', 'Wa ', 'Lou ', 'Ya ', 'Rao ', 'Jiao ', 'Luan ', 'Ping ', 'Xian ', 'Shao ', 'Li ', 'Cheng ', 'Xiao ', 'Mang ', 'Fu ', 'Suo ', 'Wu ', 'Wei ', 'Ke ', 'Lai ', 'Chuo ', 'Ding ', 'Niang ', 'Xing ', 'Nan ', 'Yu ', 'Nuo ', 'Pei ', 'Nei ', 'Juan ', 'Shen ', 'Zhi ', 'Han ', 'Di ', 'Zhuang ', 'E ', 'Pin ', 'Tui ', 'Han ', 'Mian ', 'Wu ', 'Yan ', 'Wu ', 'Xi ', 'Yan ', 'Yu ', 'Si ', 'Yu ', 'Wa ', '[?] ', 'Xian ', 'Ju ', 'Qu ', 'Shui ', 'Qi ', 'Xian ', 'Zhui ', 'Dong ', 'Chang ', 'Lu ', 'Ai ', 'E ', 'E ', 'Lou ', 'Mian ', 'Cong ', 'Pou ', 'Ju ', 'Po ', 'Cai ', 'Ding ', 'Wan ', 'Biao ', 'Xiao ', 'Shu ', 'Qi ', 'Hui ', 'Fu ', 'E ', 'Wo ', 'Tan ', 'Fei ', 'Wei ', 'Jie ', 'Tian ', 'Ni ', 'Quan ', 'Jing ', 'Hun ', 'Jing ', 'Qian ', 'Dian ', 'Xing ', 'Hu ', 'Wa ', 'Lai ', 'Bi ', 'Yin ', 'Chou ', 'Chuo ', 'Fu ', 'Jing ', 'Lun ', 'Yan ', 'Lan ', 'Kun ', 'Yin ', 'Ya ', 'Ju ', 'Li ', 'Dian ', 'Xian ', 'Hwa ', 'Hua ', 'Ying ', 'Chan ', 'Shen ', 'Ting ', 'Dang ', 'Yao ', 'Wu ', 'Nan ', 'Ruo ', 'Jia ', 'Tou ', 'Xu ', 'Yu ', 'Wei ', 'Ti ', 'Rou ', 'Mei ', 'Dan ', 'Ruan ', 'Qin ', 'Hui ', 'Wu ', 'Qian ', 'Chun ', 'Mao ', 'Fu ', 'Jie ', 'Duan ', 'Xi ', 'Zhong ', 'Mei ', 'Huang ', 'Mian ', 'An ', 'Ying ', 'Xuan ', 'Jie ', 'Wei ', 'Mei ', 'Yuan ', 'Zhen ', 'Qiu ', 'Ti ', 'Xie ', 'Tuo ', 'Lian ', 'Mao ', 'Ran ', 'Si ', 'Pian ', 'Wei ', 'Wa ', 'Jiu ', 'Hu ', 'Ao ', '[?] ', 'Bou ', 'Xu ', 'Tou ', 'Gui ', 'Zou ', 'Yao ', 'Pi ', 'Xi ', 'Yuan ', 'Ying ', 'Rong ', 'Ru ', 'Chi ', 'Liu ', 'Mei ', 'Pan ', 'Ao ', 'Ma ', 'Gou ', 'Kui ', 'Qin ', 'Jia ', 'Sao ', 'Zhen ', 'Yuan ', 'Cha ', 'Yong ', 'Ming ', 'Ying ', 'Ji ', 'Su ', 'Niao ', 'Xian ', 'Tao ', 'Pang ', 'Lang ', 'Nao ', 'Bao ', 'Ai ', 'Pi ', 'Pin ', 'Yi ', 'Piao ', 'Yu ', 'Lei ', 'Xuan ', 'Man ', 'Yi ', 'Zhang ', 'Kang ', 'Yong ', 'Ni ', 'Li ', 'Di ', 'Gui ', 'Yan ', 'Jin ', 'Zhuan ', 'Chang ', 'Ce ', 'Han ', 'Nen ', 'Lao ', 'Mo ', 'Zhe ', 'Hu ', 'Hu ', 'Ao ', 'Nen ', 'Qiang ', 'Ma ', 'Pie ', 'Gu ', 'Wu ', 'Jiao ', 'Tuo ', 'Zhan ', 'Mao ', 'Xian ', 'Xian ', 'Mo ', 'Liao ', 'Lian ', 'Hua '];
<?php return ['byum', 'byub', 'byubs', 'byus', 'byuss', 'byung', 'byuj', 'byuc', 'byuk', 'byut', 'byup', 'byuh', 'beu', 'beug', 'beugg', 'beugs', 'beun', 'beunj', 'beunh', 'beud', 'beul', 'beulg', 'beulm', 'beulb', 'beuls', 'beult', 'beulp', 'beulh', 'beum', 'beub', 'beubs', 'beus', 'beuss', 'beung', 'beuj', 'beuc', 'beuk', 'beut', 'beup', 'beuh', 'byi', 'byig', 'byigg', 'byigs', 'byin', 'byinj', 'byinh', 'byid', 'byil', 'byilg', 'byilm', 'byilb', 'byils', 'byilt', 'byilp', 'byilh', 'byim', 'byib', 'byibs', 'byis', 'byiss', 'bying', 'byij', 'byic', 'byik', 'byit', 'byip', 'byih', 'bi', 'big', 'bigg', 'bigs', 'bin', 'binj', 'binh', 'bid', 'bil', 'bilg', 'bilm', 'bilb', 'bils', 'bilt', 'bilp', 'bilh', 'bim', 'bib', 'bibs', 'bis', 'biss', 'bing', 'bij', 'bic', 'bik', 'bit', 'bip', 'bih', 'bba', 'bbag', 'bbagg', 'bbags', 'bban', 'bbanj', 'bbanh', 'bbad', 'bbal', 'bbalg', 'bbalm', 'bbalb', 'bbals', 'bbalt', 'bbalp', 'bbalh', 'bbam', 'bbab', 'bbabs', 'bbas', 'bbass', 'bbang', 'bbaj', 'bbac', 'bbak', 'bbat', 'bbap', 'bbah', 'bbae', 'bbaeg', 'bbaegg', 'bbaegs', 'bbaen', 'bbaenj', 'bbaenh', 'bbaed', 'bbael', 'bbaelg', 'bbaelm', 'bbaelb', 'bbaels', 'bbaelt', 'bbaelp', 'bbaelh', 'bbaem', 'bbaeb', 'bbaebs', 'bbaes', 'bbaess', 'bbaeng', 'bbaej', 'bbaec', 'bbaek', 'bbaet', 'bbaep', 'bbaeh', 'bbya', 'bbyag', 'bbyagg', 'bbyags', 'bbyan', 'bbyanj', 'bbyanh', 'bbyad', 'bbyal', 'bbyalg', 'bbyalm', 'bbyalb', 'bbyals', 'bbyalt', 'bbyalp', 'bbyalh', 'bbyam', 'bbyab', 'bbyabs', 'bbyas', 'bbyass', 'bbyang', 'bbyaj', 'bbyac', 'bbyak', 'bbyat', 'bbyap', 'bbyah', 'bbyae', 'bbyaeg', 'bbyaegg', 'bbyaegs', 'bbyaen', 'bbyaenj', 'bbyaenh', 'bbyaed', 'bbyael', 'bbyaelg', 'bbyaelm', 'bbyaelb', 'bbyaels', 'bbyaelt', 'bbyaelp', 'bbyaelh', 'bbyaem', 'bbyaeb', 'bbyaebs', 'bbyaes', 'bbyaess', 'bbyaeng', 'bbyaej', 'bbyaec', 'bbyaek', 'bbyaet', 'bbyaep', 'bbyaeh', 'bbeo', 'bbeog', 'bbeogg', 'bbeogs', 'bbeon', 'bbeonj', 'bbeonh', 'bbeod', 'bbeol', 'bbeolg', 'bbeolm', 'bbeolb', 'bbeols', 'bbeolt', 'bbeolp', 'bbeolh', 'bbeom', 'bbeob', 'bbeobs', 'bbeos', 'bbeoss', 'bbeong', 'bbeoj', 'bbeoc', 'bbeok', 'bbeot', 'bbeop', 'bbeoh', 'bbe', 'bbeg', 'bbegg', 'bbegs', 'bben', 'bbenj', 'bbenh', 'bbed', 'bbel', 'bbelg', 'bbelm', 'bbelb', 'bbels', 'bbelt', 'bbelp', 'bbelh', 'bbem', 'bbeb', 'bbebs', 'bbes'];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '{Salla}', '{Qala}', 'Allah', 'Akbar', 'Mohammed', 'SL`M', 'Rasul', '{Alayhi}', '{WaSallam}', '{Salla}', '{Salla Llahu Alayhi WaSallam}', '{Jalla Jalalahu}', 'Rial ', '{Bismillah Ar-Rahman Ar-Rahimi}', '[?]', '[?]'];
<?php return [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '-', '-', '-', '-', '--', '--', '||', '_', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '+', '++', '*', '*>', '.', '..', '...', '.', "\n",
    "\n\n",
    '', '', '', '', '', ' ', '%0', '%00', '\'', '\'\'', '\'\'\'', '`', '``', '```', '^', '<', '>', '*', '!!', '!?', '-', '_', '-', '^', '***', '--', '/', '-[', ']-', '??', '?!', '!?', '7', 'PP', '(]', '[)', '*', '[?]', '[?]', '[?]', '%', '~', '[?]', '[?]', '[?]', "''''",    // 0x57
    '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ' ', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '0', 'i', '', '', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', 'n', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '=', '(', ')', '[?]', 'a', 'e', 'o', 'x', '[?]', 'h', 'k', 'l', 'm', 'n', 'p', 's', 't', '[?]', '[?]', '[?]', 'ECU', 'CL', 'Cr', 'Fr.', 'L.', 'mil', 'N', 'Pts', 'Rs', 'W', 'NS', 'D', 'EUR', 'K', 'T', 'Dr', 'Pf', 'P', 'G', 'A', 'UAH', 'C|', 'L', 'Sm', 'T', 'Rs', 'L', 'M', 'm', 'R', 'l', 'BTC', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ];
<?php return ['Ming ', 'Sheng ', 'Shi ', 'Yun ', 'Mian ', 'Pan ', 'Fang ', 'Miao ', 'Dan ', 'Mei ', 'Mao ', 'Kan ', 'Xian ', 'Ou ', 'Shi ', 'Yang ', 'Zheng ', 'Yao ', 'Shen ', 'Huo ', 'Da ', 'Zhen ', 'Kuang ', 'Ju ', 'Shen ', 'Chi ', 'Sheng ', 'Mei ', 'Mo ', 'Zhu ', 'Zhen ', 'Zhen ', 'Mian ', 'Di ', 'Yuan ', 'Die ', 'Yi ', 'Zi ', 'Zi ', 'Chao ', 'Zha ', 'Xuan ', 'Bing ', 'Mi ', 'Long ', 'Sui ', 'Dong ', 'Mi ', 'Die ', 'Yi ', 'Er ', 'Ming ', 'Xuan ', 'Chi ', 'Kuang ', 'Juan ', 'Mou ', 'Zhen ', 'Tiao ', 'Yang ', 'Yan ', 'Mo ', 'Zhong ', 'Mai ', 'Zhao ', 'Zheng ', 'Mei ', 'Jun ', 'Shao ', 'Han ', 'Huan ', 'Di ', 'Cheng ', 'Cuo ', 'Juan ', 'E ', 'Wan ', 'Xian ', 'Xi ', 'Kun ', 'Lai ', 'Jian ', 'Shan ', 'Tian ', 'Hun ', 'Wan ', 'Ling ', 'Shi ', 'Qiong ', 'Lie ', 'Yai ', 'Jing ', 'Zheng ', 'Li ', 'Lai ', 'Sui ', 'Juan ', 'Shui ', 'Sui ', 'Du ', 'Bi ', 'Bi ', 'Mu ', 'Hun ', 'Ni ', 'Lu ', 'Yi ', 'Jie ', 'Cai ', 'Zhou ', 'Yu ', 'Hun ', 'Ma ', 'Xia ', 'Xing ', 'Xi ', 'Gun ', 'Cai ', 'Chun ', 'Jian ', 'Mei ', 'Du ', 'Hou ', 'Xuan ', 'Ti ', 'Kui ', 'Gao ', 'Rui ', 'Mou ', 'Xu ', 'Fa ', 'Wen ', 'Miao ', 'Chou ', 'Kui ', 'Mi ', 'Weng ', 'Kou ', 'Dang ', 'Chen ', 'Ke ', 'Sou ', 'Xia ', 'Qiong ', 'Mao ', 'Ming ', 'Man ', 'Shui ', 'Ze ', 'Zhang ', 'Yi ', 'Diao ', 'Ou ', 'Mo ', 'Shun ', 'Cong ', 'Lou ', 'Chi ', 'Man ', 'Piao ', 'Cheng ', 'Ji ', 'Meng ', '[?] ', 'Run ', 'Pie ', 'Xi ', 'Qiao ', 'Pu ', 'Zhu ', 'Deng ', 'Shen ', 'Shun ', 'Liao ', 'Che ', 'Xian ', 'Kan ', 'Ye ', 'Xu ', 'Tong ', 'Mou ', 'Lin ', 'Kui ', 'Xian ', 'Ye ', 'Ai ', 'Hui ', 'Zhan ', 'Jian ', 'Gu ', 'Zhao ', 'Qu ', 'Wei ', 'Chou ', 'Sao ', 'Ning ', 'Xun ', 'Yao ', 'Huo ', 'Meng ', 'Mian ', 'Bin ', 'Mian ', 'Li ', 'Kuang ', 'Jue ', 'Xuan ', 'Mian ', 'Huo ', 'Lu ', 'Meng ', 'Long ', 'Guan ', 'Man ', 'Xi ', 'Chu ', 'Tang ', 'Kan ', 'Zhu ', 'Mao ', 'Jin ', 'Lin ', 'Yu ', 'Shuo ', 'Ce ', 'Jue ', 'Shi ', 'Yi ', 'Shen ', 'Zhi ', 'Hou ', 'Shen ', 'Ying ', 'Ju ', 'Zhou ', 'Jiao ', 'Cuo ', 'Duan ', 'Ai ', 'Jiao ', 'Zeng ', 'Huo ', 'Bai ', 'Shi ', 'Ding ', 'Qi ', 'Ji ', 'Zi ', 'Gan ', 'Wu ', 'Tuo ', 'Ku ', 'Qiang ', 'Xi ', 'Fan ', 'Kuang '];
<?php return ['nzup', 'nzurx', 'nzur', 'nzyt', 'nzyx', 'nzy', 'nzyp', 'nzyrx', 'nzyr', 'sit', 'six', 'si', 'sip', 'siex', 'sie', 'siep', 'sat', 'sax', 'sa', 'sap', 'suox', 'suo', 'suop', 'sot', 'sox', 'so', 'sop', 'sex', 'se', 'sep', 'sut', 'sux', 'su', 'sup', 'surx', 'sur', 'syt', 'syx', 'sy', 'syp', 'syrx', 'syr', 'ssit', 'ssix', 'ssi', 'ssip', 'ssiex', 'ssie', 'ssiep', 'ssat', 'ssax', 'ssa', 'ssap', 'ssot', 'ssox', 'sso', 'ssop', 'ssex', 'sse', 'ssep', 'ssut', 'ssux', 'ssu', 'ssup', 'ssyt', 'ssyx', 'ssy', 'ssyp', 'ssyrx', 'ssyr', 'zhat', 'zhax', 'zha', 'zhap', 'zhuox', 'zhuo', 'zhuop', 'zhot', 'zhox', 'zho', 'zhop', 'zhet', 'zhex', 'zhe', 'zhep', 'zhut', 'zhux', 'zhu', 'zhup', 'zhurx', 'zhur', 'zhyt', 'zhyx', 'zhy', 'zhyp', 'zhyrx', 'zhyr', 'chat', 'chax', 'cha', 'chap', 'chuot', 'chuox', 'chuo', 'chuop', 'chot', 'chox', 'cho', 'chop', 'chet', 'chex', 'che', 'chep', 'chux', 'chu', 'chup', 'churx', 'chur', 'chyt', 'chyx', 'chy', 'chyp', 'chyrx', 'chyr', 'rrax', 'rra', 'rruox', 'rruo', 'rrot', 'rrox', 'rro', 'rrop', 'rret', 'rrex', 'rre', 'rrep', 'rrut', 'rrux', 'rru', 'rrup', 'rrurx', 'rrur', 'rryt', 'rryx', 'rry', 'rryp', 'rryrx', 'rryr', 'nrat', 'nrax', 'nra', 'nrap', 'nrox', 'nro', 'nrop', 'nret', 'nrex', 'nre', 'nrep', 'nrut', 'nrux', 'nru', 'nrup', 'nrurx', 'nrur', 'nryt', 'nryx', 'nry', 'nryp', 'nryrx', 'nryr', 'shat', 'shax', 'sha', 'shap', 'shuox', 'shuo', 'shuop', 'shot', 'shox', 'sho', 'shop', 'shet', 'shex', 'she', 'shep', 'shut', 'shux', 'shu', 'shup', 'shurx', 'shur', 'shyt', 'shyx', 'shy', 'shyp', 'shyrx', 'shyr', 'rat', 'rax', 'ra', 'rap', 'ruox', 'ruo', 'ruop', 'rot', 'rox', 'ro', 'rop', 'rex', 're', 'rep', 'rut', 'rux', 'ru', 'rup', 'rurx', 'rur', 'ryt', 'ryx', 'ry', 'ryp', 'ryrx', 'ryr', 'jit', 'jix', 'ji', 'jip', 'jiet', 'jiex', 'jie', 'jiep', 'juot', 'juox', 'juo', 'juop', 'jot', 'jox', 'jo', 'jop', 'jut', 'jux', 'ju', 'jup', 'jurx', 'jur', 'jyt', 'jyx', 'jy', 'jyp', 'jyrx', 'jyr', 'qit', 'qix', 'qi', 'qip'];
<?php return ['Lu ', 'Mu ', 'Li ', 'Tong ', 'Rong ', 'Chang ', 'Pu ', 'Luo ', 'Zhan ', 'Sao ', 'Zhan ', 'Meng ', 'Luo ', 'Qu ', 'Die ', 'Shi ', 'Di ', 'Min ', 'Jue ', 'Mang ', 'Qi ', 'Pie ', 'Nai ', 'Qi ', 'Dao ', 'Xian ', 'Chuan ', 'Fen ', 'Ri ', 'Nei ', '[?] ', 'Fu ', 'Shen ', 'Dong ', 'Qing ', 'Qi ', 'Yin ', 'Xi ', 'Hai ', 'Yang ', 'An ', 'Ya ', 'Ke ', 'Qing ', 'Ya ', 'Dong ', 'Dan ', 'Lu ', 'Qing ', 'Yang ', 'Yun ', 'Yun ', 'Shui ', 'San ', 'Zheng ', 'Bing ', 'Yong ', 'Dang ', 'Shitamizu ', 'Le ', 'Ni ', 'Tun ', 'Fan ', 'Gui ', 'Ting ', 'Zhi ', 'Qiu ', 'Bin ', 'Ze ', 'Mian ', 'Cuan ', 'Hui ', 'Diao ', 'Yi ', 'Cha ', 'Zhuo ', 'Chuan ', 'Wan ', 'Fan ', 'Dai ', 'Xi ', 'Tuo ', 'Mang ', 'Qiu ', 'Qi ', 'Shan ', 'Pai ', 'Han ', 'Qian ', 'Wu ', 'Wu ', 'Xun ', 'Si ', 'Ru ', 'Gong ', 'Jiang ', 'Chi ', 'Wu ', 'Tsuchi ', '[?] ', 'Tang ', 'Zhi ', 'Chi ', 'Qian ', 'Mi ', 'Yu ', 'Wang ', 'Qing ', 'Jing ', 'Rui ', 'Jun ', 'Hong ', 'Tai ', 'Quan ', 'Ji ', 'Bian ', 'Bian ', 'Gan ', 'Wen ', 'Zhong ', 'Fang ', 'Xiong ', 'Jue ', 'Hang ', 'Niou ', 'Qi ', 'Fen ', 'Xu ', 'Xu ', 'Qin ', 'Yi ', 'Wo ', 'Yun ', 'Yuan ', 'Hang ', 'Yan ', 'Chen ', 'Chen ', 'Dan ', 'You ', 'Dun ', 'Hu ', 'Huo ', 'Qie ', 'Mu ', 'Rou ', 'Mei ', 'Ta ', 'Mian ', 'Wu ', 'Chong ', 'Tian ', 'Bi ', 'Sha ', 'Zhi ', 'Pei ', 'Pan ', 'Zhui ', 'Za ', 'Gou ', 'Liu ', 'Mei ', 'Ze ', 'Feng ', 'Ou ', 'Li ', 'Lun ', 'Cang ', 'Feng ', 'Wei ', 'Hu ', 'Mo ', 'Mei ', 'Shu ', 'Ju ', 'Zan ', 'Tuo ', 'Tuo ', 'Tuo ', 'He ', 'Li ', 'Mi ', 'Yi ', 'Fa ', 'Fei ', 'You ', 'Tian ', 'Zhi ', 'Zhao ', 'Gu ', 'Zhan ', 'Yan ', 'Si ', 'Kuang ', 'Jiong ', 'Ju ', 'Xie ', 'Qiu ', 'Yi ', 'Jia ', 'Zhong ', 'Quan ', 'Bo ', 'Hui ', 'Mi ', 'Ben ', 'Zhuo ', 'Chu ', 'Le ', 'You ', 'Gu ', 'Hong ', 'Gan ', 'Fa ', 'Mao ', 'Si ', 'Hu ', 'Ping ', 'Ci ', 'Fan ', 'Chi ', 'Su ', 'Ning ', 'Cheng ', 'Ling ', 'Pao ', 'Bo ', 'Qi ', 'Si ', 'Ni ', 'Ju ', 'Yue ', 'Zhu ', 'Sheng ', 'Lei ', 'Xuan ', 'Xue ', 'Fu ', 'Pan ', 'Min ', 'Tai ', 'Yang ', 'Ji ', 'Yong ', 'Guan ', 'Beng ', 'Xue ', 'Long ', 'Lu ', '[?] ', 'Bo ', 'Xie ', 'Po ', 'Ze ', 'Jing ', 'Yin '];
<?php return ['He ', 'Lan ', 'Biao ', 'Rong ', 'Li ', 'Mo ', 'Bao ', 'Ruo ', 'Lu ', 'La ', 'Ao ', 'Xun ', 'Kuang ', 'Shuo ', '[?] ', 'Li ', 'Lu ', 'Jue ', 'Liao ', 'Yan ', 'Xi ', 'Xie ', 'Long ', 'Ye ', '[?] ', 'Rang ', 'Yue ', 'Lan ', 'Cong ', 'Jue ', 'Tong ', 'Guan ', '[?] ', 'Che ', 'Mi ', 'Tang ', 'Lan ', 'Zhu ', '[?] ', 'Ling ', 'Cuan ', 'Yu ', 'Zhua ', 'Tsumekanmuri ', 'Pa ', 'Zheng ', 'Pao ', 'Cheng ', 'Yuan ', 'Ai ', 'Wei ', '[?] ', 'Jue ', 'Jue ', 'Fu ', 'Ye ', 'Ba ', 'Die ', 'Ye ', 'Yao ', 'Zu ', 'Shuang ', 'Er ', 'Qiang ', 'Chuang ', 'Ge ', 'Zang ', 'Die ', 'Qiang ', 'Yong ', 'Qiang ', 'Pian ', 'Ban ', 'Pan ', 'Shao ', 'Jian ', 'Pai ', 'Du ', 'Chuang ', 'Tou ', 'Zha ', 'Bian ', 'Die ', 'Bang ', 'Bo ', 'Chuang ', 'You ', '[?] ', 'Du ', 'Ya ', 'Cheng ', 'Niu ', 'Ushihen ', 'Pin ', 'Jiu ', 'Mou ', 'Tuo ', 'Mu ', 'Lao ', 'Ren ', 'Mang ', 'Fang ', 'Mao ', 'Mu ', 'Gang ', 'Wu ', 'Yan ', 'Ge ', 'Bei ', 'Si ', 'Jian ', 'Gu ', 'You ', 'Ge ', 'Sheng ', 'Mu ', 'Di ', 'Qian ', 'Quan ', 'Quan ', 'Zi ', 'Te ', 'Xi ', 'Mang ', 'Keng ', 'Qian ', 'Wu ', 'Gu ', 'Xi ', 'Li ', 'Li ', 'Pou ', 'Ji ', 'Gang ', 'Zhi ', 'Ben ', 'Quan ', 'Run ', 'Du ', 'Ju ', 'Jia ', 'Jian ', 'Feng ', 'Pian ', 'Ke ', 'Ju ', 'Kao ', 'Chu ', 'Xi ', 'Bei ', 'Luo ', 'Jie ', 'Ma ', 'San ', 'Wei ', 'Li ', 'Dun ', 'Tong ', '[?] ', 'Jiang ', 'Ikenie ', 'Li ', 'Du ', 'Lie ', 'Pi ', 'Piao ', 'Bao ', 'Xi ', 'Chou ', 'Wei ', 'Kui ', 'Chou ', 'Quan ', 'Fan ', 'Ba ', 'Fan ', 'Qiu ', 'Ji ', 'Cai ', 'Chuo ', 'An ', 'Jie ', 'Zhuang ', 'Guang ', 'Ma ', 'You ', 'Kang ', 'Bo ', 'Hou ', 'Ya ', 'Yin ', 'Huan ', 'Zhuang ', 'Yun ', 'Kuang ', 'Niu ', 'Di ', 'Qing ', 'Zhong ', 'Mu ', 'Bei ', 'Pi ', 'Ju ', 'Ni ', 'Sheng ', 'Pao ', 'Xia ', 'Tuo ', 'Hu ', 'Ling ', 'Fei ', 'Pi ', 'Ni ', 'Ao ', 'You ', 'Gou ', 'Yue ', 'Ju ', 'Dan ', 'Po ', 'Gu ', 'Xian ', 'Ning ', 'Huan ', 'Hen ', 'Jiao ', 'He ', 'Zhao ', 'Ji ', 'Xun ', 'Shan ', 'Ta ', 'Rong ', 'Shou ', 'Tong ', 'Lao ', 'Du ', 'Xia ', 'Shi ', 'Hua ', 'Zheng ', 'Yu ', 'Sun ', 'Yu ', 'Bi ', 'Mang ', 'Xi ', 'Juan ', 'Li ', 'Xia ', 'Yin ', 'Suan ', 'Lang ', 'Bei ', 'Zhi ', 'Yan '];
<?php return ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 26 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 52 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 78 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 104 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 130 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 156 => 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 181 => 'Z', 182 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 208 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 234 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
<?php return ['Yi ', 'Jun ', 'Nong ', 'Chan ', 'Yi ', 'Dang ', 'Jing ', 'Xuan ', 'Kuai ', 'Jian ', 'Chu ', 'Dan ', 'Jiao ', 'Sha ', 'Zai ', '[?] ', 'Bin ', 'An ', 'Ru ', 'Tai ', 'Chou ', 'Chai ', 'Lan ', 'Ni ', 'Jin ', 'Qian ', 'Meng ', 'Wu ', 'Ning ', 'Qiong ', 'Ni ', 'Chang ', 'Lie ', 'Lei ', 'Lu ', 'Kuang ', 'Bao ', 'Du ', 'Biao ', 'Zan ', 'Zhi ', 'Si ', 'You ', 'Hao ', 'Chen ', 'Chen ', 'Li ', 'Teng ', 'Wei ', 'Long ', 'Chu ', 'Chan ', 'Rang ', 'Shu ', 'Hui ', 'Li ', 'Luo ', 'Zan ', 'Nuo ', 'Tang ', 'Yan ', 'Lei ', 'Nang ', 'Er ', 'Wu ', 'Yun ', 'Zan ', 'Yuan ', 'Xiong ', 'Chong ', 'Zhao ', 'Xiong ', 'Xian ', 'Guang ', 'Dui ', 'Ke ', 'Dui ', 'Mian ', 'Tu ', 'Chang ', 'Er ', 'Dui ', 'Er ', 'Xin ', 'Tu ', 'Si ', 'Yan ', 'Yan ', 'Shi ', 'Shi ', 'Dang ', 'Qian ', 'Dou ', 'Fen ', 'Mao ', 'Shen ', 'Dou ', 'Bai ', 'Jing ', 'Li ', 'Huang ', 'Ru ', 'Wang ', 'Nei ', 'Quan ', 'Liang ', 'Yu ', 'Ba ', 'Gong ', 'Liu ', 'Xi ', '[?] ', 'Lan ', 'Gong ', 'Tian ', 'Guan ', 'Xing ', 'Bing ', 'Qi ', 'Ju ', 'Dian ', 'Zi ', 'Ppwun ', 'Yang ', 'Jian ', 'Shou ', 'Ji ', 'Yi ', 'Ji ', 'Chan ', 'Jiong ', 'Mao ', 'Ran ', 'Nei ', 'Yuan ', 'Mao ', 'Gang ', 'Ran ', 'Ce ', 'Jiong ', 'Ce ', 'Zai ', 'Gua ', 'Jiong ', 'Mao ', 'Zhou ', 'Mou ', 'Gou ', 'Xu ', 'Mian ', 'Mi ', 'Rong ', 'Yin ', 'Xie ', 'Kan ', 'Jun ', 'Nong ', 'Yi ', 'Mi ', 'Shi ', 'Guan ', 'Meng ', 'Zhong ', 'Ju ', 'Yuan ', 'Ming ', 'Kou ', 'Lam ', 'Fu ', 'Xie ', 'Mi ', 'Bing ', 'Dong ', 'Tai ', 'Gang ', 'Feng ', 'Bing ', 'Hu ', 'Chong ', 'Jue ', 'Hu ', 'Kuang ', 'Ye ', 'Leng ', 'Pan ', 'Fu ', 'Min ', 'Dong ', 'Xian ', 'Lie ', 'Xia ', 'Jian ', 'Jing ', 'Shu ', 'Mei ', 'Tu ', 'Qi ', 'Gu ', 'Zhun ', 'Song ', 'Jing ', 'Liang ', 'Qing ', 'Diao ', 'Ling ', 'Dong ', 'Gan ', 'Jian ', 'Yin ', 'Cou ', 'Yi ', 'Li ', 'Cang ', 'Ming ', 'Zhuen ', 'Cui ', 'Si ', 'Duo ', 'Jin ', 'Lin ', 'Lin ', 'Ning ', 'Xi ', 'Du ', 'Ji ', 'Fan ', 'Fan ', 'Fan ', 'Feng ', 'Ju ', 'Chu ', 'Tako ', 'Feng ', 'Mok ', 'Ci ', 'Fu ', 'Feng ', 'Ping ', 'Feng ', 'Kai ', 'Huang ', 'Kai ', 'Gan ', 'Deng ', 'Ping ', 'Qu ', 'Xiong ', 'Kuai ', 'Tu ', 'Ao ', 'Chu ', 'Ji ', 'Dang ', 'Han ', 'Han ', 'Zao '];
<?php return ['cyess', 'cyeng', 'cyej', 'cyec', 'cyek', 'cyet', 'cyep', 'cyeh', 'co', 'cog', 'cogg', 'cogs', 'con', 'conj', 'conh', 'cod', 'col', 'colg', 'colm', 'colb', 'cols', 'colt', 'colp', 'colh', 'com', 'cob', 'cobs', 'cos', 'coss', 'cong', 'coj', 'coc', 'cok', 'cot', 'cop', 'coh', 'cwa', 'cwag', 'cwagg', 'cwags', 'cwan', 'cwanj', 'cwanh', 'cwad', 'cwal', 'cwalg', 'cwalm', 'cwalb', 'cwals', 'cwalt', 'cwalp', 'cwalh', 'cwam', 'cwab', 'cwabs', 'cwas', 'cwass', 'cwang', 'cwaj', 'cwac', 'cwak', 'cwat', 'cwap', 'cwah', 'cwae', 'cwaeg', 'cwaegg', 'cwaegs', 'cwaen', 'cwaenj', 'cwaenh', 'cwaed', 'cwael', 'cwaelg', 'cwaelm', 'cwaelb', 'cwaels', 'cwaelt', 'cwaelp', 'cwaelh', 'cwaem', 'cwaeb', 'cwaebs', 'cwaes', 'cwaess', 'cwaeng', 'cwaej', 'cwaec', 'cwaek', 'cwaet', 'cwaep', 'cwaeh', 'coe', 'coeg', 'coegg', 'coegs', 'coen', 'coenj', 'coenh', 'coed', 'coel', 'coelg', 'coelm', 'coelb', 'coels', 'coelt', 'coelp', 'coelh', 'coem', 'coeb', 'coebs', 'coes', 'coess', 'coeng', 'coej', 'coec', 'coek', 'coet', 'coep', 'coeh', 'cyo', 'cyog', 'cyogg', 'cyogs', 'cyon', 'cyonj', 'cyonh', 'cyod', 'cyol', 'cyolg', 'cyolm', 'cyolb', 'cyols', 'cyolt', 'cyolp', 'cyolh', 'cyom', 'cyob', 'cyobs', 'cyos', 'cyoss', 'cyong', 'cyoj', 'cyoc', 'cyok', 'cyot', 'cyop', 'cyoh', 'cu', 'cug', 'cugg', 'cugs', 'cun', 'cunj', 'cunh', 'cud', 'cul', 'culg', 'culm', 'culb', 'culs', 'cult', 'culp', 'culh', 'cum', 'cub', 'cubs', 'cus', 'cuss', 'cung', 'cuj', 'cuc', 'cuk', 'cut', 'cup', 'cuh', 'cweo', 'cweog', 'cweogg', 'cweogs', 'cweon', 'cweonj', 'cweonh', 'cweod', 'cweol', 'cweolg', 'cweolm', 'cweolb', 'cweols', 'cweolt', 'cweolp', 'cweolh', 'cweom', 'cweob', 'cweobs', 'cweos', 'cweoss', 'cweong', 'cweoj', 'cweoc', 'cweok', 'cweot', 'cweop', 'cweoh', 'cwe', 'cweg', 'cwegg', 'cwegs', 'cwen', 'cwenj', 'cwenh', 'cwed', 'cwel', 'cwelg', 'cwelm', 'cwelb', 'cwels', 'cwelt', 'cwelp', 'cwelh', 'cwem', 'cweb', 'cwebs', 'cwes', 'cwess', 'cweng', 'cwej', 'cwec', 'cwek', 'cwet', 'cwep', 'cweh', 'cwi', 'cwig', 'cwigg', 'cwigs', 'cwin', 'cwinj', 'cwinh', 'cwid', 'cwil', 'cwilg', 'cwilm', 'cwilb', 'cwils', 'cwilt', 'cwilp', 'cwilh', 'cwim', 'cwib', 'cwibs', 'cwis', 'cwiss', 'cwing', 'cwij', 'cwic'];
<?php return ['nyaess', 'nyaeng', 'nyaej', 'nyaec', 'nyaek', 'nyaet', 'nyaep', 'nyaeh', 'neo', 'neog', 'neogg', 'neogs', 'neon', 'neonj', 'neonh', 'neod', 'neol', 'neolg', 'neolm', 'neolb', 'neols', 'neolt', 'neolp', 'neolh', 'neom', 'neob', 'neobs', 'neos', 'neoss', 'neong', 'neoj', 'neoc', 'neok', 'neot', 'neop', 'neoh', 'ne', 'neg', 'negg', 'negs', 'nen', 'nenj', 'nenh', 'ned', 'nel', 'nelg', 'nelm', 'nelb', 'nels', 'nelt', 'nelp', 'nelh', 'nem', 'neb', 'nebs', 'nes', 'ness', 'neng', 'nej', 'nec', 'nek', 'net', 'nep', 'neh', 'nyeo', 'nyeog', 'nyeogg', 'nyeogs', 'nyeon', 'nyeonj', 'nyeonh', 'nyeod', 'nyeol', 'nyeolg', 'nyeolm', 'nyeolb', 'nyeols', 'nyeolt', 'nyeolp', 'nyeolh', 'nyeom', 'nyeob', 'nyeobs', 'nyeos', 'nyeoss', 'nyeong', 'nyeoj', 'nyeoc', 'nyeok', 'nyeot', 'nyeop', 'nyeoh', 'nye', 'nyeg', 'nyegg', 'nyegs', 'nyen', 'nyenj', 'nyenh', 'nyed', 'nyel', 'nyelg', 'nyelm', 'nyelb', 'nyels', 'nyelt', 'nyelp', 'nyelh', 'nyem', 'nyeb', 'nyebs', 'nyes', 'nyess', 'nyeng', 'nyej', 'nyec', 'nyek', 'nyet', 'nyep', 'nyeh', 'no', 'nog', 'nogg', 'nogs', 'non', 'nonj', 'nonh', 'nod', 'nol', 'nolg', 'nolm', 'nolb', 'nols', 'nolt', 'nolp', 'nolh', 'nom', 'nob', 'nobs', 'nos', 'noss', 'nong', 'noj', 'noc', 'nok', 'not', 'nop', 'noh', 'nwa', 'nwag', 'nwagg', 'nwags', 'nwan', 'nwanj', 'nwanh', 'nwad', 'nwal', 'nwalg', 'nwalm', 'nwalb', 'nwals', 'nwalt', 'nwalp', 'nwalh', 'nwam', 'nwab', 'nwabs', 'nwas', 'nwass', 'nwang', 'nwaj', 'nwac', 'nwak', 'nwat', 'nwap', 'nwah', 'nwae', 'nwaeg', 'nwaegg', 'nwaegs', 'nwaen', 'nwaenj', 'nwaenh', 'nwaed', 'nwael', 'nwaelg', 'nwaelm', 'nwaelb', 'nwaels', 'nwaelt', 'nwaelp', 'nwaelh', 'nwaem', 'nwaeb', 'nwaebs', 'nwaes', 'nwaess', 'nwaeng', 'nwaej', 'nwaec', 'nwaek', 'nwaet', 'nwaep', 'nwaeh', 'noe', 'noeg', 'noegg', 'noegs', 'noen', 'noenj', 'noenh', 'noed', 'noel', 'noelg', 'noelm', 'noelb', 'noels', 'noelt', 'noelp', 'noelh', 'noem', 'noeb', 'noebs', 'noes', 'noess', 'noeng', 'noej', 'noec', 'noek', 'noet', 'noep', 'noeh', 'nyo', 'nyog', 'nyogg', 'nyogs', 'nyon', 'nyonj', 'nyonh', 'nyod', 'nyol', 'nyolg', 'nyolm', 'nyolb', 'nyols', 'nyolt', 'nyolp', 'nyolh', 'nyom', 'nyob', 'nyobs', 'nyos', 'nyoss', 'nyong', 'nyoj', 'nyoc'];
<?php return ['Qiao ', 'Chou ', 'Bei ', 'Xuan ', 'Wei ', 'Ge ', 'Qian ', 'Wei ', 'Yu ', 'Yu ', 'Bi ', 'Xuan ', 'Huan ', 'Min ', 'Bi ', 'Yi ', 'Mian ', 'Yong ', 'Kai ', 'Dang ', 'Yin ', 'E ', 'Chen ', 'Mou ', 'Ke ', 'Ke ', 'Yu ', 'Ai ', 'Qie ', 'Yan ', 'Nuo ', 'Gan ', 'Yun ', 'Zong ', 'Sai ', 'Leng ', 'Fen ', '[?] ', 'Kui ', 'Kui ', 'Que ', 'Gong ', 'Yun ', 'Su ', 'Su ', 'Qi ', 'Yao ', 'Song ', 'Huang ', 'Ji ', 'Gu ', 'Ju ', 'Chuang ', 'Ni ', 'Xie ', 'Kai ', 'Zheng ', 'Yong ', 'Cao ', 'Sun ', 'Shen ', 'Bo ', 'Kai ', 'Yuan ', 'Xie ', 'Hun ', 'Yong ', 'Yang ', 'Li ', 'Sao ', 'Tao ', 'Yin ', 'Ci ', 'Xu ', 'Qian ', 'Tai ', 'Huang ', 'Yun ', 'Shen ', 'Ming ', '[?] ', 'She ', 'Cong ', 'Piao ', 'Mo ', 'Mu ', 'Guo ', 'Chi ', 'Can ', 'Can ', 'Can ', 'Cui ', 'Min ', 'Te ', 'Zhang ', 'Tong ', 'Ao ', 'Shuang ', 'Man ', 'Guan ', 'Que ', 'Zao ', 'Jiu ', 'Hui ', 'Kai ', 'Lian ', 'Ou ', 'Song ', 'Jin ', 'Yin ', 'Lu ', 'Shang ', 'Wei ', 'Tuan ', 'Man ', 'Qian ', 'She ', 'Yong ', 'Qing ', 'Kang ', 'Di ', 'Zhi ', 'Lou ', 'Juan ', 'Qi ', 'Qi ', 'Yu ', 'Ping ', 'Liao ', 'Cong ', 'You ', 'Chong ', 'Zhi ', 'Tong ', 'Cheng ', 'Qi ', 'Qu ', 'Peng ', 'Bei ', 'Bie ', 'Chun ', 'Jiao ', 'Zeng ', 'Chi ', 'Lian ', 'Ping ', 'Kui ', 'Hui ', 'Qiao ', 'Cheng ', 'Yin ', 'Yin ', 'Xi ', 'Xi ', 'Dan ', 'Tan ', 'Duo ', 'Dui ', 'Dui ', 'Su ', 'Jue ', 'Ce ', 'Xiao ', 'Fan ', 'Fen ', 'Lao ', 'Lao ', 'Chong ', 'Han ', 'Qi ', 'Xian ', 'Min ', 'Jing ', 'Liao ', 'Wu ', 'Can ', 'Jue ', 'Cu ', 'Xian ', 'Tan ', 'Sheng ', 'Pi ', 'Yi ', 'Chu ', 'Xian ', 'Nao ', 'Dan ', 'Tan ', 'Jing ', 'Song ', 'Han ', 'Jiao ', 'Wai ', 'Huan ', 'Dong ', 'Qin ', 'Qin ', 'Qu ', 'Cao ', 'Ken ', 'Xie ', 'Ying ', 'Ao ', 'Mao ', 'Yi ', 'Lin ', 'Se ', 'Jun ', 'Huai ', 'Men ', 'Lan ', 'Ai ', 'Lin ', 'Yan ', 'Gua ', 'Xia ', 'Chi ', 'Yu ', 'Yin ', 'Dai ', 'Meng ', 'Ai ', 'Meng ', 'Dui ', 'Qi ', 'Mo ', 'Lan ', 'Men ', 'Chou ', 'Zhi ', 'Nuo ', 'Nuo ', 'Yan ', 'Yang ', 'Bo ', 'Zhi ', 'Kuang ', 'Kuang ', 'You ', 'Fu ', 'Liu ', 'Mie ', 'Cheng ', '[?] ', 'Chan ', 'Meng ', 'Lan ', 'Huai ', 'Xuan ', 'Rang ', 'Chan ', 'Ji ', 'Ju ', 'Huan ', 'She ', 'Yi '];
<?php return ['Yu ', 'Shui ', 'Shen ', 'Diao ', 'Chan ', 'Liang ', 'Zhun ', 'Sui ', 'Tan ', 'Shen ', 'Yi ', 'Mou ', 'Chen ', 'Die ', 'Huang ', 'Jian ', 'Xie ', 'Nue ', 'Ye ', 'Wei ', 'E ', 'Yu ', 'Xuan ', 'Chan ', 'Zi ', 'An ', 'Yan ', 'Di ', 'Mi ', 'Pian ', 'Xu ', 'Mo ', 'Dang ', 'Su ', 'Xie ', 'Yao ', 'Bang ', 'Shi ', 'Qian ', 'Mi ', 'Jin ', 'Man ', 'Zhe ', 'Jian ', 'Miu ', 'Tan ', 'Zen ', 'Qiao ', 'Lan ', 'Pu ', 'Jue ', 'Yan ', 'Qian ', 'Zhan ', 'Chen ', 'Gu ', 'Qian ', 'Hong ', 'Xia ', 'Jue ', 'Hong ', 'Han ', 'Hong ', 'Xi ', 'Xi ', 'Huo ', 'Liao ', 'Han ', 'Du ', 'Long ', 'Dou ', 'Jiang ', 'Qi ', 'Shi ', 'Li ', 'Deng ', 'Wan ', 'Bi ', 'Shu ', 'Xian ', 'Feng ', 'Zhi ', 'Zhi ', 'Yan ', 'Yan ', 'Shi ', 'Chu ', 'Hui ', 'Tun ', 'Yi ', 'Tun ', 'Yi ', 'Jian ', 'Ba ', 'Hou ', 'E ', 'Cu ', 'Xiang ', 'Huan ', 'Jian ', 'Ken ', 'Gai ', 'Qu ', 'Fu ', 'Xi ', 'Bin ', 'Hao ', 'Yu ', 'Zhu ', 'Jia ', '[?] ', 'Xi ', 'Bo ', 'Wen ', 'Huan ', 'Bin ', 'Di ', 'Zong ', 'Fen ', 'Yi ', 'Zhi ', 'Bao ', 'Chai ', 'Han ', 'Pi ', 'Na ', 'Pi ', 'Gou ', 'Na ', 'You ', 'Diao ', 'Mo ', 'Si ', 'Xiu ', 'Huan ', 'Kun ', 'He ', 'He ', 'Mo ', 'Han ', 'Mao ', 'Li ', 'Ni ', 'Bi ', 'Yu ', 'Jia ', 'Tuan ', 'Mao ', 'Pi ', 'Xi ', 'E ', 'Ju ', 'Mo ', 'Chu ', 'Tan ', 'Huan ', 'Jue ', 'Bei ', 'Zhen ', 'Yuan ', 'Fu ', 'Cai ', 'Gong ', 'Te ', 'Yi ', 'Hang ', 'Wan ', 'Pin ', 'Huo ', 'Fan ', 'Tan ', 'Guan ', 'Ze ', 'Zhi ', 'Er ', 'Zhu ', 'Shi ', 'Bi ', 'Zi ', 'Er ', 'Gui ', 'Pian ', 'Bian ', 'Mai ', 'Dai ', 'Sheng ', 'Kuang ', 'Fei ', 'Tie ', 'Yi ', 'Chi ', 'Mao ', 'He ', 'Bi ', 'Lu ', 'Ren ', 'Hui ', 'Gai ', 'Pian ', 'Zi ', 'Jia ', 'Xu ', 'Zei ', 'Jiao ', 'Gai ', 'Zang ', 'Jian ', 'Ying ', 'Xun ', 'Zhen ', 'She ', 'Bin ', 'Bin ', 'Qiu ', 'She ', 'Chuan ', 'Zang ', 'Zhou ', 'Lai ', 'Zan ', 'Si ', 'Chen ', 'Shang ', 'Tian ', 'Pei ', 'Geng ', 'Xian ', 'Mai ', 'Jian ', 'Sui ', 'Fu ', 'Tan ', 'Cong ', 'Cong ', 'Zhi ', 'Ji ', 'Zhang ', 'Du ', 'Jin ', 'Xiong ', 'Shun ', 'Yun ', 'Bao ', 'Zai ', 'Lai ', 'Feng ', 'Cang ', 'Ji ', 'Sheng ', 'Ai ', 'Zhuan ', 'Fu ', 'Gou ', 'Sai ', 'Ze ', 'Liao '];
<?php return ['pyuk', 'pyut', 'pyup', 'pyuh', 'peu', 'peug', 'peugg', 'peugs', 'peun', 'peunj', 'peunh', 'peud', 'peul', 'peulg', 'peulm', 'peulb', 'peuls', 'peult', 'peulp', 'peulh', 'peum', 'peub', 'peubs', 'peus', 'peuss', 'peung', 'peuj', 'peuc', 'peuk', 'peut', 'peup', 'peuh', 'pyi', 'pyig', 'pyigg', 'pyigs', 'pyin', 'pyinj', 'pyinh', 'pyid', 'pyil', 'pyilg', 'pyilm', 'pyilb', 'pyils', 'pyilt', 'pyilp', 'pyilh', 'pyim', 'pyib', 'pyibs', 'pyis', 'pyiss', 'pying', 'pyij', 'pyic', 'pyik', 'pyit', 'pyip', 'pyih', 'pi', 'pig', 'pigg', 'pigs', 'pin', 'pinj', 'pinh', 'pid', 'pil', 'pilg', 'pilm', 'pilb', 'pils', 'pilt', 'pilp', 'pilh', 'pim', 'pib', 'pibs', 'pis', 'piss', 'ping', 'pij', 'pic', 'pik', 'pit', 'pip', 'pih', 'ha', 'hag', 'hagg', 'hags', 'han', 'hanj', 'hanh', 'had', 'hal', 'halg', 'halm', 'halb', 'hals', 'halt', 'halp', 'halh', 'ham', 'hab', 'habs', 'has', 'hass', 'hang', 'haj', 'hac', 'hak', 'hat', 'hap', 'hah', 'hae', 'haeg', 'haegg', 'haegs', 'haen', 'haenj', 'haenh', 'haed', 'hael', 'haelg', 'haelm', 'haelb', 'haels', 'haelt', 'haelp', 'haelh', 'haem', 'haeb', 'haebs', 'haes', 'haess', 'haeng', 'haej', 'haec', 'haek', 'haet', 'haep', 'haeh', 'hya', 'hyag', 'hyagg', 'hyags', 'hyan', 'hyanj', 'hyanh', 'hyad', 'hyal', 'hyalg', 'hyalm', 'hyalb', 'hyals', 'hyalt', 'hyalp', 'hyalh', 'hyam', 'hyab', 'hyabs', 'hyas', 'hyass', 'hyang', 'hyaj', 'hyac', 'hyak', 'hyat', 'hyap', 'hyah', 'hyae', 'hyaeg', 'hyaegg', 'hyaegs', 'hyaen', 'hyaenj', 'hyaenh', 'hyaed', 'hyael', 'hyaelg', 'hyaelm', 'hyaelb', 'hyaels', 'hyaelt', 'hyaelp', 'hyaelh', 'hyaem', 'hyaeb', 'hyaebs', 'hyaes', 'hyaess', 'hyaeng', 'hyaej', 'hyaec', 'hyaek', 'hyaet', 'hyaep', 'hyaeh', 'heo', 'heog', 'heogg', 'heogs', 'heon', 'heonj', 'heonh', 'heod', 'heol', 'heolg', 'heolm', 'heolb', 'heols', 'heolt', 'heolp', 'heolh', 'heom', 'heob', 'heobs', 'heos', 'heoss', 'heong', 'heoj', 'heoc', 'heok', 'heot', 'heop', 'heoh', 'he', 'heg', 'hegg', 'hegs', 'hen', 'henj', 'henh', 'hed', 'hel', 'helg', 'helm', 'helb', 'hels', 'helt', 'help', 'helh', 'hem', 'heb', 'hebs', 'hes', 'hess', 'heng', 'hej', 'hec', 'hek', 'het', 'hep', 'heh'];
<?php return ['Chan ', 'Ge ', 'Lou ', 'Zong ', 'Geng ', 'Jiao ', 'Gou ', 'Qin ', 'Yong ', 'Que ', 'Chou ', 'Chi ', 'Zhan ', 'Sun ', 'Sun ', 'Bo ', 'Chu ', 'Rong ', 'Beng ', 'Cuo ', 'Sao ', 'Ke ', 'Yao ', 'Dao ', 'Zhi ', 'Nu ', 'Xie ', 'Jian ', 'Sou ', 'Qiu ', 'Gao ', 'Xian ', 'Shuo ', 'Sang ', 'Jin ', 'Mie ', 'E ', 'Chui ', 'Nuo ', 'Shan ', 'Ta ', 'Jie ', 'Tang ', 'Pan ', 'Ban ', 'Da ', 'Li ', 'Tao ', 'Hu ', 'Zhi ', 'Wa ', 'Xia ', 'Qian ', 'Wen ', 'Qiang ', 'Tian ', 'Zhen ', 'E ', 'Xi ', 'Nuo ', 'Quan ', 'Cha ', 'Zha ', 'Ge ', 'Wu ', 'En ', 'She ', 'Kang ', 'She ', 'Shu ', 'Bai ', 'Yao ', 'Bin ', 'Sou ', 'Tan ', 'Sa ', 'Chan ', 'Suo ', 'Liao ', 'Chong ', 'Chuang ', 'Guo ', 'Bing ', 'Feng ', 'Shuai ', 'Di ', 'Qi ', 'Sou ', 'Zhai ', 'Lian ', 'Tang ', 'Chi ', 'Guan ', 'Lu ', 'Luo ', 'Lou ', 'Zong ', 'Gai ', 'Hu ', 'Zha ', 'Chuang ', 'Tang ', 'Hua ', 'Cui ', 'Nai ', 'Mo ', 'Jiang ', 'Gui ', 'Ying ', 'Zhi ', 'Ao ', 'Zhi ', 'Nie ', 'Man ', 'Shan ', 'Kou ', 'Shu ', 'Suo ', 'Tuan ', 'Jiao ', 'Mo ', 'Mo ', 'Zhe ', 'Xian ', 'Keng ', 'Piao ', 'Jiang ', 'Yin ', 'Gou ', 'Qian ', 'Lue ', 'Ji ', 'Ying ', 'Jue ', 'Pie ', 'Pie ', 'Lao ', 'Dun ', 'Xian ', 'Ruan ', 'Kui ', 'Zan ', 'Yi ', 'Xun ', 'Cheng ', 'Cheng ', 'Sa ', 'Nao ', 'Heng ', 'Si ', 'Qian ', 'Huang ', 'Da ', 'Zun ', 'Nian ', 'Lin ', 'Zheng ', 'Hui ', 'Zhuang ', 'Jiao ', 'Ji ', 'Cao ', 'Dan ', 'Dan ', 'Che ', 'Bo ', 'Che ', 'Jue ', 'Xiao ', 'Liao ', 'Ben ', 'Fu ', 'Qiao ', 'Bo ', 'Cuo ', 'Zhuo ', 'Zhuan ', 'Tuo ', 'Pu ', 'Qin ', 'Dun ', 'Nian ', '[?] ', 'Xie ', 'Lu ', 'Jiao ', 'Cuan ', 'Ta ', 'Han ', 'Qiao ', 'Zhua ', 'Jian ', 'Gan ', 'Yong ', 'Lei ', 'Kuo ', 'Lu ', 'Shan ', 'Zhuo ', 'Ze ', 'Pu ', 'Chuo ', 'Ji ', 'Dang ', 'Suo ', 'Cao ', 'Qing ', 'Jing ', 'Huan ', 'Jie ', 'Qin ', 'Kuai ', 'Dan ', 'Xi ', 'Ge ', 'Pi ', 'Bo ', 'Ao ', 'Ju ', 'Ye ', '[?] ', 'Mang ', 'Sou ', 'Mi ', 'Ji ', 'Tai ', 'Zhuo ', 'Dao ', 'Xing ', 'Lan ', 'Ca ', 'Ju ', 'Ye ', 'Ru ', 'Ye ', 'Ye ', 'Ni ', 'Hu ', 'Ji ', 'Bin ', 'Ning ', 'Ge ', 'Zhi ', 'Jie ', 'Kuo ', 'Mo ', 'Jian ', 'Xie ', 'Lie ', 'Tan ', 'Bai ', 'Sou ', 'Lu ', 'Lue ', 'Rao ', 'Zhi '];
<?php return ['ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'mn', 'me', 'mi', 'vn', 'mkh', '[?]', '[?]', '[?]', '[?]', '[?]', 'yi', '', 'ay', '`', '', 'd', 'h', 'k', 'l', 'm', 'm', 't', '+', 'sh', 's', 'sh', 's', 'a', 'a', '', 'b', 'g', 'd', 'h', 'v', 'z', '[?]', 't', 'y', 'k', 'k', 'l', '[?]', 'l', '[?]', 'n', 'n', '[?]', 'p', 'p', '[?]', 'ts', 'ts', 'r', 'sh', 't', 'vo', 'b', 'k', 'p', 'l', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '', 'EUR',  // "\xc2\x80" => "\xe2\x82\xac" => EURO SIGN
    '', ',', 'f', ',,',   // "\xc2\x84" => "\xe2\x80\x9e" => DOUBLE LOW-9 QUOTATION MARK
    '...',  // "\xc2\x85" => "\xe2\x80\xa6" =>  HORIZONTAL ELLIPSIS
    '+', '++',   // "\xc2\x87" => "\xe2\x80\xa1" => DOUBLE DAGGER
    '^', '%0',   // "\xc2\x89" => "\xe2\x80\xb0" => PER MILLE SIGN
    'S', '<', 'OE',   // "\xc2\x8c" => "\xc5\x92" => LATIN CAPITAL LIGATURE OE
    '', 'Z', '', '', '\'',   // "\xc2\x91" => "\xe2\x80\x98" => LEFT SINGLE QUOTATION MARK
    '\'',   // "\xc2\x92" => "\xe2\x80\x99" => RIGHT SINGLE QUOTATION MARK
    '"', '"', '*', '-', '--',   // "\xc2\x97" => "\xe2\x80\x94" => EM DASH
    '~', 'tm', 's', '>', 'oe', '', 'z', 'Y', ' ', '!', 'C/', 'PS', '$?', 'Y=', '|', 'SS', '"', '(c)', 'a', '<<', '!', '', '(r)', '-', 'deg', '+-', '2', '3', '\'', 'u', 'P', '*', ',', '1', 'o', '>>', '1/4', '1/2', '3/4', '?', 'A', 'A', 'A', 'A', // Not "AE" - used in languages other than German
    'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', // Not "OE" - used in languages other than German
    'O', 'x', 'O', 'U', 'U', 'U', // Not "UE" - used in languages other than German
    'U', 'Y', 'Th', 'ss', 'a', 'a', 'a', 'a', // Not "ae" - used in languages other than German
    'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'd', 'n', 'o', 'o', 'o', 'o', // Not "oe" - used in languages other than German
    'o', '/', 'o', 'u', 'u', 'u', // Not "ue" - used in languages other than German
    'u', 'y', 'th', 'y', ];
<?php return ['Fou ', 'Yiao ', 'Jue ', 'Jue ', 'Pi ', 'Huan ', 'Zhen ', 'Bao ', 'Yan ', 'Ya ', 'Zheng ', 'Fang ', 'Feng ', 'Wen ', 'Ou ', 'Te ', 'Jia ', 'Nu ', 'Ling ', 'Mie ', 'Fu ', 'Tuo ', 'Wen ', 'Li ', 'Bian ', 'Zhi ', 'Ge ', 'Yuan ', 'Zi ', 'Qu ', 'Xiao ', 'Zhi ', 'Dan ', 'Ju ', 'You ', 'Gu ', 'Zhong ', 'Yu ', 'Yang ', 'Rong ', 'Ya ', 'Tie ', 'Yu ', 'Shigi ', 'Ying ', 'Zhui ', 'Wu ', 'Er ', 'Gua ', 'Ai ', 'Zhi ', 'Yan ', 'Heng ', 'Jiao ', 'Ji ', 'Lie ', 'Zhu ', 'Ren ', 'Yi ', 'Hong ', 'Luo ', 'Ru ', 'Mou ', 'Ge ', 'Ren ', 'Jiao ', 'Xiu ', 'Zhou ', 'Zhi ', 'Luo ', 'Chidori ', 'Toki ', 'Ten ', 'Luan ', 'Jia ', 'Ji ', 'Yu ', 'Huan ', 'Tuo ', 'Bu ', 'Wu ', 'Juan ', 'Yu ', 'Bo ', 'Xun ', 'Xun ', 'Bi ', 'Xi ', 'Jun ', 'Ju ', 'Tu ', 'Jing ', 'Ti ', 'E ', 'E ', 'Kuang ', 'Hu ', 'Wu ', 'Shen ', 'Lai ', 'Ikaruga ', 'Kakesu ', 'Lu ', 'Ping ', 'Shu ', 'Fu ', 'An ', 'Zhao ', 'Peng ', 'Qin ', 'Qian ', 'Bei ', 'Diao ', 'Lu ', 'Que ', 'Jian ', 'Ju ', 'Tu ', 'Ya ', 'Yuan ', 'Qi ', 'Li ', 'Ye ', 'Zhui ', 'Kong ', 'Zhui ', 'Kun ', 'Sheng ', 'Qi ', 'Jing ', 'Yi ', 'Yi ', 'Jing ', 'Zi ', 'Lai ', 'Dong ', 'Qi ', 'Chun ', 'Geng ', 'Ju ', 'Qu ', 'Isuka ', 'Kikuitadaki ', 'Ji ', 'Shu ', '[?] ', 'Chi ', 'Miao ', 'Rou ', 'An ', 'Qiu ', 'Ti ', 'Hu ', 'Ti ', 'E ', 'Jie ', 'Mao ', 'Fu ', 'Chun ', 'Tu ', 'Yan ', 'He ', 'Yuan ', 'Pian ', 'Yun ', 'Mei ', 'Hu ', 'Ying ', 'Dun ', 'Mu ', 'Ju ', 'Tsugumi ', 'Cang ', 'Fang ', 'Gu ', 'Ying ', 'Yuan ', 'Xuan ', 'Weng ', 'Shi ', 'He ', 'Chu ', 'Tang ', 'Xia ', 'Ruo ', 'Liu ', 'Ji ', 'Gu ', 'Jian ', 'Zhun ', 'Han ', 'Zi ', 'Zi ', 'Ni ', 'Yao ', 'Yan ', 'Ji ', 'Li ', 'Tian ', 'Kou ', 'Ti ', 'Ti ', 'Ni ', 'Tu ', 'Ma ', 'Jiao ', 'Gao ', 'Tian ', 'Chen ', 'Li ', 'Zhuan ', 'Zhe ', 'Ao ', 'Yao ', 'Yi ', 'Ou ', 'Chi ', 'Zhi ', 'Liao ', 'Rong ', 'Lou ', 'Bi ', 'Shuang ', 'Zhuo ', 'Yu ', 'Wu ', 'Jue ', 'Yin ', 'Quan ', 'Si ', 'Jiao ', 'Yi ', 'Hua ', 'Bi ', 'Ying ', 'Su ', 'Huang ', 'Fan ', 'Jiao ', 'Liao ', 'Yan ', 'Kao ', 'Jiu ', 'Xian ', 'Xian ', 'Tu ', 'Mai ', 'Zun ', 'Yu ', 'Ying ', 'Lu ', 'Tuan ', 'Xian ', 'Xue ', 'Yi ', 'Pi '];
<?php return ['Huai ', 'Tai ', 'Song ', 'Wu ', 'Ou ', 'Chang ', 'Chuang ', 'Ju ', 'Yi ', 'Bao ', 'Chao ', 'Min ', 'Pei ', 'Zuo ', 'Zen ', 'Yang ', 'Kou ', 'Ban ', 'Nu ', 'Nao ', 'Zheng ', 'Pa ', 'Bu ', 'Tie ', 'Gu ', 'Hu ', 'Ju ', 'Da ', 'Lian ', 'Si ', 'Chou ', 'Di ', 'Dai ', 'Yi ', 'Tu ', 'You ', 'Fu ', 'Ji ', 'Peng ', 'Xing ', 'Yuan ', 'Ni ', 'Guai ', 'Fu ', 'Xi ', 'Bi ', 'You ', 'Qie ', 'Xuan ', 'Cong ', 'Bing ', 'Huang ', 'Xu ', 'Chu ', 'Pi ', 'Xi ', 'Xi ', 'Tan ', 'Koraeru ', 'Zong ', 'Dui ', '[?] ', 'Ki ', 'Yi ', 'Chi ', 'Ren ', 'Xun ', 'Shi ', 'Xi ', 'Lao ', 'Heng ', 'Kuang ', 'Mu ', 'Zhi ', 'Xie ', 'Lian ', 'Tiao ', 'Huang ', 'Die ', 'Hao ', 'Kong ', 'Gui ', 'Heng ', 'Xi ', 'Xiao ', 'Shu ', 'S ', 'Kua ', 'Qiu ', 'Yang ', 'Hui ', 'Hui ', 'Chi ', 'Jia ', 'Yi ', 'Xiong ', 'Guai ', 'Lin ', 'Hui ', 'Zi ', 'Xu ', 'Chi ', 'Xiang ', 'Nu ', 'Hen ', 'En ', 'Ke ', 'Tong ', 'Tian ', 'Gong ', 'Quan ', 'Xi ', 'Qia ', 'Yue ', 'Peng ', 'Ken ', 'De ', 'Hui ', 'E ', 'Kyuu ', 'Tong ', 'Yan ', 'Kai ', 'Ce ', 'Nao ', 'Yun ', 'Mang ', 'Yong ', 'Yong ', 'Yuan ', 'Pi ', 'Kun ', 'Qiao ', 'Yue ', 'Yu ', 'Yu ', 'Jie ', 'Xi ', 'Zhe ', 'Lin ', 'Ti ', 'Han ', 'Hao ', 'Qie ', 'Ti ', 'Bu ', 'Yi ', 'Qian ', 'Hui ', 'Xi ', 'Bei ', 'Man ', 'Yi ', 'Heng ', 'Song ', 'Quan ', 'Cheng ', 'Hui ', 'Wu ', 'Wu ', 'You ', 'Li ', 'Liang ', 'Huan ', 'Cong ', 'Yi ', 'Yue ', 'Li ', 'Nin ', 'Nao ', 'E ', 'Que ', 'Xuan ', 'Qian ', 'Wu ', 'Min ', 'Cong ', 'Fei ', 'Bei ', 'Duo ', 'Cui ', 'Chang ', 'Men ', 'Li ', 'Ji ', 'Guan ', 'Guan ', 'Xing ', 'Dao ', 'Qi ', 'Kong ', 'Tian ', 'Lun ', 'Xi ', 'Kan ', 'Kun ', 'Ni ', 'Qing ', 'Chou ', 'Dun ', 'Guo ', 'Chan ', 'Liang ', 'Wan ', 'Yuan ', 'Jin ', 'Ji ', 'Lin ', 'Yu ', 'Huo ', 'He ', 'Quan ', 'Tan ', 'Ti ', 'Ti ', 'Nie ', 'Wang ', 'Chuo ', 'Bu ', 'Hun ', 'Xi ', 'Tang ', 'Xin ', 'Wei ', 'Hui ', 'E ', 'Rui ', 'Zong ', 'Jian ', 'Yong ', 'Dian ', 'Ju ', 'Can ', 'Cheng ', 'De ', 'Bei ', 'Qie ', 'Can ', 'Dan ', 'Guan ', 'Duo ', 'Nao ', 'Yun ', 'Xiang ', 'Zhui ', 'Die ', 'Huang ', 'Chun ', 'Qiong ', 'Re ', 'Xing ', 'Ce ', 'Bian ', 'Hun ', 'Zong ', 'Ti '];
<?php return ['ggwem', 'ggweb', 'ggwebs', 'ggwes', 'ggwess', 'ggweng', 'ggwej', 'ggwec', 'ggwek', 'ggwet', 'ggwep', 'ggweh', 'ggwi', 'ggwig', 'ggwigg', 'ggwigs', 'ggwin', 'ggwinj', 'ggwinh', 'ggwid', 'ggwil', 'ggwilg', 'ggwilm', 'ggwilb', 'ggwils', 'ggwilt', 'ggwilp', 'ggwilh', 'ggwim', 'ggwib', 'ggwibs', 'ggwis', 'ggwiss', 'ggwing', 'ggwij', 'ggwic', 'ggwik', 'ggwit', 'ggwip', 'ggwih', 'ggyu', 'ggyug', 'ggyugg', 'ggyugs', 'ggyun', 'ggyunj', 'ggyunh', 'ggyud', 'ggyul', 'ggyulg', 'ggyulm', 'ggyulb', 'ggyuls', 'ggyult', 'ggyulp', 'ggyulh', 'ggyum', 'ggyub', 'ggyubs', 'ggyus', 'ggyuss', 'ggyung', 'ggyuj', 'ggyuc', 'ggyuk', 'ggyut', 'ggyup', 'ggyuh', 'ggeu', 'ggeug', 'ggeugg', 'ggeugs', 'ggeun', 'ggeunj', 'ggeunh', 'ggeud', 'ggeul', 'ggeulg', 'ggeulm', 'ggeulb', 'ggeuls', 'ggeult', 'ggeulp', 'ggeulh', 'ggeum', 'ggeub', 'ggeubs', 'ggeus', 'ggeuss', 'ggeung', 'ggeuj', 'ggeuc', 'ggeuk', 'ggeut', 'ggeup', 'ggeuh', 'ggyi', 'ggyig', 'ggyigg', 'ggyigs', 'ggyin', 'ggyinj', 'ggyinh', 'ggyid', 'ggyil', 'ggyilg', 'ggyilm', 'ggyilb', 'ggyils', 'ggyilt', 'ggyilp', 'ggyilh', 'ggyim', 'ggyib', 'ggyibs', 'ggyis', 'ggyiss', 'ggying', 'ggyij', 'ggyic', 'ggyik', 'ggyit', 'ggyip', 'ggyih', 'ggi', 'ggig', 'ggigg', 'ggigs', 'ggin', 'gginj', 'gginh', 'ggid', 'ggil', 'ggilg', 'ggilm', 'ggilb', 'ggils', 'ggilt', 'ggilp', 'ggilh', 'ggim', 'ggib', 'ggibs', 'ggis', 'ggiss', 'gging', 'ggij', 'ggic', 'ggik', 'ggit', 'ggip', 'ggih', 'na', 'nag', 'nagg', 'nags', 'nan', 'nanj', 'nanh', 'nad', 'nal', 'nalg', 'nalm', 'nalb', 'nals', 'nalt', 'nalp', 'nalh', 'nam', 'nab', 'nabs', 'nas', 'nass', 'nang', 'naj', 'nac', 'nak', 'nat', 'nap', 'nah', 'nae', 'naeg', 'naegg', 'naegs', 'naen', 'naenj', 'naenh', 'naed', 'nael', 'naelg', 'naelm', 'naelb', 'naels', 'naelt', 'naelp', 'naelh', 'naem', 'naeb', 'naebs', 'naes', 'naess', 'naeng', 'naej', 'naec', 'naek', 'naet', 'naep', 'naeh', 'nya', 'nyag', 'nyagg', 'nyags', 'nyan', 'nyanj', 'nyanh', 'nyad', 'nyal', 'nyalg', 'nyalm', 'nyalb', 'nyals', 'nyalt', 'nyalp', 'nyalh', 'nyam', 'nyab', 'nyabs', 'nyas', 'nyass', 'nyang', 'nyaj', 'nyac', 'nyak', 'nyat', 'nyap', 'nyah', 'nyae', 'nyaeg', 'nyaegg', 'nyaegs', 'nyaen', 'nyaenj', 'nyaenh', 'nyaed', 'nyael', 'nyaelg', 'nyaelm', 'nyaelb', 'nyaels', 'nyaelt', 'nyaelp', 'nyaelh', 'nyaem', 'nyaeb', 'nyaebs', 'nyaes'];
<?php

return [
    0 => 'w', 'x', 'y', 'z', 4 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 30 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 56 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 82 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 108 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 134 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 160 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 186 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 212 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 238 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ];
<?php return ['Kai ', 'Bian ', 'Yi ', 'Qi ', 'Nong ', 'Fen ', 'Ju ', 'Yan ', 'Yi ', 'Zang ', 'Bi ', 'Yi ', 'Yi ', 'Er ', 'San ', 'Shi ', 'Er ', 'Shi ', 'Shi ', 'Gong ', 'Diao ', 'Yin ', 'Hu ', 'Fu ', 'Hong ', 'Wu ', 'Tui ', 'Chi ', 'Jiang ', 'Ba ', 'Shen ', 'Di ', 'Zhang ', 'Jue ', 'Tao ', 'Fu ', 'Di ', 'Mi ', 'Xian ', 'Hu ', 'Chao ', 'Nu ', 'Jing ', 'Zhen ', 'Yi ', 'Mi ', 'Quan ', 'Wan ', 'Shao ', 'Ruo ', 'Xuan ', 'Jing ', 'Dun ', 'Zhang ', 'Jiang ', 'Qiang ', 'Peng ', 'Dan ', 'Qiang ', 'Bi ', 'Bi ', 'She ', 'Dan ', 'Jian ', 'Gou ', 'Sei ', 'Fa ', 'Bi ', 'Kou ', 'Nagi ', 'Bie ', 'Xiao ', 'Dan ', 'Kuo ', 'Qiang ', 'Hong ', 'Mi ', 'Kuo ', 'Wan ', 'Jue ', 'Ji ', 'Ji ', 'Gui ', 'Dang ', 'Lu ', 'Lu ', 'Tuan ', 'Hui ', 'Zhi ', 'Hui ', 'Hui ', 'Yi ', 'Yi ', 'Yi ', 'Yi ', 'Huo ', 'Huo ', 'Shan ', 'Xing ', 'Wen ', 'Tong ', 'Yan ', 'Yan ', 'Yu ', 'Chi ', 'Cai ', 'Biao ', 'Diao ', 'Bin ', 'Peng ', 'Yong ', 'Piao ', 'Zhang ', 'Ying ', 'Chi ', 'Chi ', 'Zhuo ', 'Tuo ', 'Ji ', 'Pang ', 'Zhong ', 'Yi ', 'Wang ', 'Che ', 'Bi ', 'Chi ', 'Ling ', 'Fu ', 'Wang ', 'Zheng ', 'Cu ', 'Wang ', 'Jing ', 'Dai ', 'Xi ', 'Xun ', 'Hen ', 'Yang ', 'Huai ', 'Lu ', 'Hou ', 'Wa ', 'Cheng ', 'Zhi ', 'Xu ', 'Jing ', 'Tu ', 'Cong ', '[?] ', 'Lai ', 'Cong ', 'De ', 'Pai ', 'Xi ', '[?] ', 'Qi ', 'Chang ', 'Zhi ', 'Cong ', 'Zhou ', 'Lai ', 'Yu ', 'Xie ', 'Jie ', 'Jian ', 'Chi ', 'Jia ', 'Bian ', 'Huang ', 'Fu ', 'Xun ', 'Wei ', 'Pang ', 'Yao ', 'Wei ', 'Xi ', 'Zheng ', 'Piao ', 'Chi ', 'De ', 'Zheng ', 'Zheng ', 'Bie ', 'De ', 'Chong ', 'Che ', 'Jiao ', 'Wei ', 'Jiao ', 'Hui ', 'Mei ', 'Long ', 'Xiang ', 'Bao ', 'Qu ', 'Xin ', 'Shu ', 'Bi ', 'Yi ', 'Le ', 'Ren ', 'Dao ', 'Ding ', 'Gai ', 'Ji ', 'Ren ', 'Ren ', 'Chan ', 'Tan ', 'Te ', 'Te ', 'Gan ', 'Qi ', 'Shi ', 'Cun ', 'Zhi ', 'Wang ', 'Mang ', 'Xi ', 'Fan ', 'Ying ', 'Tian ', 'Min ', 'Min ', 'Zhong ', 'Chong ', 'Wu ', 'Ji ', 'Wu ', 'Xi ', 'Ye ', 'You ', 'Wan ', 'Cong ', 'Zhong ', 'Kuai ', 'Yu ', 'Bian ', 'Zhi ', 'Qi ', 'Cui ', 'Chen ', 'Tai ', 'Tun ', 'Qian ', 'Nian ', 'Hun ', 'Xiong ', 'Niu ', 'Wang ', 'Xian ', 'Xin ', 'Kang ', 'Hu ', 'Kai ', 'Fen '];
<?php return [' @ ', ' ... ', ', ', '. ', ': ', ' // ', '', '-', ', ', '. ', '', '', '', '', '', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'a', 'e', 'i', 'o', 'u', 'O', 'U', 'ee', 'n', 'ng', 'b', 'p', 'q', 'g', 'm', 'l', 's', 'sh', 't', 'd', 'ch', 'j', 'y', 'r', 'w', 'f', 'k', 'kha', 'ts', 'z', 'h', 'zr', 'lh', 'zh', 'ch', '-', 'e', 'i', 'o', 'u', 'O', 'U', 'ng', 'b', 'p', 'q', 'g', 'm', 't', 'd', 'ch', 'j', 'ts', 'y', 'w', 'k', 'g', 'h', 'jy', 'ny', 'dz', 'e', 'i', 'iy', 'U', 'u', 'ng', 'k', 'g', 'h', 'p', 'sh', 't', 'd', 'j', 'f', 'g', 'h', 'ts', 'z', 'r', 'ch', 'zh', 'i', 'k', 'r', 'f', 'zh', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'H', 'X', 'W', 'M', ' 3 ', ' 333 ', 'a', 'i', 'k', 'ng', 'c', 'tt', 'tth', 'dd', 'nn', 't', 'd', 'p', 'ph', 'ss', 'zh', 'z', 'a', 't', 'zh', 'gh', 'ng', 'c', 'jh', 'tta', 'ddh', 't', 'dh', 'ss', 'cy', 'zh', 'z', 'u', 'y', 'bh', '\'', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php

return [
    'uz'                => 0,
    'tk'                => 1,
    'th'                => 0,
    'ps'                => 0,
    'or'                => 0,
    'mn'                => 0,
    'ko'                => 0,
    'ky'                => 0,
    'hy'                => 1,
    'bn'                => 5,
    'be'                => 0,
    'am'                => 0,
    'ja'                => 0,
    'zh'                => 0,
    'nl'                => 1,
    'it'                => 1,
    'mk'                => 1,
    'pt'                => 1,
    'el__greeklish'     => 2,
    'el'                => 2,
    'hi'                => 2,
    'sv'                => 1,
    'tr'                => 1,
    'bg'                => 2,
    'hu'                => 1,
    'my'                => 5,
    'hr'                => 2,
    'fi'                => 1,
    'ka'                => 1,
    'ru'                => 1,
    'ru__gost_2000_b'   => 1,
    'ru__passport_2013' => 1,
    'uk'                => 1,
    'kk'                => 1,
    'cs'                => 1,
    'da'                => 1,
    'pl'                => 1,
    'ro'                => 1,
    'eo'                => 1,
    'et'                => 1,
    'lv'                => 1,
    'lt'                => 1,
    'no'                => 1,
    'vi'                => 1,
    'ar'                => 1,
    'fa'                => 1,
    'sr'                => 1,
    'sr__cyr'           => 1,
    'sr__lat'           => 1,
    'az'                => 1,
    'sk'                => 1,
    'fr'                => 1,
    'fr_at'             => 1,
    'fr_ch'             => 1,
    'de'                => 1,
    'de_at'             => 1,
    'de_ch'             => 1,
    'en'                => 0,
    'latin'             => 3,
    ' '                 => 1,
    'msword'            => 1,
];
<?php return [' ', ', ', '. ', '"', '[JIS]', '"', '/', '0', '<', '> ', '<<', '>> ', '[', '] ', '{', '} ', '[(', ')] ', '@', 'X ', '[', '] ', '[[', ']] ', '((', ')) ', '[[', ']] ', '~ ', '``', '\'\'', ',,', '@', '1', '2', '3', '4', '5', '6', '7', '8', '9', '', '', '', '', '', '', '~', '+', '+', '+', '+', '', '@', ' // ', '+10+', '+20+', '+30+', '[?]', '[?]', '[?]', '', '', '[?]', 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'shi',   // 0x57
    'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', 'da', 'chi',   // 0x61
    'di', 'tsu',   // 0x63
    'tsu',   // 0x64
    'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', 'wi', 'we', 'wo', 'n', 'vu', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '"', '"', '[?]', '[?]', 'a', 'a', 'i', 'i', 'u', 'u', 'e', 'e', 'o', 'o', 'ka', 'ga', 'ki', 'gi', 'ku', 'gu', 'ke', 'ge', 'ko', 'go', 'sa', 'za', 'shi',   // 0xb7
    'zi', 'su', 'zu', 'se', 'ze', 'so', 'zo', 'ta', 'da', 'chi',   // 0xc1
    'di', 'tsu',   // 0xc3
    'tsu',   // 0xc4
    'du', 'te', 'de', 'to', 'do', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'ba', 'pa', 'hi', 'bi', 'pi', 'hu', 'bu', 'pu', 'he', 'be', 'pe', 'ho', 'bo', 'po', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'ya', 'yu', 'yu', 'yo', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wa', 'wi', 'we', 'wo', 'n', 'vu', 'ka', 'ke', 'va', 'vi', 've', 'vo', '', '', '"', '"', ];
<?php return ['A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', 'R', 'r', 'R', 'r', 'U', 'u', 'U', 'u', 'S', 's', 'T', 't', 'Y', 'y', 'H', 'h', 'N', 'd', 'OU', 'ou', 'Z', 'z', 'A', 'a', 'E', 'e', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'Y', 'y', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', '[?]', '[?]', 'B', 'U', '^', 'E', 'e', 'J', 'j', 'q', 'q', 'R', 'r', 'Y', 'y', 'a', 'a', 'a', 'b', 'o', 'c', 'd', 'd', 'e', '@', '@', 'e', 'e', 'e', 'e', 'j', 'g', 'g', 'g', 'g', 'u', 'Y', 'h', 'h', 'i', 'i', 'I', 'l', 'l', 'l', 'lZ', 'W', 'W', 'm', 'n', 'n', 'n', 'o', 'OE', 'O', 'F', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'R', 'R', 's', 'S', 'j', 'S', 'S', 't', 't', 'u', 'U', 'v', '^', 'w', 'y', 'Y', 'z', 'z', 'Z', 'Z', '?', '?', '?', 'C', '@', 'B', 'E', 'G', 'H', 'j', 'k', 'L', 'q', '?', '?', 'dz', 'dZ', 'dz', 'ts', 'tS', 'tC', 'fN', 'ls', 'lz', 'WW', ']]', 'h', 'h', 'h', 'h', 'j', 'r', 'r', 'r', 'r', 'w', 'y', '\'', '"', '`', '\'', '`', '`', '\'', '?', '?', '<', '>', '^', 'V', '^', 'V', '\'', '-', '/', '\\', ',', '_', '\\', '/', ':', '.', '`', '\'', '^', 'V', '+', '-', 'V', '.', '@', ',', '~', '"', 'R', 'X', 'G', 'l', 's', 'x', '?', '', '', '', '', '', '', '', 'V', '=', '"', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['nyok', 'nyot', 'nyop', 'nyoh', 'nu', 'nug', 'nugg', 'nugs', 'nun', 'nunj', 'nunh', 'nud', 'nul', 'nulg', 'nulm', 'nulb', 'nuls', 'nult', 'nulp', 'nulh', 'num', 'nub', 'nubs', 'nus', 'nuss', 'nung', 'nuj', 'nuc', 'nuk', 'nut', 'nup', 'nuh', 'nweo', 'nweog', 'nweogg', 'nweogs', 'nweon', 'nweonj', 'nweonh', 'nweod', 'nweol', 'nweolg', 'nweolm', 'nweolb', 'nweols', 'nweolt', 'nweolp', 'nweolh', 'nweom', 'nweob', 'nweobs', 'nweos', 'nweoss', 'nweong', 'nweoj', 'nweoc', 'nweok', 'nweot', 'nweop', 'nweoh', 'nwe', 'nweg', 'nwegg', 'nwegs', 'nwen', 'nwenj', 'nwenh', 'nwed', 'nwel', 'nwelg', 'nwelm', 'nwelb', 'nwels', 'nwelt', 'nwelp', 'nwelh', 'nwem', 'nweb', 'nwebs', 'nwes', 'nwess', 'nweng', 'nwej', 'nwec', 'nwek', 'nwet', 'nwep', 'nweh', 'nwi', 'nwig', 'nwigg', 'nwigs', 'nwin', 'nwinj', 'nwinh', 'nwid', 'nwil', 'nwilg', 'nwilm', 'nwilb', 'nwils', 'nwilt', 'nwilp', 'nwilh', 'nwim', 'nwib', 'nwibs', 'nwis', 'nwiss', 'nwing', 'nwij', 'nwic', 'nwik', 'nwit', 'nwip', 'nwih', 'nyu', 'nyug', 'nyugg', 'nyugs', 'nyun', 'nyunj', 'nyunh', 'nyud', 'nyul', 'nyulg', 'nyulm', 'nyulb', 'nyuls', 'nyult', 'nyulp', 'nyulh', 'nyum', 'nyub', 'nyubs', 'nyus', 'nyuss', 'nyung', 'nyuj', 'nyuc', 'nyuk', 'nyut', 'nyup', 'nyuh', 'neu', 'neug', 'neugg', 'neugs', 'neun', 'neunj', 'neunh', 'neud', 'neul', 'neulg', 'neulm', 'neulb', 'neuls', 'neult', 'neulp', 'neulh', 'neum', 'neub', 'neubs', 'neus', 'neuss', 'neung', 'neuj', 'neuc', 'neuk', 'neut', 'neup', 'neuh', 'nyi', 'nyig', 'nyigg', 'nyigs', 'nyin', 'nyinj', 'nyinh', 'nyid', 'nyil', 'nyilg', 'nyilm', 'nyilb', 'nyils', 'nyilt', 'nyilp', 'nyilh', 'nyim', 'nyib', 'nyibs', 'nyis', 'nyiss', 'nying', 'nyij', 'nyic', 'nyik', 'nyit', 'nyip', 'nyih', 'ni', 'nig', 'nigg', 'nigs', 'nin', 'ninj', 'ninh', 'nid', 'nil', 'nilg', 'nilm', 'nilb', 'nils', 'nilt', 'nilp', 'nilh', 'nim', 'nib', 'nibs', 'nis', 'niss', 'ning', 'nij', 'nic', 'nik', 'nit', 'nip', 'nih', 'da', 'dag', 'dagg', 'dags', 'dan', 'danj', 'danh', 'dad', 'dal', 'dalg', 'dalm', 'dalb', 'dals', 'dalt', 'dalp', 'dalh', 'dam', 'dab', 'dabs', 'das', 'dass', 'dang', 'daj', 'dac', 'dak', 'dat', 'dap', 'dah'];
<?php return ['Chey ', 'Thak ', 'Thak ', 'Thang ', 'Thayk ', 'Thong ', 'Pho ', 'Phok ', 'Hang ', 'Hang ', 'Hyen ', 'Hwak ', 'Wu ', 'Huo ', '[?] ', '[?] ', 'Zhong ', '[?] ', 'Qing ', '[?] ', '[?] ', 'Xi ', 'Zhu ', 'Yi ', 'Li ', 'Shen ', 'Xiang ', 'Fu ', 'Jing ', 'Jing ', 'Yu ', '[?] ', 'Hagi ', '[?] ', 'Zhu ', '[?] ', '[?] ', 'Yi ', 'Du ', '[?] ', '[?] ', '[?] ', 'Fan ', 'Si ', 'Guan ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['toels', 'toelt', 'toelp', 'toelh', 'toem', 'toeb', 'toebs', 'toes', 'toess', 'toeng', 'toej', 'toec', 'toek', 'toet', 'toep', 'toeh', 'tyo', 'tyog', 'tyogg', 'tyogs', 'tyon', 'tyonj', 'tyonh', 'tyod', 'tyol', 'tyolg', 'tyolm', 'tyolb', 'tyols', 'tyolt', 'tyolp', 'tyolh', 'tyom', 'tyob', 'tyobs', 'tyos', 'tyoss', 'tyong', 'tyoj', 'tyoc', 'tyok', 'tyot', 'tyop', 'tyoh', 'tu', 'tug', 'tugg', 'tugs', 'tun', 'tunj', 'tunh', 'tud', 'tul', 'tulg', 'tulm', 'tulb', 'tuls', 'tult', 'tulp', 'tulh', 'tum', 'tub', 'tubs', 'tus', 'tuss', 'tung', 'tuj', 'tuc', 'tuk', 'tut', 'tup', 'tuh', 'tweo', 'tweog', 'tweogg', 'tweogs', 'tweon', 'tweonj', 'tweonh', 'tweod', 'tweol', 'tweolg', 'tweolm', 'tweolb', 'tweols', 'tweolt', 'tweolp', 'tweolh', 'tweom', 'tweob', 'tweobs', 'tweos', 'tweoss', 'tweong', 'tweoj', 'tweoc', 'tweok', 'tweot', 'tweop', 'tweoh', 'twe', 'tweg', 'twegg', 'twegs', 'twen', 'twenj', 'twenh', 'twed', 'twel', 'twelg', 'twelm', 'twelb', 'twels', 'twelt', 'twelp', 'twelh', 'twem', 'tweb', 'twebs', 'twes', 'twess', 'tweng', 'twej', 'twec', 'twek', 'twet', 'twep', 'tweh', 'twi', 'twig', 'twigg', 'twigs', 'twin', 'twinj', 'twinh', 'twid', 'twil', 'twilg', 'twilm', 'twilb', 'twils', 'twilt', 'twilp', 'twilh', 'twim', 'twib', 'twibs', 'twis', 'twiss', 'twing', 'twij', 'twic', 'twik', 'twit', 'twip', 'twih', 'tyu', 'tyug', 'tyugg', 'tyugs', 'tyun', 'tyunj', 'tyunh', 'tyud', 'tyul', 'tyulg', 'tyulm', 'tyulb', 'tyuls', 'tyult', 'tyulp', 'tyulh', 'tyum', 'tyub', 'tyubs', 'tyus', 'tyuss', 'tyung', 'tyuj', 'tyuc', 'tyuk', 'tyut', 'tyup', 'tyuh', 'teu', 'teug', 'teugg', 'teugs', 'teun', 'teunj', 'teunh', 'teud', 'teul', 'teulg', 'teulm', 'teulb', 'teuls', 'teult', 'teulp', 'teulh', 'teum', 'teub', 'teubs', 'teus', 'teuss', 'teung', 'teuj', 'teuc', 'teuk', 'teut', 'teup', 'teuh', 'tyi', 'tyig', 'tyigg', 'tyigs', 'tyin', 'tyinj', 'tyinh', 'tyid', 'tyil', 'tyilg', 'tyilm', 'tyilb', 'tyils', 'tyilt', 'tyilp', 'tyilh', 'tyim', 'tyib', 'tyibs', 'tyis', 'tyiss', 'tying', 'tyij', 'tyic', 'tyik', 'tyit', 'tyip', 'tyih', 'ti', 'tig', 'tigg', 'tigs', 'tin', 'tinj', 'tinh', 'tid', 'til', 'tilg', 'tilm', 'tilb', 'tils', 'tilt', 'tilp', 'tilh'];
<?php return ['Sha ', 'Li ', 'Han ', 'Xian ', 'Jing ', 'Pai ', 'Fei ', 'Yao ', 'Ba ', 'Qi ', 'Ni ', 'Biao ', 'Yin ', 'Lai ', 'Xi ', 'Jian ', 'Qiang ', 'Kun ', 'Yan ', 'Guo ', 'Zong ', 'Mi ', 'Chang ', 'Yi ', 'Zhi ', 'Zheng ', 'Ya ', 'Meng ', 'Cai ', 'Cu ', 'She ', 'Kari ', 'Cen ', 'Luo ', 'Hu ', 'Zong ', 'Ji ', 'Wei ', 'Feng ', 'Wo ', 'Yuan ', 'Xing ', 'Zhu ', 'Mao ', 'Wei ', 'Yuan ', 'Xian ', 'Tuan ', 'Ya ', 'Nao ', 'Xie ', 'Jia ', 'Hou ', 'Bian ', 'You ', 'You ', 'Mei ', 'Zha ', 'Yao ', 'Sun ', 'Bo ', 'Ming ', 'Hua ', 'Yuan ', 'Sou ', 'Ma ', 'Yuan ', 'Dai ', 'Yu ', 'Shi ', 'Hao ', '[?] ', 'Yi ', 'Zhen ', 'Chuang ', 'Hao ', 'Man ', 'Jing ', 'Jiang ', 'Mu ', 'Zhang ', 'Chan ', 'Ao ', 'Ao ', 'Hao ', 'Cui ', 'Fen ', 'Jue ', 'Bi ', 'Bi ', 'Huang ', 'Pu ', 'Lin ', 'Yu ', 'Tong ', 'Yao ', 'Liao ', 'Shuo ', 'Xiao ', 'Swu ', 'Ton ', 'Xi ', 'Ge ', 'Juan ', 'Du ', 'Hui ', 'Kuai ', 'Xian ', 'Xie ', 'Ta ', 'Xian ', 'Xun ', 'Ning ', 'Pin ', 'Huo ', 'Nou ', 'Meng ', 'Lie ', 'Nao ', 'Guang ', 'Shou ', 'Lu ', 'Ta ', 'Xian ', 'Mi ', 'Rang ', 'Huan ', 'Nao ', 'Luo ', 'Xian ', 'Qi ', 'Jue ', 'Xuan ', 'Miao ', 'Zi ', 'Lu ', 'Lu ', 'Yu ', 'Su ', 'Wang ', 'Qiu ', 'Ga ', 'Ding ', 'Le ', 'Ba ', 'Ji ', 'Hong ', 'Di ', 'Quan ', 'Gan ', 'Jiu ', 'Yu ', 'Ji ', 'Yu ', 'Yang ', 'Ma ', 'Gong ', 'Wu ', 'Fu ', 'Wen ', 'Jie ', 'Ya ', 'Fen ', 'Bian ', 'Beng ', 'Yue ', 'Jue ', 'Yun ', 'Jue ', 'Wan ', 'Jian ', 'Mei ', 'Dan ', 'Pi ', 'Wei ', 'Huan ', 'Xian ', 'Qiang ', 'Ling ', 'Dai ', 'Yi ', 'An ', 'Ping ', 'Dian ', 'Fu ', 'Xuan ', 'Xi ', 'Bo ', 'Ci ', 'Gou ', 'Jia ', 'Shao ', 'Po ', 'Ci ', 'Ke ', 'Ran ', 'Sheng ', 'Shen ', 'Yi ', 'Zu ', 'Jia ', 'Min ', 'Shan ', 'Liu ', 'Bi ', 'Zhen ', 'Zhen ', 'Jue ', 'Fa ', 'Long ', 'Jin ', 'Jiao ', 'Jian ', 'Li ', 'Guang ', 'Xian ', 'Zhou ', 'Gong ', 'Yan ', 'Xiu ', 'Yang ', 'Xu ', 'Luo ', 'Su ', 'Zhu ', 'Qin ', 'Ken ', 'Xun ', 'Bao ', 'Er ', 'Xiang ', 'Yao ', 'Xia ', 'Heng ', 'Gui ', 'Chong ', 'Xu ', 'Ban ', 'Pei ', '[?] ', 'Dang ', 'Ei ', 'Hun ', 'Wen ', 'E ', 'Cheng ', 'Ti ', 'Wu ', 'Wu ', 'Cheng ', 'Jun ', 'Mei ', 'Bei ', 'Ting ', 'Xian ', 'Chuo '];
<?php return ['[?]', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '[?]', '[?]', '.', '[', ']', ',', '*', 'wo', 'a', 'i', 'u', 'e', 'o', 'ya', 'yu', 'yo', 'tu', '+', 'a', 'i', 'u', 'e', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', 'ta', 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'n', ':', ';', '', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'dd', 'r', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', 'rh', 'm', 'b', 'bb', 'bs', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', '[?]', '[?]', '[?]', 'a', 'ae', 'ya', 'yae', 'eo', 'e', '[?]', '[?]', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', '[?]', '[?]', 'yo', 'u', 'weo', 'we', 'wi', 'yu', '[?]', '[?]', 'eu', 'yi', 'i', '[?]', '[?]', '[?]', '/C', 'PS', '!', '-', '|', 'Y=', 'W=', '[?]', '|', '-', '|', '-', '|', '#', 'O', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '{', '|', '}', '', '', '', ''];
<?php return ['Hu ', 'Xi ', 'Shu ', 'He ', 'Xun ', 'Ku ', 'Jue ', 'Xiao ', 'Xi ', 'Yan ', 'Han ', 'Zhuang ', 'Jun ', 'Di ', 'Xie ', 'Ji ', 'Wu ', '[?] ', '[?] ', 'Han ', 'Yan ', 'Huan ', 'Men ', 'Ju ', 'Chou ', 'Bei ', 'Fen ', 'Lin ', 'Kun ', 'Hun ', 'Tun ', 'Xi ', 'Cui ', 'Wu ', 'Hong ', 'Ju ', 'Fu ', 'Wo ', 'Jiao ', 'Cong ', 'Feng ', 'Ping ', 'Qiong ', 'Ruo ', 'Xi ', 'Qiong ', 'Xin ', 'Zhuo ', 'Yan ', 'Yan ', 'Yi ', 'Jue ', 'Yu ', 'Gang ', 'Ran ', 'Pi ', 'Gu ', '[?] ', 'Sheng ', 'Chang ', 'Shao ', '[?] ', '[?] ', '[?] ', '[?] ', 'Chen ', 'He ', 'Kui ', 'Zhong ', 'Duan ', 'Xia ', 'Hui ', 'Feng ', 'Lian ', 'Xuan ', 'Xing ', 'Huang ', 'Jiao ', 'Jian ', 'Bi ', 'Ying ', 'Zhu ', 'Wei ', 'Tuan ', 'Tian ', 'Xi ', 'Nuan ', 'Nuan ', 'Chan ', 'Yan ', 'Jiong ', 'Jiong ', 'Yu ', 'Mei ', 'Sha ', 'Wei ', 'Ye ', 'Xin ', 'Qiong ', 'Rou ', 'Mei ', 'Huan ', 'Xu ', 'Zhao ', 'Wei ', 'Fan ', 'Qiu ', 'Sui ', 'Yang ', 'Lie ', 'Zhu ', 'Jie ', 'Gao ', 'Gua ', 'Bao ', 'Hu ', 'Yun ', 'Xia ', '[?] ', '[?] ', 'Bian ', 'Gou ', 'Tui ', 'Tang ', 'Chao ', 'Shan ', 'N ', 'Bo ', 'Huang ', 'Xie ', 'Xi ', 'Wu ', 'Xi ', 'Yun ', 'He ', 'He ', 'Xi ', 'Yun ', 'Xiong ', 'Nai ', 'Shan ', 'Qiong ', 'Yao ', 'Xun ', 'Mi ', 'Lian ', 'Ying ', 'Wen ', 'Rong ', 'Oozutsu ', '[?] ', 'Qiang ', 'Liu ', 'Xi ', 'Bi ', 'Biao ', 'Zong ', 'Lu ', 'Jian ', 'Shou ', 'Yi ', 'Lou ', 'Feng ', 'Sui ', 'Yi ', 'Tong ', 'Jue ', 'Zong ', 'Yun ', 'Hu ', 'Yi ', 'Zhi ', 'Ao ', 'Wei ', 'Liao ', 'Han ', 'Ou ', 'Re ', 'Jiong ', 'Man ', '[?] ', 'Shang ', 'Cuan ', 'Zeng ', 'Jian ', 'Xi ', 'Xi ', 'Xi ', 'Yi ', 'Xiao ', 'Chi ', 'Huang ', 'Chan ', 'Ye ', 'Qian ', 'Ran ', 'Yan ', 'Xian ', 'Qiao ', 'Zun ', 'Deng ', 'Dun ', 'Shen ', 'Jiao ', 'Fen ', 'Si ', 'Liao ', 'Yu ', 'Lin ', 'Tong ', 'Shao ', 'Fen ', 'Fan ', 'Yan ', 'Xun ', 'Lan ', 'Mei ', 'Tang ', 'Yi ', 'Jing ', 'Men ', '[?] ', '[?] ', 'Ying ', 'Yu ', 'Yi ', 'Xue ', 'Lan ', 'Tai ', 'Zao ', 'Can ', 'Sui ', 'Xi ', 'Que ', 'Cong ', 'Lian ', 'Hui ', 'Zhu ', 'Xie ', 'Ling ', 'Wei ', 'Yi ', 'Xie ', 'Zhao ', 'Hui ', 'Tatsu ', 'Nung ', 'Lan ', 'Ru ', 'Xian ', 'Kao ', 'Xun ', 'Jin ', 'Chou ', 'Chou ', 'Yao '];
<?php return ['Ci ', 'Xiang ', 'She ', 'Luo ', 'Qin ', 'Ying ', 'Chai ', 'Li ', 'Ze ', 'Xuan ', 'Lian ', 'Zhu ', 'Ze ', 'Xie ', 'Mang ', 'Xie ', 'Qi ', 'Rong ', 'Jian ', 'Meng ', 'Hao ', 'Ruan ', 'Huo ', 'Zhuo ', 'Jie ', 'Bin ', 'He ', 'Mie ', 'Fan ', 'Lei ', 'Jie ', 'La ', 'Mi ', 'Li ', 'Chun ', 'Li ', 'Qiu ', 'Nie ', 'Lu ', 'Du ', 'Xiao ', 'Zhu ', 'Long ', 'Li ', 'Long ', 'Feng ', 'Ye ', 'Beng ', 'Shang ', 'Gu ', 'Juan ', 'Ying ', '[?] ', 'Xi ', 'Can ', 'Qu ', 'Quan ', 'Du ', 'Can ', 'Man ', 'Jue ', 'Jie ', 'Zhu ', 'Zha ', 'Xie ', 'Huang ', 'Niu ', 'Pei ', 'Nu ', 'Xin ', 'Zhong ', 'Mo ', 'Er ', 'Ke ', 'Mie ', 'Xi ', 'Xing ', 'Yan ', 'Kan ', 'Yuan ', '[?] ', 'Ling ', 'Xuan ', 'Shu ', 'Xian ', 'Tong ', 'Long ', 'Jie ', 'Xian ', 'Ya ', 'Hu ', 'Wei ', 'Dao ', 'Chong ', 'Wei ', 'Dao ', 'Zhun ', 'Heng ', 'Qu ', 'Yi ', 'Yi ', 'Bu ', 'Gan ', 'Yu ', 'Biao ', 'Cha ', 'Yi ', 'Shan ', 'Chen ', 'Fu ', 'Gun ', 'Fen ', 'Shuai ', 'Jie ', 'Na ', 'Zhong ', 'Dan ', 'Ri ', 'Zhong ', 'Zhong ', 'Xie ', 'Qi ', 'Xie ', 'Ran ', 'Zhi ', 'Ren ', 'Qin ', 'Jin ', 'Jun ', 'Yuan ', 'Mei ', 'Chai ', 'Ao ', 'Niao ', 'Hui ', 'Ran ', 'Jia ', 'Tuo ', 'Ling ', 'Dai ', 'Bao ', 'Pao ', 'Yao ', 'Zuo ', 'Bi ', 'Shao ', 'Tan ', 'Ju ', 'He ', 'Shu ', 'Xiu ', 'Zhen ', 'Yi ', 'Pa ', 'Bo ', 'Di ', 'Wa ', 'Fu ', 'Gun ', 'Zhi ', 'Zhi ', 'Ran ', 'Pan ', 'Yi ', 'Mao ', 'Tuo ', 'Na ', 'Kou ', 'Xian ', 'Chan ', 'Qu ', 'Bei ', 'Gun ', 'Xi ', 'Ne ', 'Bo ', 'Horo ', 'Fu ', 'Yi ', 'Chi ', 'Ku ', 'Ren ', 'Jiang ', 'Jia ', 'Cun ', 'Mo ', 'Jie ', 'Er ', 'Luo ', 'Ru ', 'Zhu ', 'Gui ', 'Yin ', 'Cai ', 'Lie ', 'Kamishimo ', 'Yuki ', 'Zhuang ', 'Dang ', '[?] ', 'Kun ', 'Ken ', 'Niao ', 'Shu ', 'Jia ', 'Kun ', 'Cheng ', 'Li ', 'Juan ', 'Shen ', 'Pou ', 'Ge ', 'Yi ', 'Yu ', 'Zhen ', 'Liu ', 'Qiu ', 'Qun ', 'Ji ', 'Yi ', 'Bu ', 'Zhuang ', 'Shui ', 'Sha ', 'Qun ', 'Li ', 'Lian ', 'Lian ', 'Ku ', 'Jian ', 'Fou ', 'Chan ', 'Bi ', 'Gun ', 'Tao ', 'Yuan ', 'Ling ', 'Chi ', 'Chang ', 'Chou ', 'Duo ', 'Biao ', 'Liang ', 'Chang ', 'Pei ', 'Pei ', 'Fei ', 'Yuan ', 'Luo ', 'Guo ', 'Yan ', 'Du ', 'Xi ', 'Zhi ', 'Ju ', 'Qi '];
<?php return ['poss', 'pong', 'poj', 'poc', 'pok', 'pot', 'pop', 'poh', 'pwa', 'pwag', 'pwagg', 'pwags', 'pwan', 'pwanj', 'pwanh', 'pwad', 'pwal', 'pwalg', 'pwalm', 'pwalb', 'pwals', 'pwalt', 'pwalp', 'pwalh', 'pwam', 'pwab', 'pwabs', 'pwas', 'pwass', 'pwang', 'pwaj', 'pwac', 'pwak', 'pwat', 'pwap', 'pwah', 'pwae', 'pwaeg', 'pwaegg', 'pwaegs', 'pwaen', 'pwaenj', 'pwaenh', 'pwaed', 'pwael', 'pwaelg', 'pwaelm', 'pwaelb', 'pwaels', 'pwaelt', 'pwaelp', 'pwaelh', 'pwaem', 'pwaeb', 'pwaebs', 'pwaes', 'pwaess', 'pwaeng', 'pwaej', 'pwaec', 'pwaek', 'pwaet', 'pwaep', 'pwaeh', 'poe', 'poeg', 'poegg', 'poegs', 'poen', 'poenj', 'poenh', 'poed', 'poel', 'poelg', 'poelm', 'poelb', 'poels', 'poelt', 'poelp', 'poelh', 'poem', 'poeb', 'poebs', 'poes', 'poess', 'poeng', 'poej', 'poec', 'poek', 'poet', 'poep', 'poeh', 'pyo', 'pyog', 'pyogg', 'pyogs', 'pyon', 'pyonj', 'pyonh', 'pyod', 'pyol', 'pyolg', 'pyolm', 'pyolb', 'pyols', 'pyolt', 'pyolp', 'pyolh', 'pyom', 'pyob', 'pyobs', 'pyos', 'pyoss', 'pyong', 'pyoj', 'pyoc', 'pyok', 'pyot', 'pyop', 'pyoh', 'pu', 'pug', 'pugg', 'pugs', 'pun', 'punj', 'punh', 'pud', 'pul', 'pulg', 'pulm', 'pulb', 'puls', 'pult', 'pulp', 'pulh', 'pum', 'pub', 'pubs', 'pus', 'puss', 'pung', 'puj', 'puc', 'puk', 'put', 'pup', 'puh', 'pweo', 'pweog', 'pweogg', 'pweogs', 'pweon', 'pweonj', 'pweonh', 'pweod', 'pweol', 'pweolg', 'pweolm', 'pweolb', 'pweols', 'pweolt', 'pweolp', 'pweolh', 'pweom', 'pweob', 'pweobs', 'pweos', 'pweoss', 'pweong', 'pweoj', 'pweoc', 'pweok', 'pweot', 'pweop', 'pweoh', 'pwe', 'pweg', 'pwegg', 'pwegs', 'pwen', 'pwenj', 'pwenh', 'pwed', 'pwel', 'pwelg', 'pwelm', 'pwelb', 'pwels', 'pwelt', 'pwelp', 'pwelh', 'pwem', 'pweb', 'pwebs', 'pwes', 'pwess', 'pweng', 'pwej', 'pwec', 'pwek', 'pwet', 'pwep', 'pweh', 'pwi', 'pwig', 'pwigg', 'pwigs', 'pwin', 'pwinj', 'pwinh', 'pwid', 'pwil', 'pwilg', 'pwilm', 'pwilb', 'pwils', 'pwilt', 'pwilp', 'pwilh', 'pwim', 'pwib', 'pwibs', 'pwis', 'pwiss', 'pwing', 'pwij', 'pwic', 'pwik', 'pwit', 'pwip', 'pwih', 'pyu', 'pyug', 'pyugg', 'pyugs', 'pyun', 'pyunj', 'pyunh', 'pyud', 'pyul', 'pyulg', 'pyulm', 'pyulb', 'pyuls', 'pyult', 'pyulp', 'pyulh', 'pyum', 'pyub', 'pyubs', 'pyus', 'pyuss', 'pyung', 'pyuj', 'pyuc'];
<?php return ['geul', 'geulg', 'geulm', 'geulb', 'geuls', 'geult', 'geulp', 'geulh', 'geum', 'geub', 'geubs', 'geus', 'geuss', 'geung', 'geuj', 'geuc', 'geuk', 'geut', 'geup', 'geuh', 'gyi', 'gyig', 'gyigg', 'gyigs', 'gyin', 'gyinj', 'gyinh', 'gyid', 'gyil', 'gyilg', 'gyilm', 'gyilb', 'gyils', 'gyilt', 'gyilp', 'gyilh', 'gyim', 'gyib', 'gyibs', 'gyis', 'gyiss', 'gying', 'gyij', 'gyic', 'gyik', 'gyit', 'gyip', 'gyih', 'gi', 'gig', 'gigg', 'gigs', 'gin', 'ginj', 'ginh', 'gid', 'gil', 'gilg', 'gilm', 'gilb', 'gils', 'gilt', 'gilp', 'gilh', 'gim', 'gib', 'gibs', 'gis', 'giss', 'ging', 'gij', 'gic', 'gik', 'git', 'gip', 'gih', 'gga', 'ggag', 'ggagg', 'ggags', 'ggan', 'gganj', 'gganh', 'ggad', 'ggal', 'ggalg', 'ggalm', 'ggalb', 'ggals', 'ggalt', 'ggalp', 'ggalh', 'ggam', 'ggab', 'ggabs', 'ggas', 'ggass', 'ggang', 'ggaj', 'ggac', 'ggak', 'ggat', 'ggap', 'ggah', 'ggae', 'ggaeg', 'ggaegg', 'ggaegs', 'ggaen', 'ggaenj', 'ggaenh', 'ggaed', 'ggael', 'ggaelg', 'ggaelm', 'ggaelb', 'ggaels', 'ggaelt', 'ggaelp', 'ggaelh', 'ggaem', 'ggaeb', 'ggaebs', 'ggaes', 'ggaess', 'ggaeng', 'ggaej', 'ggaec', 'ggaek', 'ggaet', 'ggaep', 'ggaeh', 'ggya', 'ggyag', 'ggyagg', 'ggyags', 'ggyan', 'ggyanj', 'ggyanh', 'ggyad', 'ggyal', 'ggyalg', 'ggyalm', 'ggyalb', 'ggyals', 'ggyalt', 'ggyalp', 'ggyalh', 'ggyam', 'ggyab', 'ggyabs', 'ggyas', 'ggyass', 'ggyang', 'ggyaj', 'ggyac', 'ggyak', 'ggyat', 'ggyap', 'ggyah', 'ggyae', 'ggyaeg', 'ggyaegg', 'ggyaegs', 'ggyaen', 'ggyaenj', 'ggyaenh', 'ggyaed', 'ggyael', 'ggyaelg', 'ggyaelm', 'ggyaelb', 'ggyaels', 'ggyaelt', 'ggyaelp', 'ggyaelh', 'ggyaem', 'ggyaeb', 'ggyaebs', 'ggyaes', 'ggyaess', 'ggyaeng', 'ggyaej', 'ggyaec', 'ggyaek', 'ggyaet', 'ggyaep', 'ggyaeh', 'ggeo', 'ggeog', 'ggeogg', 'ggeogs', 'ggeon', 'ggeonj', 'ggeonh', 'ggeod', 'ggeol', 'ggeolg', 'ggeolm', 'ggeolb', 'ggeols', 'ggeolt', 'ggeolp', 'ggeolh', 'ggeom', 'ggeob', 'ggeobs', 'ggeos', 'ggeoss', 'ggeong', 'ggeoj', 'ggeoc', 'ggeok', 'ggeot', 'ggeop', 'ggeoh', 'gge', 'ggeg', 'ggegg', 'ggegs', 'ggen', 'ggenj', 'ggenh', 'gged', 'ggel', 'ggelg', 'ggelm', 'ggelb', 'ggels', 'ggelt', 'ggelp', 'ggelh', 'ggem', 'ggeb', 'ggebs', 'gges', 'ggess', 'ggeng', 'ggej', 'ggec', 'ggek', 'gget', 'ggep', 'ggeh', 'ggyeo', 'ggyeog', 'ggyeogg', 'ggyeogs', 'ggyeon', 'ggyeonj', 'ggyeonh', 'ggyeod', 'ggyeol', 'ggyeolg', 'ggyeolm', 'ggyeolb'];
<?php return ['Guo ', 'Yin ', 'Hun ', 'Pu ', 'Yu ', 'Han ', 'Yuan ', 'Lun ', 'Quan ', 'Yu ', 'Qing ', 'Guo ', 'Chuan ', 'Wei ', 'Yuan ', 'Quan ', 'Ku ', 'Fu ', 'Yuan ', 'Yuan ', 'E ', 'Tu ', 'Tu ', 'Tu ', 'Tuan ', 'Lue ', 'Hui ', 'Yi ', 'Yuan ', 'Luan ', 'Luan ', 'Tu ', 'Ya ', 'Tu ', 'Ting ', 'Sheng ', 'Pu ', 'Lu ', 'Iri ', 'Ya ', 'Zai ', 'Wei ', 'Ge ', 'Yu ', 'Wu ', 'Gui ', 'Pi ', 'Yi ', 'Di ', 'Qian ', 'Qian ', 'Zhen ', 'Zhuo ', 'Dang ', 'Qia ', 'Akutsu ', 'Yama ', 'Kuang ', 'Chang ', 'Qi ', 'Nie ', 'Mo ', 'Ji ', 'Jia ', 'Zhi ', 'Zhi ', 'Ban ', 'Xun ', 'Tou ', 'Qin ', 'Fen ', 'Jun ', 'Keng ', 'Tun ', 'Fang ', 'Fen ', 'Ben ', 'Tan ', 'Kan ', 'Pi ', 'Zuo ', 'Keng ', 'Bi ', 'Xing ', 'Di ', 'Jing ', 'Ji ', 'Kuai ', 'Di ', 'Jing ', 'Jian ', 'Tan ', 'Li ', 'Ba ', 'Wu ', 'Fen ', 'Zhui ', 'Po ', 'Pan ', 'Tang ', 'Kun ', 'Qu ', 'Tan ', 'Zhi ', 'Tuo ', 'Gan ', 'Ping ', 'Dian ', 'Gua ', 'Ni ', 'Tai ', 'Pi ', 'Jiong ', 'Yang ', 'Fo ', 'Ao ', 'Liu ', 'Qiu ', 'Mu ', 'Ke ', 'Gou ', 'Xue ', 'Ba ', 'Chi ', 'Che ', 'Ling ', 'Zhu ', 'Fu ', 'Hu ', 'Zhi ', 'Chui ', 'La ', 'Long ', 'Long ', 'Lu ', 'Ao ', 'Tay ', 'Pao ', '[?] ', 'Xing ', 'Dong ', 'Ji ', 'Ke ', 'Lu ', 'Ci ', 'Chi ', 'Lei ', 'Gai ', 'Yin ', 'Hou ', 'Dui ', 'Zhao ', 'Fu ', 'Guang ', 'Yao ', 'Duo ', 'Duo ', 'Gui ', 'Cha ', 'Yang ', 'Yin ', 'Fa ', 'Gou ', 'Yuan ', 'Die ', 'Xie ', 'Ken ', 'Jiong ', 'Shou ', 'E ', 'Ha ', 'Dian ', 'Hong ', 'Wu ', 'Kua ', '[?] ', 'Tao ', 'Dang ', 'Kai ', 'Gake ', 'Nao ', 'An ', 'Xing ', 'Xian ', 'Huan ', 'Bang ', 'Pei ', 'Ba ', 'Yi ', 'Yin ', 'Han ', 'Xu ', 'Chui ', 'Cen ', 'Geng ', 'Ai ', 'Peng ', 'Fang ', 'Que ', 'Yong ', 'Xun ', 'Jia ', 'Di ', 'Mai ', 'Lang ', 'Xuan ', 'Cheng ', 'Yan ', 'Jin ', 'Zhe ', 'Lei ', 'Lie ', 'Bu ', 'Cheng ', 'Gomi ', 'Bu ', 'Shi ', 'Xun ', 'Guo ', 'Jiong ', 'Ye ', 'Nian ', 'Di ', 'Yu ', 'Bu ', 'Ya ', 'Juan ', 'Sui ', 'Pi ', 'Cheng ', 'Wan ', 'Ju ', 'Lun ', 'Zheng ', 'Kong ', 'Chong ', 'Dong ', 'Dai ', 'Tan ', 'An ', 'Cai ', 'Shu ', 'Beng ', 'Kan ', 'Zhi ', 'Duo ', 'Yi ', 'Zhi ', 'Yi ', 'Pei ', 'Ji ', 'Zhun ', 'Qi ', 'Sao ', 'Ju ', 'Ni '];
<?php return ['Kui ', 'Si ', 'Liu ', 'Nao ', 'Heng ', 'Pie ', 'Sui ', 'Fan ', 'Qiao ', 'Quan ', 'Yang ', 'Tang ', 'Xiang ', 'Jue ', 'Jiao ', 'Zun ', 'Liao ', 'Jie ', 'Lao ', 'Dui ', 'Tan ', 'Zan ', 'Ji ', 'Jian ', 'Zhong ', 'Deng ', 'Ya ', 'Ying ', 'Dui ', 'Jue ', 'Nou ', 'Ti ', 'Pu ', 'Tie ', '[?] ', '[?] ', 'Ding ', 'Shan ', 'Kai ', 'Jian ', 'Fei ', 'Sui ', 'Lu ', 'Juan ', 'Hui ', 'Yu ', 'Lian ', 'Zhuo ', 'Qiao ', 'Qian ', 'Zhuo ', 'Lei ', 'Bi ', 'Tie ', 'Huan ', 'Ye ', 'Duo ', 'Guo ', 'Dang ', 'Ju ', 'Fen ', 'Da ', 'Bei ', 'Yi ', 'Ai ', 'Zong ', 'Xun ', 'Diao ', 'Zhu ', 'Heng ', 'Zhui ', 'Ji ', 'Nie ', 'Ta ', 'Huo ', 'Qing ', 'Bin ', 'Ying ', 'Kui ', 'Ning ', 'Xu ', 'Jian ', 'Jian ', 'Yari ', 'Cha ', 'Zhi ', 'Mie ', 'Li ', 'Lei ', 'Ji ', 'Zuan ', 'Kuang ', 'Shang ', 'Peng ', 'La ', 'Du ', 'Shuo ', 'Chuo ', 'Lu ', 'Biao ', 'Bao ', 'Lu ', '[?] ', '[?] ', 'Long ', 'E ', 'Lu ', 'Xin ', 'Jian ', 'Lan ', 'Bo ', 'Jian ', 'Yao ', 'Chan ', 'Xiang ', 'Jian ', 'Xi ', 'Guan ', 'Cang ', 'Nie ', 'Lei ', 'Cuan ', 'Qu ', 'Pan ', 'Luo ', 'Zuan ', 'Luan ', 'Zao ', 'Nie ', 'Jue ', 'Tang ', 'Shu ', 'Lan ', 'Jin ', 'Qiu ', 'Yi ', 'Zhen ', 'Ding ', 'Zhao ', 'Po ', 'Diao ', 'Tu ', 'Qian ', 'Chuan ', 'Shan ', 'Ji ', 'Fan ', 'Diao ', 'Men ', 'Nu ', 'Xi ', 'Chai ', 'Xing ', 'Gai ', 'Bu ', 'Tai ', 'Ju ', 'Dun ', 'Chao ', 'Zhong ', 'Na ', 'Bei ', 'Gang ', 'Ban ', 'Qian ', 'Yao ', 'Qin ', 'Jun ', 'Wu ', 'Gou ', 'Kang ', 'Fang ', 'Huo ', 'Tou ', 'Niu ', 'Ba ', 'Yu ', 'Qian ', 'Zheng ', 'Qian ', 'Gu ', 'Bo ', 'E ', 'Po ', 'Bu ', 'Ba ', 'Yue ', 'Zuan ', 'Mu ', 'Dan ', 'Jia ', 'Dian ', 'You ', 'Tie ', 'Bo ', 'Ling ', 'Shuo ', 'Qian ', 'Liu ', 'Bao ', 'Shi ', 'Xuan ', 'She ', 'Bi ', 'Ni ', 'Pi ', 'Duo ', 'Xing ', 'Kao ', 'Lao ', 'Er ', 'Mang ', 'Ya ', 'You ', 'Cheng ', 'Jia ', 'Ye ', 'Nao ', 'Zhi ', 'Dang ', 'Tong ', 'Lu ', 'Diao ', 'Yin ', 'Kai ', 'Zha ', 'Zhu ', 'Xian ', 'Ting ', 'Diu ', 'Xian ', 'Hua ', 'Quan ', 'Sha ', 'Jia ', 'Yao ', 'Ge ', 'Ming ', 'Zheng ', 'Se ', 'Jiao ', 'Yi ', 'Chan ', 'Chong ', 'Tang ', 'An ', 'Yin ', 'Ru ', 'Zhu ', 'Lao ', 'Pu ', 'Wu ', 'Lai ', 'Te ', 'Lian ', 'Keng '];
<?php return ['[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 't', 'tth', 'd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'l', 'v', 'sh', 'ss', 's', 'h', 'l', 'q', 'a', 'aa', 'i', 'ii', 'u', 'uk', 'uu', 'uuv', 'ry', 'ryy', 'ly', 'lyy', 'e', 'ai', 'oo', 'oo', 'au', 'a', 'aa', 'aa', 'i', 'ii', 'y', 'yy', 'u', 'uu', 'ua', 'oe', 'ya', 'ie', 'e', 'ae', 'ai', 'oo', 'au', 'M', 'H', 'a`', '', '', '', 'r', '', '!', '', '', '', '', '', '.', ' // ', ':', '+', '++', ' * ', ' /// ', 'KR', '\'', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Chu ', 'Jing ', 'Nie ', 'Xiao ', 'Bo ', 'Chi ', 'Qun ', 'Mou ', 'Shu ', 'Lang ', 'Yong ', 'Jiao ', 'Chou ', 'Qiao ', '[?] ', 'Ta ', 'Jian ', 'Qi ', 'Wo ', 'Wei ', 'Zhuo ', 'Jie ', 'Ji ', 'Nie ', 'Ju ', 'Ju ', 'Lun ', 'Lu ', 'Leng ', 'Huai ', 'Ju ', 'Chi ', 'Wan ', 'Quan ', 'Ti ', 'Bo ', 'Zu ', 'Qie ', 'Ji ', 'Cu ', 'Zong ', 'Cai ', 'Zong ', 'Peng ', 'Zhi ', 'Zheng ', 'Dian ', 'Zhi ', 'Yu ', 'Duo ', 'Dun ', 'Chun ', 'Yong ', 'Zhong ', 'Di ', 'Zhe ', 'Chen ', 'Chuai ', 'Jian ', 'Gua ', 'Tang ', 'Ju ', 'Fu ', 'Zu ', 'Die ', 'Pian ', 'Rou ', 'Nuo ', 'Ti ', 'Cha ', 'Tui ', 'Jian ', 'Dao ', 'Cuo ', 'Xi ', 'Ta ', 'Qiang ', 'Zhan ', 'Dian ', 'Ti ', 'Ji ', 'Nie ', 'Man ', 'Liu ', 'Zhan ', 'Bi ', 'Chong ', 'Lu ', 'Liao ', 'Cu ', 'Tang ', 'Dai ', 'Suo ', 'Xi ', 'Kui ', 'Ji ', 'Zhi ', 'Qiang ', 'Di ', 'Man ', 'Zong ', 'Lian ', 'Beng ', 'Zao ', 'Nian ', 'Bie ', 'Tui ', 'Ju ', 'Deng ', 'Ceng ', 'Xian ', 'Fan ', 'Chu ', 'Zhong ', 'Dun ', 'Bo ', 'Cu ', 'Zu ', 'Jue ', 'Jue ', 'Lin ', 'Ta ', 'Qiao ', 'Qiao ', 'Pu ', 'Liao ', 'Dun ', 'Cuan ', 'Kuang ', 'Zao ', 'Ta ', 'Bi ', 'Bi ', 'Zhu ', 'Ju ', 'Chu ', 'Qiao ', 'Dun ', 'Chou ', 'Ji ', 'Wu ', 'Yue ', 'Nian ', 'Lin ', 'Lie ', 'Zhi ', 'Li ', 'Zhi ', 'Chan ', 'Chu ', 'Duan ', 'Wei ', 'Long ', 'Lin ', 'Xian ', 'Wei ', 'Zuan ', 'Lan ', 'Xie ', 'Rang ', 'Xie ', 'Nie ', 'Ta ', 'Qu ', 'Jie ', 'Cuan ', 'Zuan ', 'Xi ', 'Kui ', 'Jue ', 'Lin ', 'Shen ', 'Gong ', 'Dan ', 'Segare ', 'Qu ', 'Ti ', 'Duo ', 'Duo ', 'Gong ', 'Lang ', 'Nerau ', 'Luo ', 'Ai ', 'Ji ', 'Ju ', 'Tang ', 'Utsuke ', '[?] ', 'Yan ', 'Shitsuke ', 'Kang ', 'Qu ', 'Lou ', 'Lao ', 'Tuo ', 'Zhi ', 'Yagate ', 'Ti ', 'Dao ', 'Yagate ', 'Yu ', 'Che ', 'Ya ', 'Gui ', 'Jun ', 'Wei ', 'Yue ', 'Xin ', 'Di ', 'Xuan ', 'Fan ', 'Ren ', 'Shan ', 'Qiang ', 'Shu ', 'Tun ', 'Chen ', 'Dai ', 'E ', 'Na ', 'Qi ', 'Mao ', 'Ruan ', 'Ren ', 'Fan ', 'Zhuan ', 'Hong ', 'Hu ', 'Qu ', 'Huang ', 'Di ', 'Ling ', 'Dai ', 'Ao ', 'Zhen ', 'Fan ', 'Kuang ', 'Ang ', 'Peng ', 'Bei ', 'Gu ', 'Ku ', 'Pao ', 'Zhu ', 'Rong ', 'E ', 'Ba ', 'Zhou ', 'Zhi ', 'Yao ', 'Ke ', 'Yi ', 'Qing ', 'Shi ', 'Ping '];
<?php return ['Ti ', 'Li ', 'Bin ', 'Zong ', 'Ti ', 'Peng ', 'Song ', 'Zheng ', 'Quan ', 'Zong ', 'Shun ', 'Jian ', 'Duo ', 'Hu ', 'La ', 'Jiu ', 'Qi ', 'Lian ', 'Zhen ', 'Bin ', 'Peng ', 'Mo ', 'San ', 'Man ', 'Man ', 'Seng ', 'Xu ', 'Lie ', 'Qian ', 'Qian ', 'Nong ', 'Huan ', 'Kuai ', 'Ning ', 'Bin ', 'Lie ', 'Rang ', 'Dou ', 'Dou ', 'Nao ', 'Hong ', 'Xi ', 'Dou ', 'Han ', 'Dou ', 'Dou ', 'Jiu ', 'Chang ', 'Yu ', 'Yu ', 'Li ', 'Juan ', 'Fu ', 'Qian ', 'Gui ', 'Zong ', 'Liu ', 'Gui ', 'Shang ', 'Yu ', 'Gui ', 'Mei ', 'Ji ', 'Qi ', 'Jie ', 'Kui ', 'Hun ', 'Ba ', 'Po ', 'Mei ', 'Xu ', 'Yan ', 'Xiao ', 'Liang ', 'Yu ', 'Tui ', 'Qi ', 'Wang ', 'Liang ', 'Wei ', 'Jian ', 'Chi ', 'Piao ', 'Bi ', 'Mo ', 'Ji ', 'Xu ', 'Chou ', 'Yan ', 'Zhan ', 'Yu ', 'Dao ', 'Ren ', 'Ji ', 'Eri ', 'Gong ', 'Tuo ', 'Diao ', 'Ji ', 'Xu ', 'E ', 'E ', 'Sha ', 'Hang ', 'Tun ', 'Mo ', 'Jie ', 'Shen ', 'Fan ', 'Yuan ', 'Bi ', 'Lu ', 'Wen ', 'Hu ', 'Lu ', 'Za ', 'Fang ', 'Fen ', 'Na ', 'You ', 'Namazu ', 'Todo ', 'He ', 'Xia ', 'Qu ', 'Han ', 'Pi ', 'Ling ', 'Tuo ', 'Bo ', 'Qiu ', 'Ping ', 'Fu ', 'Bi ', 'Ji ', 'Wei ', 'Ju ', 'Diao ', 'Bo ', 'You ', 'Gun ', 'Pi ', 'Nian ', 'Xing ', 'Tai ', 'Bao ', 'Fu ', 'Zha ', 'Ju ', 'Gu ', 'Kajika ', 'Tong ', '[?] ', 'Ta ', 'Jie ', 'Shu ', 'Hou ', 'Xiang ', 'Er ', 'An ', 'Wei ', 'Tiao ', 'Zhu ', 'Yin ', 'Lie ', 'Luo ', 'Tong ', 'Yi ', 'Qi ', 'Bing ', 'Wei ', 'Jiao ', 'Bu ', 'Gui ', 'Xian ', 'Ge ', 'Hui ', 'Bora ', 'Mate ', 'Kao ', 'Gori ', 'Duo ', 'Jun ', 'Ti ', 'Man ', 'Xiao ', 'Za ', 'Sha ', 'Qin ', 'Yu ', 'Nei ', 'Zhe ', 'Gun ', 'Geng ', 'Su ', 'Wu ', 'Qiu ', 'Ting ', 'Fu ', 'Wan ', 'You ', 'Li ', 'Sha ', 'Sha ', 'Gao ', 'Meng ', 'Ugui ', 'Asari ', 'Subashiri ', 'Kazunoko ', 'Yong ', 'Ni ', 'Zi ', 'Qi ', 'Qing ', 'Xiang ', 'Nei ', 'Chun ', 'Ji ', 'Diao ', 'Qie ', 'Gu ', 'Zhou ', 'Dong ', 'Lai ', 'Fei ', 'Ni ', 'Yi ', 'Kun ', 'Lu ', 'Jiu ', 'Chang ', 'Jing ', 'Lun ', 'Ling ', 'Zou ', 'Li ', 'Meng ', 'Zong ', 'Zhi ', 'Nian ', 'Shachi ', 'Dojou ', 'Sukesou ', 'Shi ', 'Shen ', 'Hun ', 'Shi ', 'Hou ', 'Xing ', 'Zhu ', 'La ', 'Zong ', 'Ji ', 'Bian ', 'Bian '];
<?php return [' ', 'a', '1', 'b', '\'', 'k', '2', 'l', '@', 'c', 'i', 'f', '/', 'm', 's', 'p', '"', 'e', '3', 'h', '9', 'o', '6', 'r', '^', 'd', 'j', 'g', '>', 'n', 't', 'q', ',', '*', '5', '<', '-', 'u', '8', 'v', '.', '%', '[', '$', '+', 'x', '!', '&', ';', ':', '4', '\\', '0', 'z', '7', '(', '_', '?', 'w', ']', '#', 'y', ')', '=', '[d7]', '[d17]', '[d27]', '[d127]', '[d37]', '[d137]', '[d237]', '[d1237]', '[d47]', '[d147]', '[d247]', '[d1247]', '[d347]', '[d1347]', '[d2347]', '[d12347]', '[d57]', '[d157]', '[d257]', '[d1257]', '[d357]', '[d1357]', '[d2357]', '[d12357]', '[d457]', '[d1457]', '[d2457]', '[d12457]', '[d3457]', '[d13457]', '[d23457]', '[d123457]', '[d67]', '[d167]', '[d267]', '[d1267]', '[d367]', '[d1367]', '[d2367]', '[d12367]', '[d467]', '[d1467]', '[d2467]', '[d12467]', '[d3467]', '[d13467]', '[d23467]', '[d123467]', '[d567]', '[d1567]', '[d2567]', '[d12567]', '[d3567]', '[d13567]', '[d23567]', '[d123567]', '[d4567]', '[d14567]', '[d24567]', '[d124567]', '[d34567]', '[d134567]', '[d234567]', '[d1234567]', '[d8]', '[d18]', '[d28]', '[d128]', '[d38]', '[d138]', '[d238]', '[d1238]', '[d48]', '[d148]', '[d248]', '[d1248]', '[d348]', '[d1348]', '[d2348]', '[d12348]', '[d58]', '[d158]', '[d258]', '[d1258]', '[d358]', '[d1358]', '[d2358]', '[d12358]', '[d458]', '[d1458]', '[d2458]', '[d12458]', '[d3458]', '[d13458]', '[d23458]', '[d123458]', '[d68]', '[d168]', '[d268]', '[d1268]', '[d368]', '[d1368]', '[d2368]', '[d12368]', '[d468]', '[d1468]', '[d2468]', '[d12468]', '[d3468]', '[d13468]', '[d23468]', '[d123468]', '[d568]', '[d1568]', '[d2568]', '[d12568]', '[d3568]', '[d13568]', '[d23568]', '[d123568]', '[d4568]', '[d14568]', '[d24568]', '[d124568]', '[d34568]', '[d134568]', '[d234568]', '[d1234568]', '[d78]', '[d178]', '[d278]', '[d1278]', '[d378]', '[d1378]', '[d2378]', '[d12378]', '[d478]', '[d1478]', '[d2478]', '[d12478]', '[d3478]', '[d13478]', '[d23478]', '[d123478]', '[d578]', '[d1578]', '[d2578]', '[d12578]', '[d3578]', '[d13578]', '[d23578]', '[d123578]', '[d4578]', '[d14578]', '[d24578]', '[d124578]', '[d34578]', '[d134578]', '[d234578]', '[d1234578]', '[d678]', '[d1678]', '[d2678]', '[d12678]', '[d3678]', '[d13678]', '[d23678]', '[d123678]', '[d4678]', '[d14678]', '[d24678]', '[d124678]', '[d34678]', '[d134678]', '[d234678]', '[d1234678]', '[d5678]', '[d15678]', '[d25678]', '[d125678]', '[d35678]', '[d135678]', '[d235678]', '[d1235678]', '[d45678]', '[d145678]', '[d245678]', '[d1245678]', '[d345678]', '[d1345678]', '[d2345678]', '[d12345678]'];
<?php return ['Ben ', 'Yuan ', 'Wen ', 'Re ', 'Fei ', 'Qing ', 'Yuan ', 'Ke ', 'Ji ', 'She ', 'Yuan ', 'Shibui ', 'Lu ', 'Zi ', 'Du ', '[?] ', 'Jian ', 'Min ', 'Pi ', 'Tani ', 'Yu ', 'Yuan ', 'Shen ', 'Shen ', 'Rou ', 'Huan ', 'Zhu ', 'Jian ', 'Nuan ', 'Yu ', 'Qiu ', 'Ting ', 'Qu ', 'Du ', 'Feng ', 'Zha ', 'Bo ', 'Wo ', 'Wo ', 'Di ', 'Wei ', 'Wen ', 'Ru ', 'Xie ', 'Ce ', 'Wei ', 'Ge ', 'Gang ', 'Yan ', 'Hong ', 'Xuan ', 'Mi ', 'Ke ', 'Mao ', 'Ying ', 'Yan ', 'You ', 'Hong ', 'Miao ', 'Xing ', 'Mei ', 'Zai ', 'Hun ', 'Nai ', 'Kui ', 'Shi ', 'E ', 'Pai ', 'Mei ', 'Lian ', 'Qi ', 'Qi ', 'Mei ', 'Tian ', 'Cou ', 'Wei ', 'Can ', 'Tuan ', 'Mian ', 'Hui ', 'Mo ', 'Xu ', 'Ji ', 'Pen ', 'Jian ', 'Jian ', 'Hu ', 'Feng ', 'Xiang ', 'Yi ', 'Yin ', 'Zhan ', 'Shi ', 'Jie ', 'Cheng ', 'Huang ', 'Tan ', 'Yu ', 'Bi ', 'Min ', 'Shi ', 'Tu ', 'Sheng ', 'Yong ', 'Qu ', 'Zhong ', 'Suei ', 'Jiu ', 'Jiao ', 'Qiou ', 'Yin ', 'Tang ', 'Long ', 'Huo ', 'Yuan ', 'Nan ', 'Ban ', 'You ', 'Quan ', 'Chui ', 'Liang ', 'Chan ', 'Yan ', 'Chun ', 'Nie ', 'Zi ', 'Wan ', 'Shi ', 'Man ', 'Ying ', 'Ratsu ', 'Kui ', '[?] ', 'Jian ', 'Xu ', 'Lu ', 'Gui ', 'Gai ', '[?] ', '[?] ', 'Po ', 'Jin ', 'Gui ', 'Tang ', 'Yuan ', 'Suo ', 'Yuan ', 'Lian ', 'Yao ', 'Meng ', 'Zhun ', 'Sheng ', 'Ke ', 'Tai ', 'Da ', 'Wa ', 'Liu ', 'Gou ', 'Sao ', 'Ming ', 'Zha ', 'Shi ', 'Yi ', 'Lun ', 'Ma ', 'Pu ', 'Wei ', 'Li ', 'Cai ', 'Wu ', 'Xi ', 'Wen ', 'Qiang ', 'Ze ', 'Shi ', 'Su ', 'Yi ', 'Zhen ', 'Sou ', 'Yun ', 'Xiu ', 'Yin ', 'Rong ', 'Hun ', 'Su ', 'Su ', 'Ni ', 'Ta ', 'Shi ', 'Ru ', 'Wei ', 'Pan ', 'Chu ', 'Chu ', 'Pang ', 'Weng ', 'Cang ', 'Mie ', 'He ', 'Dian ', 'Hao ', 'Huang ', 'Xi ', 'Zi ', 'Di ', 'Zhi ', 'Ying ', 'Fu ', 'Jie ', 'Hua ', 'Ge ', 'Zi ', 'Tao ', 'Teng ', 'Sui ', 'Bi ', 'Jiao ', 'Hui ', 'Gun ', 'Yin ', 'Gao ', 'Long ', 'Zhi ', 'Yan ', 'She ', 'Man ', 'Ying ', 'Chun ', 'Lu ', 'Lan ', 'Luan ', '[?] ', 'Bin ', 'Tan ', 'Yu ', 'Sou ', 'Hu ', 'Bi ', 'Biao ', 'Zhi ', 'Jiang ', 'Kou ', 'Shen ', 'Shang ', 'Di ', 'Mi ', 'Ao ', 'Lu ', 'Hu ', 'Hu ', 'You ', 'Chan ', 'Fan ', 'Yong ', 'Gun ', 'Man '];
<?php return ['Fa ', 'Ge ', 'He ', 'Kun ', 'Jiu ', 'Yue ', 'Lang ', 'Du ', 'Yu ', 'Yan ', 'Chang ', 'Xi ', 'Wen ', 'Hun ', 'Yan ', 'E ', 'Chan ', 'Lan ', 'Qu ', 'Hui ', 'Kuo ', 'Que ', 'Ge ', 'Tian ', 'Ta ', 'Que ', 'Kan ', 'Huan ', 'Fu ', 'Fu ', 'Le ', 'Dui ', 'Xin ', 'Qian ', 'Wu ', 'Yi ', 'Tuo ', 'Yin ', 'Yang ', 'Dou ', 'E ', 'Sheng ', 'Ban ', 'Pei ', 'Keng ', 'Yun ', 'Ruan ', 'Zhi ', 'Pi ', 'Jing ', 'Fang ', 'Yang ', 'Yin ', 'Zhen ', 'Jie ', 'Cheng ', 'E ', 'Qu ', 'Di ', 'Zu ', 'Zuo ', 'Dian ', 'Ling ', 'A ', 'Tuo ', 'Tuo ', 'Po ', 'Bing ', 'Fu ', 'Ji ', 'Lu ', 'Long ', 'Chen ', 'Xing ', 'Duo ', 'Lou ', 'Mo ', 'Jiang ', 'Shu ', 'Duo ', 'Xian ', 'Er ', 'Gui ', 'Yu ', 'Gai ', 'Shan ', 'Xun ', 'Qiao ', 'Xing ', 'Chun ', 'Fu ', 'Bi ', 'Xia ', 'Shan ', 'Sheng ', 'Zhi ', 'Pu ', 'Dou ', 'Yuan ', 'Zhen ', 'Chu ', 'Xian ', 'Tou ', 'Nie ', 'Yun ', 'Xian ', 'Pei ', 'Pei ', 'Zou ', 'Yi ', 'Dui ', 'Lun ', 'Yin ', 'Ju ', 'Chui ', 'Chen ', 'Pi ', 'Ling ', 'Tao ', 'Xian ', 'Lu ', 'Sheng ', 'Xian ', 'Yin ', 'Zhu ', 'Yang ', 'Reng ', 'Shan ', 'Chong ', 'Yan ', 'Yin ', 'Yu ', 'Ti ', 'Yu ', 'Long ', 'Wei ', 'Wei ', 'Nie ', 'Dui ', 'Sui ', 'An ', 'Huang ', 'Jie ', 'Sui ', 'Yin ', 'Gai ', 'Yan ', 'Hui ', 'Ge ', 'Yun ', 'Wu ', 'Wei ', 'Ai ', 'Xi ', 'Tang ', 'Ji ', 'Zhang ', 'Dao ', 'Ao ', 'Xi ', 'Yin ', '[?] ', 'Rao ', 'Lin ', 'Tui ', 'Deng ', 'Pi ', 'Sui ', 'Sui ', 'Yu ', 'Xian ', 'Fen ', 'Ni ', 'Er ', 'Ji ', 'Dao ', 'Xi ', 'Yin ', 'E ', 'Hui ', 'Long ', 'Xi ', 'Li ', 'Li ', 'Li ', 'Zhui ', 'He ', 'Zhi ', 'Zhun ', 'Jun ', 'Nan ', 'Yi ', 'Que ', 'Yan ', 'Qian ', 'Ya ', 'Xiong ', 'Ya ', 'Ji ', 'Gu ', 'Huan ', 'Zhi ', 'Gou ', 'Jun ', 'Ci ', 'Yong ', 'Ju ', 'Chu ', 'Hu ', 'Za ', 'Luo ', 'Yu ', 'Chou ', 'Diao ', 'Sui ', 'Han ', 'Huo ', 'Shuang ', 'Guan ', 'Chu ', 'Za ', 'Yong ', 'Ji ', 'Xi ', 'Chou ', 'Liu ', 'Li ', 'Nan ', 'Xue ', 'Za ', 'Ji ', 'Ji ', 'Yu ', 'Yu ', 'Xue ', 'Na ', 'Fou ', 'Se ', 'Mu ', 'Wen ', 'Fen ', 'Pang ', 'Yun ', 'Li ', 'Li ', 'Ang ', 'Ling ', 'Lei ', 'An ', 'Bao ', 'Meng ', 'Dian ', 'Dang ', 'Xing ', 'Wu ', 'Zhao '];
<?php return ['ke', 'keg', 'kegg', 'kegs', 'ken', 'kenj', 'kenh', 'ked', 'kel', 'kelg', 'kelm', 'kelb', 'kels', 'kelt', 'kelp', 'kelh', 'kem', 'keb', 'kebs', 'kes', 'kess', 'keng', 'kej', 'kec', 'kek', 'ket', 'kep', 'keh', 'kyeo', 'kyeog', 'kyeogg', 'kyeogs', 'kyeon', 'kyeonj', 'kyeonh', 'kyeod', 'kyeol', 'kyeolg', 'kyeolm', 'kyeolb', 'kyeols', 'kyeolt', 'kyeolp', 'kyeolh', 'kyeom', 'kyeob', 'kyeobs', 'kyeos', 'kyeoss', 'kyeong', 'kyeoj', 'kyeoc', 'kyeok', 'kyeot', 'kyeop', 'kyeoh', 'kye', 'kyeg', 'kyegg', 'kyegs', 'kyen', 'kyenj', 'kyenh', 'kyed', 'kyel', 'kyelg', 'kyelm', 'kyelb', 'kyels', 'kyelt', 'kyelp', 'kyelh', 'kyem', 'kyeb', 'kyebs', 'kyes', 'kyess', 'kyeng', 'kyej', 'kyec', 'kyek', 'kyet', 'kyep', 'kyeh', 'ko', 'kog', 'kogg', 'kogs', 'kon', 'konj', 'konh', 'kod', 'kol', 'kolg', 'kolm', 'kolb', 'kols', 'kolt', 'kolp', 'kolh', 'kom', 'kob', 'kobs', 'kos', 'koss', 'kong', 'koj', 'koc', 'kok', 'kot', 'kop', 'koh', 'kwa', 'kwag', 'kwagg', 'kwags', 'kwan', 'kwanj', 'kwanh', 'kwad', 'kwal', 'kwalg', 'kwalm', 'kwalb', 'kwals', 'kwalt', 'kwalp', 'kwalh', 'kwam', 'kwab', 'kwabs', 'kwas', 'kwass', 'kwang', 'kwaj', 'kwac', 'kwak', 'kwat', 'kwap', 'kwah', 'kwae', 'kwaeg', 'kwaegg', 'kwaegs', 'kwaen', 'kwaenj', 'kwaenh', 'kwaed', 'kwael', 'kwaelg', 'kwaelm', 'kwaelb', 'kwaels', 'kwaelt', 'kwaelp', 'kwaelh', 'kwaem', 'kwaeb', 'kwaebs', 'kwaes', 'kwaess', 'kwaeng', 'kwaej', 'kwaec', 'kwaek', 'kwaet', 'kwaep', 'kwaeh', 'koe', 'koeg', 'koegg', 'koegs', 'koen', 'koenj', 'koenh', 'koed', 'koel', 'koelg', 'koelm', 'koelb', 'koels', 'koelt', 'koelp', 'koelh', 'koem', 'koeb', 'koebs', 'koes', 'koess', 'koeng', 'koej', 'koec', 'koek', 'koet', 'koep', 'koeh', 'kyo', 'kyog', 'kyogg', 'kyogs', 'kyon', 'kyonj', 'kyonh', 'kyod', 'kyol', 'kyolg', 'kyolm', 'kyolb', 'kyols', 'kyolt', 'kyolp', 'kyolh', 'kyom', 'kyob', 'kyobs', 'kyos', 'kyoss', 'kyong', 'kyoj', 'kyoc', 'kyok', 'kyot', 'kyop', 'kyoh', 'ku', 'kug', 'kugg', 'kugs', 'kun', 'kunj', 'kunh', 'kud', 'kul', 'kulg', 'kulm', 'kulb', 'kuls', 'kult', 'kulp', 'kulh', 'kum', 'kub', 'kubs', 'kus', 'kuss', 'kung', 'kuj', 'kuc', 'kuk', 'kut', 'kup', 'kuh', 'kweo', 'kweog', 'kweogg', 'kweogs'];
<?php return ['bols', 'bolt', 'bolp', 'bolh', 'bom', 'bob', 'bobs', 'bos', 'boss', 'bong', 'boj', 'boc', 'bok', 'bot', 'bop', 'boh', 'bwa', 'bwag', 'bwagg', 'bwags', 'bwan', 'bwanj', 'bwanh', 'bwad', 'bwal', 'bwalg', 'bwalm', 'bwalb', 'bwals', 'bwalt', 'bwalp', 'bwalh', 'bwam', 'bwab', 'bwabs', 'bwas', 'bwass', 'bwang', 'bwaj', 'bwac', 'bwak', 'bwat', 'bwap', 'bwah', 'bwae', 'bwaeg', 'bwaegg', 'bwaegs', 'bwaen', 'bwaenj', 'bwaenh', 'bwaed', 'bwael', 'bwaelg', 'bwaelm', 'bwaelb', 'bwaels', 'bwaelt', 'bwaelp', 'bwaelh', 'bwaem', 'bwaeb', 'bwaebs', 'bwaes', 'bwaess', 'bwaeng', 'bwaej', 'bwaec', 'bwaek', 'bwaet', 'bwaep', 'bwaeh', 'boe', 'boeg', 'boegg', 'boegs', 'boen', 'boenj', 'boenh', 'boed', 'boel', 'boelg', 'boelm', 'boelb', 'boels', 'boelt', 'boelp', 'boelh', 'boem', 'boeb', 'boebs', 'boes', 'boess', 'boeng', 'boej', 'boec', 'boek', 'boet', 'boep', 'boeh', 'byo', 'byog', 'byogg', 'byogs', 'byon', 'byonj', 'byonh', 'byod', 'byol', 'byolg', 'byolm', 'byolb', 'byols', 'byolt', 'byolp', 'byolh', 'byom', 'byob', 'byobs', 'byos', 'byoss', 'byong', 'byoj', 'byoc', 'byok', 'byot', 'byop', 'byoh', 'bu', 'bug', 'bugg', 'bugs', 'bun', 'bunj', 'bunh', 'bud', 'bul', 'bulg', 'bulm', 'bulb', 'buls', 'bult', 'bulp', 'bulh', 'bum', 'bub', 'bubs', 'bus', 'buss', 'bung', 'buj', 'buc', 'buk', 'but', 'bup', 'buh', 'bweo', 'bweog', 'bweogg', 'bweogs', 'bweon', 'bweonj', 'bweonh', 'bweod', 'bweol', 'bweolg', 'bweolm', 'bweolb', 'bweols', 'bweolt', 'bweolp', 'bweolh', 'bweom', 'bweob', 'bweobs', 'bweos', 'bweoss', 'bweong', 'bweoj', 'bweoc', 'bweok', 'bweot', 'bweop', 'bweoh', 'bwe', 'bweg', 'bwegg', 'bwegs', 'bwen', 'bwenj', 'bwenh', 'bwed', 'bwel', 'bwelg', 'bwelm', 'bwelb', 'bwels', 'bwelt', 'bwelp', 'bwelh', 'bwem', 'bweb', 'bwebs', 'bwes', 'bwess', 'bweng', 'bwej', 'bwec', 'bwek', 'bwet', 'bwep', 'bweh', 'bwi', 'bwig', 'bwigg', 'bwigs', 'bwin', 'bwinj', 'bwinh', 'bwid', 'bwil', 'bwilg', 'bwilm', 'bwilb', 'bwils', 'bwilt', 'bwilp', 'bwilh', 'bwim', 'bwib', 'bwibs', 'bwis', 'bwiss', 'bwing', 'bwij', 'bwic', 'bwik', 'bwit', 'bwip', 'bwih', 'byu', 'byug', 'byugg', 'byugs', 'byun', 'byunj', 'byunh', 'byud', 'byul', 'byulg', 'byulm', 'byulb', 'byuls', 'byult', 'byulp', 'byulh'];
<?php return ['apartment', 'alpha', 'ampere', 'are', 'inning', 'inch', 'won', 'escudo', 'acre', 'ounce', 'ohm', 'kai-ri', 'carat', 'calorie', 'gallon', 'gamma', 'giga', 'guinea', 'curie', 'guilder', 'kilo', 'kilogram', 'kilometer', 'kilowatt', 'gram', 'gram ton', 'cruzeiro', 'krone', 'case', 'koruna', 'co-op', 'cycle', 'centime', 'shilling', 'centi', 'cent', 'dozen', 'desi', 'dollar', 'ton', 'nano', 'knot', 'heights', 'percent', 'parts', 'barrel', 'piaster', 'picul', 'pico', 'building', 'farad', 'feet', 'bushel', 'franc', 'hectare', 'peso', 'pfennig', 'hertz', 'pence', 'page', 'beta', 'point', 'volt', 'hon', 'pound', 'hall', 'horn', 'micro', 'mile', 'mach', 'mark', 'mansion', 'micron', 'milli', 'millibar', 'mega', 'megaton', 'meter', 'yard', 'yard', 'yuan', 'liter', 'lira', 'rupee', 'ruble', 'rem', 'roentgen', 'watt', '0h', '1h', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h', '12h', '13h', '14h', '15h', '16h', '17h', '18h', '19h', '20h', '21h', '22h', '23h', '24h', 'hPa', 'da', 'AU', 'bar', 'oV', 'pc', 'dm', 'dm^2', 'dm^3', 'IU', 'Heisei', 'Syouwa', 'Taisyou', 'Meiji', 'Inc.', 'pA', 'nA', 'microamp', 'mA', 'kA', 'kB', 'MB', 'GB', 'cal', 'kcal', 'pF', 'nF', 'microFarad', 'microgram', 'mg', 'kg', 'Hz', 'kHz', 'MHz', 'GHz', 'THz', 'microliter', 'ml', 'dl', 'kl', 'fm', 'nm', 'micrometer', 'mm', 'cm', 'km', 'mm^2', 'cm^2', 'm^2', 'km^2', 'mm^3', 'cm^3', 'm^3', 'km^3', 'm/s', 'm/s^2', 'Pa', 'kPa', 'MPa', 'GPa', 'rad', 'rad/s', 'rad/s^2', 'ps', 'ns', 'microsecond', 'ms', 'pV', 'nV', 'microvolt', 'mV', 'kV', 'MV', 'pW', 'nW', 'microwatt', 'mW', 'kW', 'MW', 'kOhm', 'MOhm', 'a.m.', 'Bq', 'cc', 'cd', 'C/kg', 'Co.', 'dB', 'Gy', 'ha', 'HP', 'in', 'K.K.', 'KM', 'kt', 'lm', 'ln', 'log', 'lx', 'mb', 'mil', 'mol', 'pH', 'p.m.', 'PPM', 'PR', 'sr', 'Sv', 'Wb', '[?]', '[?]', '1d', '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', '10d', '11d', '12d', '13d', '14d', '15d', '16d', '17d', '18d', '19d', '20d', '21d', '22d', '23d', '24d', '25d', '26d', '27d', '28d', '29d', '30d', '31d', 'gal'];
<?php return ['ddwim', 'ddwib', 'ddwibs', 'ddwis', 'ddwiss', 'ddwing', 'ddwij', 'ddwic', 'ddwik', 'ddwit', 'ddwip', 'ddwih', 'ddyu', 'ddyug', 'ddyugg', 'ddyugs', 'ddyun', 'ddyunj', 'ddyunh', 'ddyud', 'ddyul', 'ddyulg', 'ddyulm', 'ddyulb', 'ddyuls', 'ddyult', 'ddyulp', 'ddyulh', 'ddyum', 'ddyub', 'ddyubs', 'ddyus', 'ddyuss', 'ddyung', 'ddyuj', 'ddyuc', 'ddyuk', 'ddyut', 'ddyup', 'ddyuh', 'ddeu', 'ddeug', 'ddeugg', 'ddeugs', 'ddeun', 'ddeunj', 'ddeunh', 'ddeud', 'ddeul', 'ddeulg', 'ddeulm', 'ddeulb', 'ddeuls', 'ddeult', 'ddeulp', 'ddeulh', 'ddeum', 'ddeub', 'ddeubs', 'ddeus', 'ddeuss', 'ddeung', 'ddeuj', 'ddeuc', 'ddeuk', 'ddeut', 'ddeup', 'ddeuh', 'ddyi', 'ddyig', 'ddyigg', 'ddyigs', 'ddyin', 'ddyinj', 'ddyinh', 'ddyid', 'ddyil', 'ddyilg', 'ddyilm', 'ddyilb', 'ddyils', 'ddyilt', 'ddyilp', 'ddyilh', 'ddyim', 'ddyib', 'ddyibs', 'ddyis', 'ddyiss', 'ddying', 'ddyij', 'ddyic', 'ddyik', 'ddyit', 'ddyip', 'ddyih', 'ddi', 'ddig', 'ddigg', 'ddigs', 'ddin', 'ddinj', 'ddinh', 'ddid', 'ddil', 'ddilg', 'ddilm', 'ddilb', 'ddils', 'ddilt', 'ddilp', 'ddilh', 'ddim', 'ddib', 'ddibs', 'ddis', 'ddiss', 'dding', 'ddij', 'ddic', 'ddik', 'ddit', 'ddip', 'ddih', 'ra', 'rag', 'ragg', 'rags', 'ran', 'ranj', 'ranh', 'rad', 'ral', 'ralg', 'ralm', 'ralb', 'rals', 'ralt', 'ralp', 'ralh', 'ram', 'rab', 'rabs', 'ras', 'rass', 'rang', 'raj', 'rac', 'rak', 'rat', 'rap', 'rah', 'rae', 'raeg', 'raegg', 'raegs', 'raen', 'raenj', 'raenh', 'raed', 'rael', 'raelg', 'raelm', 'raelb', 'raels', 'raelt', 'raelp', 'raelh', 'raem', 'raeb', 'raebs', 'raes', 'raess', 'raeng', 'raej', 'raec', 'raek', 'raet', 'raep', 'raeh', 'rya', 'ryag', 'ryagg', 'ryags', 'ryan', 'ryanj', 'ryanh', 'ryad', 'ryal', 'ryalg', 'ryalm', 'ryalb', 'ryals', 'ryalt', 'ryalp', 'ryalh', 'ryam', 'ryab', 'ryabs', 'ryas', 'ryass', 'ryang', 'ryaj', 'ryac', 'ryak', 'ryat', 'ryap', 'ryah', 'ryae', 'ryaeg', 'ryaegg', 'ryaegs', 'ryaen', 'ryaenj', 'ryaenh', 'ryaed', 'ryael', 'ryaelg', 'ryaelm', 'ryaelb', 'ryaels', 'ryaelt', 'ryaelp', 'ryaelh', 'ryaem', 'ryaeb', 'ryaebs', 'ryaes', 'ryaess', 'ryaeng', 'ryaej', 'ryaec', 'ryaek', 'ryaet', 'ryaep', 'ryaeh', 'reo', 'reog', 'reogg', 'reogs', 'reon', 'reonj', 'reonh', 'reod', 'reol', 'reolg', 'reolm', 'reolb', 'reols', 'reolt', 'reolp', 'reolh', 'reom', 'reob', 'reobs', 'reos'];
<?php return ['Ruo ', 'Bei ', 'E ', 'Yu ', 'Juan ', 'Yu ', 'Yun ', 'Hou ', 'Kui ', 'Xiang ', 'Xiang ', 'Sou ', 'Tang ', 'Ming ', 'Xi ', 'Ru ', 'Chu ', 'Zi ', 'Zou ', 'Ju ', 'Wu ', 'Xiang ', 'Yun ', 'Hao ', 'Yong ', 'Bi ', 'Mo ', 'Chao ', 'Fu ', 'Liao ', 'Yin ', 'Zhuan ', 'Hu ', 'Qiao ', 'Yan ', 'Zhang ', 'Fan ', 'Qiao ', 'Xu ', 'Deng ', 'Bi ', 'Xin ', 'Bi ', 'Ceng ', 'Wei ', 'Zheng ', 'Mao ', 'Shan ', 'Lin ', 'Po ', 'Dan ', 'Meng ', 'Ye ', 'Cao ', 'Kuai ', 'Feng ', 'Meng ', 'Zou ', 'Kuang ', 'Lian ', 'Zan ', 'Chan ', 'You ', 'Qi ', 'Yan ', 'Chan ', 'Zan ', 'Ling ', 'Huan ', 'Xi ', 'Feng ', 'Zan ', 'Li ', 'You ', 'Ding ', 'Qiu ', 'Zhuo ', 'Pei ', 'Zhou ', 'Yi ', 'Hang ', 'Yu ', 'Jiu ', 'Yan ', 'Zui ', 'Mao ', 'Dan ', 'Xu ', 'Tou ', 'Zhen ', 'Fen ', 'Sakenomoto ', '[?] ', 'Yun ', 'Tai ', 'Tian ', 'Qia ', 'Tuo ', 'Zuo ', 'Han ', 'Gu ', 'Su ', 'Po ', 'Chou ', 'Zai ', 'Ming ', 'Luo ', 'Chuo ', 'Chou ', 'You ', 'Tong ', 'Zhi ', 'Xian ', 'Jiang ', 'Cheng ', 'Yin ', 'Tu ', 'Xiao ', 'Mei ', 'Ku ', 'Suan ', 'Lei ', 'Pu ', 'Zui ', 'Hai ', 'Yan ', 'Xi ', 'Niang ', 'Wei ', 'Lu ', 'Lan ', 'Yan ', 'Tao ', 'Pei ', 'Zhan ', 'Chun ', 'Tan ', 'Zui ', 'Chuo ', 'Cu ', 'Kun ', 'Ti ', 'Mian ', 'Du ', 'Hu ', 'Xu ', 'Xing ', 'Tan ', 'Jiu ', 'Chun ', 'Yun ', 'Po ', 'Ke ', 'Sou ', 'Mi ', 'Quan ', 'Chou ', 'Cuo ', 'Yun ', 'Yong ', 'Ang ', 'Zha ', 'Hai ', 'Tang ', 'Jiang ', 'Piao ', 'Shan ', 'Yu ', 'Li ', 'Zao ', 'Lao ', 'Yi ', 'Jiang ', 'Pu ', 'Jiao ', 'Xi ', 'Tan ', 'Po ', 'Nong ', 'Yi ', 'Li ', 'Ju ', 'Jiao ', 'Yi ', 'Niang ', 'Ru ', 'Xun ', 'Chou ', 'Yan ', 'Ling ', 'Mi ', 'Mi ', 'Niang ', 'Xin ', 'Jiao ', 'Xi ', 'Mi ', 'Yan ', 'Bian ', 'Cai ', 'Shi ', 'You ', 'Shi ', 'Shi ', 'Li ', 'Zhong ', 'Ye ', 'Liang ', 'Li ', 'Jin ', 'Jin ', 'Qiu ', 'Yi ', 'Diao ', 'Dao ', 'Zhao ', 'Ding ', 'Po ', 'Qiu ', 'He ', 'Fu ', 'Zhen ', 'Zhi ', 'Ba ', 'Luan ', 'Fu ', 'Nai ', 'Diao ', 'Shan ', 'Qiao ', 'Kou ', 'Chuan ', 'Zi ', 'Fan ', 'Yu ', 'Hua ', 'Han ', 'Gong ', 'Qi ', 'Mang ', 'Ri ', 'Di ', 'Si ', 'Xi ', 'Yi ', 'Chai ', 'Shi ', 'Tu ', 'Xi ', 'Nu ', 'Qian ', 'Ishiyumi ', 'Jian ', 'Pi ', 'Ye ', 'Yin '];
<?php return ['kweon', 'kweonj', 'kweonh', 'kweod', 'kweol', 'kweolg', 'kweolm', 'kweolb', 'kweols', 'kweolt', 'kweolp', 'kweolh', 'kweom', 'kweob', 'kweobs', 'kweos', 'kweoss', 'kweong', 'kweoj', 'kweoc', 'kweok', 'kweot', 'kweop', 'kweoh', 'kwe', 'kweg', 'kwegg', 'kwegs', 'kwen', 'kwenj', 'kwenh', 'kwed', 'kwel', 'kwelg', 'kwelm', 'kwelb', 'kwels', 'kwelt', 'kwelp', 'kwelh', 'kwem', 'kweb', 'kwebs', 'kwes', 'kwess', 'kweng', 'kwej', 'kwec', 'kwek', 'kwet', 'kwep', 'kweh', 'kwi', 'kwig', 'kwigg', 'kwigs', 'kwin', 'kwinj', 'kwinh', 'kwid', 'kwil', 'kwilg', 'kwilm', 'kwilb', 'kwils', 'kwilt', 'kwilp', 'kwilh', 'kwim', 'kwib', 'kwibs', 'kwis', 'kwiss', 'kwing', 'kwij', 'kwic', 'kwik', 'kwit', 'kwip', 'kwih', 'kyu', 'kyug', 'kyugg', 'kyugs', 'kyun', 'kyunj', 'kyunh', 'kyud', 'kyul', 'kyulg', 'kyulm', 'kyulb', 'kyuls', 'kyult', 'kyulp', 'kyulh', 'kyum', 'kyub', 'kyubs', 'kyus', 'kyuss', 'kyung', 'kyuj', 'kyuc', 'kyuk', 'kyut', 'kyup', 'kyuh', 'keu', 'keug', 'keugg', 'keugs', 'keun', 'keunj', 'keunh', 'keud', 'keul', 'keulg', 'keulm', 'keulb', 'keuls', 'keult', 'keulp', 'keulh', 'keum', 'keub', 'keubs', 'keus', 'keuss', 'keung', 'keuj', 'keuc', 'keuk', 'keut', 'keup', 'keuh', 'kyi', 'kyig', 'kyigg', 'kyigs', 'kyin', 'kyinj', 'kyinh', 'kyid', 'kyil', 'kyilg', 'kyilm', 'kyilb', 'kyils', 'kyilt', 'kyilp', 'kyilh', 'kyim', 'kyib', 'kyibs', 'kyis', 'kyiss', 'kying', 'kyij', 'kyic', 'kyik', 'kyit', 'kyip', 'kyih', 'ki', 'kig', 'kigg', 'kigs', 'kin', 'kinj', 'kinh', 'kid', 'kil', 'kilg', 'kilm', 'kilb', 'kils', 'kilt', 'kilp', 'kilh', 'kim', 'kib', 'kibs', 'kis', 'kiss', 'king', 'kij', 'kic', 'kik', 'kit', 'kip', 'kih', 'ta', 'tag', 'tagg', 'tags', 'tan', 'tanj', 'tanh', 'tad', 'tal', 'talg', 'talm', 'talb', 'tals', 'talt', 'talp', 'talh', 'tam', 'tab', 'tabs', 'tas', 'tass', 'tang', 'taj', 'tac', 'tak', 'tat', 'tap', 'tah', 'tae', 'taeg', 'taegg', 'taegs', 'taen', 'taenj', 'taenh', 'taed', 'tael', 'taelg', 'taelm', 'taelb', 'taels', 'taelt', 'taelp', 'taelh', 'taem', 'taeb', 'taebs', 'taes', 'taess', 'taeng', 'taej', 'taec', 'taek', 'taet', 'taep', 'taeh', 'tya', 'tyag', 'tyagg', 'tyags', 'tyan', 'tyanj', 'tyanh', 'tyad'];
<?php return ['tim', 'tib', 'tibs', 'tis', 'tiss', 'ting', 'tij', 'tic', 'tik', 'tit', 'tip', 'tih', 'pa', 'pag', 'pagg', 'pags', 'pan', 'panj', 'panh', 'pad', 'pal', 'palg', 'palm', 'palb', 'pals', 'palt', 'palp', 'palh', 'pam', 'pab', 'pabs', 'pas', 'pass', 'pang', 'paj', 'pac', 'pak', 'pat', 'pap', 'pah', 'pae', 'paeg', 'paegg', 'paegs', 'paen', 'paenj', 'paenh', 'paed', 'pael', 'paelg', 'paelm', 'paelb', 'paels', 'paelt', 'paelp', 'paelh', 'paem', 'paeb', 'paebs', 'paes', 'paess', 'paeng', 'paej', 'paec', 'paek', 'paet', 'paep', 'paeh', 'pya', 'pyag', 'pyagg', 'pyags', 'pyan', 'pyanj', 'pyanh', 'pyad', 'pyal', 'pyalg', 'pyalm', 'pyalb', 'pyals', 'pyalt', 'pyalp', 'pyalh', 'pyam', 'pyab', 'pyabs', 'pyas', 'pyass', 'pyang', 'pyaj', 'pyac', 'pyak', 'pyat', 'pyap', 'pyah', 'pyae', 'pyaeg', 'pyaegg', 'pyaegs', 'pyaen', 'pyaenj', 'pyaenh', 'pyaed', 'pyael', 'pyaelg', 'pyaelm', 'pyaelb', 'pyaels', 'pyaelt', 'pyaelp', 'pyaelh', 'pyaem', 'pyaeb', 'pyaebs', 'pyaes', 'pyaess', 'pyaeng', 'pyaej', 'pyaec', 'pyaek', 'pyaet', 'pyaep', 'pyaeh', 'peo', 'peog', 'peogg', 'peogs', 'peon', 'peonj', 'peonh', 'peod', 'peol', 'peolg', 'peolm', 'peolb', 'peols', 'peolt', 'peolp', 'peolh', 'peom', 'peob', 'peobs', 'peos', 'peoss', 'peong', 'peoj', 'peoc', 'peok', 'peot', 'peop', 'peoh', 'pe', 'peg', 'pegg', 'pegs', 'pen', 'penj', 'penh', 'ped', 'pel', 'pelg', 'pelm', 'pelb', 'pels', 'pelt', 'pelp', 'pelh', 'pem', 'peb', 'pebs', 'pes', 'pess', 'peng', 'pej', 'pec', 'pek', 'pet', 'pep', 'peh', 'pyeo', 'pyeog', 'pyeogg', 'pyeogs', 'pyeon', 'pyeonj', 'pyeonh', 'pyeod', 'pyeol', 'pyeolg', 'pyeolm', 'pyeolb', 'pyeols', 'pyeolt', 'pyeolp', 'pyeolh', 'pyeom', 'pyeob', 'pyeobs', 'pyeos', 'pyeoss', 'pyeong', 'pyeoj', 'pyeoc', 'pyeok', 'pyeot', 'pyeop', 'pyeoh', 'pye', 'pyeg', 'pyegg', 'pyegs', 'pyen', 'pyenj', 'pyenh', 'pyed', 'pyel', 'pyelg', 'pyelm', 'pyelb', 'pyels', 'pyelt', 'pyelp', 'pyelh', 'pyem', 'pyeb', 'pyebs', 'pyes', 'pyess', 'pyeng', 'pyej', 'pyec', 'pyek', 'pyet', 'pyep', 'pyeh', 'po', 'pog', 'pogg', 'pogs', 'pon', 'ponj', 'ponh', 'pod', 'pol', 'polg', 'polm', 'polb', 'pols', 'polt', 'polp', 'polh', 'pom', 'pob', 'pobs', 'pos'];
<?php return ['Mie ', 'Xu ', 'Mang ', 'Chi ', 'Ge ', 'Xuan ', 'Yao ', 'Zi ', 'He ', 'Ji ', 'Diao ', 'Cun ', 'Tong ', 'Ming ', 'Hou ', 'Li ', 'Tu ', 'Xiang ', 'Zha ', 'Xia ', 'Ye ', 'Lu ', 'A ', 'Ma ', 'Ou ', 'Xue ', 'Yi ', 'Jun ', 'Chou ', 'Lin ', 'Tun ', 'Yin ', 'Fei ', 'Bi ', 'Qin ', 'Qin ', 'Jie ', 'Bu ', 'Fou ', 'Ba ', 'Dun ', 'Fen ', 'E ', 'Han ', 'Ting ', 'Hang ', 'Shun ', 'Qi ', 'Hong ', 'Zhi ', 'Shen ', 'Wu ', 'Wu ', 'Chao ', 'Ne ', 'Xue ', 'Xi ', 'Chui ', 'Dou ', 'Wen ', 'Hou ', 'Ou ', 'Wu ', 'Gao ', 'Ya ', 'Jun ', 'Lu ', 'E ', 'Ge ', 'Mei ', 'Ai ', 'Qi ', 'Cheng ', 'Wu ', 'Gao ', 'Fu ', 'Jiao ', 'Hong ', 'Chi ', 'Sheng ', 'Ne ', 'Tun ', 'Fu ', 'Yi ', 'Dai ', 'Ou ', 'Li ', 'Bai ', 'Yuan ', 'Kuai ', '[?] ', 'Qiang ', 'Wu ', 'E ', 'Shi ', 'Quan ', 'Pen ', 'Wen ', 'Ni ', 'M ', 'Ling ', 'Ran ', 'You ', 'Di ', 'Zhou ', 'Shi ', 'Zhou ', 'Tie ', 'Xi ', 'Yi ', 'Qi ', 'Ping ', 'Zi ', 'Gu ', 'Zi ', 'Wei ', 'Xu ', 'He ', 'Nao ', 'Xia ', 'Pei ', 'Yi ', 'Xiao ', 'Shen ', 'Hu ', 'Ming ', 'Da ', 'Qu ', 'Ju ', 'Gem ', 'Za ', 'Tuo ', 'Duo ', 'Pou ', 'Pao ', 'Bi ', 'Fu ', 'Yang ', 'He ', 'Zha ', 'He ', 'Hai ', 'Jiu ', 'Yong ', 'Fu ', 'Que ', 'Zhou ', 'Wa ', 'Ka ', 'Gu ', 'Ka ', 'Zuo ', 'Bu ', 'Long ', 'Dong ', 'Ning ', 'Tha ', 'Si ', 'Xian ', 'Huo ', 'Qi ', 'Er ', 'E ', 'Guang ', 'Zha ', 'Xi ', 'Yi ', 'Lie ', 'Zi ', 'Mie ', 'Mi ', 'Zhi ', 'Yao ', 'Ji ', 'Zhou ', 'Ge ', 'Shuai ', 'Zan ', 'Xiao ', 'Ke ', 'Hui ', 'Kua ', 'Huai ', 'Tao ', 'Xian ', 'E ', 'Xuan ', 'Xiu ', 'Wai ', 'Yan ', 'Lao ', 'Yi ', 'Ai ', 'Pin ', 'Shen ', 'Tong ', 'Hong ', 'Xiong ', 'Chi ', 'Wa ', 'Ha ', 'Zai ', 'Yu ', 'Di ', 'Pai ', 'Xiang ', 'Ai ', 'Hen ', 'Kuang ', 'Ya ', 'Da ', 'Xiao ', 'Bi ', 'Yue ', '[?] ', 'Hua ', 'Sasou ', 'Kuai ', 'Duo ', '[?] ', 'Ji ', 'Nong ', 'Mou ', 'Yo ', 'Hao ', 'Yuan ', 'Long ', 'Pou ', 'Mang ', 'Ge ', 'E ', 'Chi ', 'Shao ', 'Li ', 'Na ', 'Zu ', 'He ', 'Ku ', 'Xiao ', 'Xian ', 'Lao ', 'Bo ', 'Zhe ', 'Zha ', 'Liang ', 'Ba ', 'Mie ', 'Le ', 'Sui ', 'Fou ', 'Bu ', 'Han ', 'Heng ', 'Geng ', 'Shuo ', 'Ge '];
<?php return ['Bu ', 'Zhang ', 'Luo ', 'Jiang ', 'Man ', 'Yan ', 'Ling ', 'Ji ', 'Piao ', 'Gun ', 'Han ', 'Di ', 'Su ', 'Lu ', 'She ', 'Shang ', 'Di ', 'Mie ', 'Xun ', 'Man ', 'Bo ', 'Di ', 'Cuo ', 'Zhe ', 'Sen ', 'Xuan ', 'Wei ', 'Hu ', 'Ao ', 'Mi ', 'Lou ', 'Cu ', 'Zhong ', 'Cai ', 'Po ', 'Jiang ', 'Mi ', 'Cong ', 'Niao ', 'Hui ', 'Jun ', 'Yin ', 'Jian ', 'Yan ', 'Shu ', 'Yin ', 'Kui ', 'Chen ', 'Hu ', 'Sha ', 'Kou ', 'Qian ', 'Ma ', 'Zang ', 'Sonoko ', 'Qiang ', 'Dou ', 'Lian ', 'Lin ', 'Kou ', 'Ai ', 'Bi ', 'Li ', 'Wei ', 'Ji ', 'Xun ', 'Sheng ', 'Fan ', 'Meng ', 'Ou ', 'Chan ', 'Dian ', 'Xun ', 'Jiao ', 'Rui ', 'Rui ', 'Lei ', 'Yu ', 'Qiao ', 'Chu ', 'Hua ', 'Jian ', 'Mai ', 'Yun ', 'Bao ', 'You ', 'Qu ', 'Lu ', 'Rao ', 'Hui ', 'E ', 'Teng ', 'Fei ', 'Jue ', 'Zui ', 'Fa ', 'Ru ', 'Fen ', 'Kui ', 'Shun ', 'Rui ', 'Ya ', 'Xu ', 'Fu ', 'Jue ', 'Dang ', 'Wu ', 'Tong ', 'Si ', 'Xiao ', 'Xi ', 'Long ', 'Yun ', '[?] ', 'Qi ', 'Jian ', 'Yun ', 'Sun ', 'Ling ', 'Yu ', 'Xia ', 'Yong ', 'Ji ', 'Hong ', 'Si ', 'Nong ', 'Lei ', 'Xuan ', 'Yun ', 'Yu ', 'Xi ', 'Hao ', 'Bo ', 'Hao ', 'Ai ', 'Wei ', 'Hui ', 'Wei ', 'Ji ', 'Ci ', 'Xiang ', 'Luan ', 'Mie ', 'Yi ', 'Leng ', 'Jiang ', 'Can ', 'Shen ', 'Qiang ', 'Lian ', 'Ke ', 'Yuan ', 'Da ', 'Ti ', 'Tang ', 'Xie ', 'Bi ', 'Zhan ', 'Sun ', 'Lian ', 'Fan ', 'Ding ', 'Jie ', 'Gu ', 'Xie ', 'Shu ', 'Jian ', 'Kao ', 'Hong ', 'Sa ', 'Xin ', 'Xun ', 'Yao ', 'Hie ', 'Sou ', 'Shu ', 'Xun ', 'Dui ', 'Pin ', 'Wei ', 'Neng ', 'Chou ', 'Mai ', 'Ru ', 'Piao ', 'Tai ', 'Qi ', 'Zao ', 'Chen ', 'Zhen ', 'Er ', 'Ni ', 'Ying ', 'Gao ', 'Cong ', 'Xiao ', 'Qi ', 'Fa ', 'Jian ', 'Xu ', 'Kui ', 'Jie ', 'Bian ', 'Diao ', 'Mi ', 'Lan ', 'Jin ', 'Cang ', 'Miao ', 'Qiong ', 'Qie ', 'Xian ', '[?] ', 'Ou ', 'Xian ', 'Su ', 'Lu ', 'Yi ', 'Xu ', 'Xie ', 'Li ', 'Yi ', 'La ', 'Lei ', 'Xiao ', 'Di ', 'Zhi ', 'Bei ', 'Teng ', 'Yao ', 'Mo ', 'Huan ', 'Piao ', 'Fan ', 'Sou ', 'Tan ', 'Tui ', 'Qiong ', 'Qiao ', 'Wei ', 'Liu ', 'Hui ', '[?] ', 'Gao ', 'Yun ', '[?] ', 'Li ', 'Shu ', 'Chu ', 'Ai ', 'Lin ', 'Zao ', 'Xuan ', 'Chen ', 'Lai ', 'Huo '];
<?php return ['Shou ', 'Yi ', 'Zhi ', 'Gu ', 'Chu ', 'Jiang ', 'Feng ', 'Bei ', 'Cay ', 'Bian ', 'Sui ', 'Qun ', 'Ling ', 'Fu ', 'Zuo ', 'Xia ', 'Xiong ', '[?] ', 'Nao ', 'Xia ', 'Kui ', 'Xi ', 'Wai ', 'Yuan ', 'Mao ', 'Su ', 'Duo ', 'Duo ', 'Ye ', 'Qing ', 'Uys ', 'Gou ', 'Gou ', 'Qi ', 'Meng ', 'Meng ', 'Yin ', 'Huo ', 'Chen ', 'Da ', 'Ze ', 'Tian ', 'Tai ', 'Fu ', 'Guai ', 'Yao ', 'Yang ', 'Hang ', 'Gao ', 'Shi ', 'Ben ', 'Tai ', 'Tou ', 'Yan ', 'Bi ', 'Yi ', 'Kua ', 'Jia ', 'Duo ', 'Kwu ', 'Kuang ', 'Yun ', 'Jia ', 'Pa ', 'En ', 'Lian ', 'Huan ', 'Di ', 'Yan ', 'Pao ', 'Quan ', 'Qi ', 'Nai ', 'Feng ', 'Xie ', 'Fen ', 'Dian ', '[?] ', 'Kui ', 'Zou ', 'Huan ', 'Qi ', 'Kai ', 'Zha ', 'Ben ', 'Yi ', 'Jiang ', 'Tao ', 'Zang ', 'Ben ', 'Xi ', 'Xiang ', 'Fei ', 'Diao ', 'Xun ', 'Keng ', 'Dian ', 'Ao ', 'She ', 'Weng ', 'Pan ', 'Ao ', 'Wu ', 'Ao ', 'Jiang ', 'Lian ', 'Duo ', 'Yun ', 'Jiang ', 'Shi ', 'Fen ', 'Huo ', 'Bi ', 'Lian ', 'Duo ', 'Nu ', 'Nu ', 'Ding ', 'Nai ', 'Qian ', 'Jian ', 'Ta ', 'Jiu ', 'Nan ', 'Cha ', 'Hao ', 'Xian ', 'Fan ', 'Ji ', 'Shuo ', 'Ru ', 'Fei ', 'Wang ', 'Hong ', 'Zhuang ', 'Fu ', 'Ma ', 'Dan ', 'Ren ', 'Fu ', 'Jing ', 'Yan ', 'Xie ', 'Wen ', 'Zhong ', 'Pa ', 'Du ', 'Ji ', 'Keng ', 'Zhong ', 'Yao ', 'Jin ', 'Yun ', 'Miao ', 'Pei ', 'Shi ', 'Yue ', 'Zhuang ', 'Niu ', 'Yan ', 'Na ', 'Xin ', 'Fen ', 'Bi ', 'Yu ', 'Tuo ', 'Feng ', 'Yuan ', 'Fang ', 'Wu ', 'Yu ', 'Gui ', 'Du ', 'Ba ', 'Ni ', 'Zhou ', 'Zhuo ', 'Zhao ', 'Da ', 'Nai ', 'Yuan ', 'Tou ', 'Xuan ', 'Zhi ', 'E ', 'Mei ', 'Mo ', 'Qi ', 'Bi ', 'Shen ', 'Qie ', 'E ', 'He ', 'Xu ', 'Fa ', 'Zheng ', 'Min ', 'Ban ', 'Mu ', 'Fu ', 'Ling ', 'Zi ', 'Zi ', 'Shi ', 'Ran ', 'Shan ', 'Yang ', 'Man ', 'Jie ', 'Gu ', 'Si ', 'Xing ', 'Wei ', 'Zi ', 'Ju ', 'Shan ', 'Pin ', 'Ren ', 'Yao ', 'Tong ', 'Jiang ', 'Shu ', 'Ji ', 'Gai ', 'Shang ', 'Kuo ', 'Juan ', 'Jiao ', 'Gou ', 'Mu ', 'Jian ', 'Jian ', 'Yi ', 'Nian ', 'Zhi ', 'Ji ', 'Ji ', 'Xian ', 'Heng ', 'Guang ', 'Jun ', 'Kua ', 'Yan ', 'Ming ', 'Lie ', 'Pei ', 'Yan ', 'You ', 'Yan ', 'Cha ', 'Shen ', 'Yin ', 'Chi ', 'Gui ', 'Quan ', 'Zi '];
<?php return ['ga', 'gag', 'gagg', 'gags', 'gan', 'ganj', 'ganh', 'gad', 'gal', 'galg', 'galm', 'galb', 'gals', 'galt', 'galp', 'galh', 'gam', 'gab', 'gabs', 'gas', 'gass', 'gang', 'gaj', 'gac', 'gak', 'gat', 'gap', 'gah', 'gae', 'gaeg', 'gaegg', 'gaegs', 'gaen', 'gaenj', 'gaenh', 'gaed', 'gael', 'gaelg', 'gaelm', 'gaelb', 'gaels', 'gaelt', 'gaelp', 'gaelh', 'gaem', 'gaeb', 'gaebs', 'gaes', 'gaess', 'gaeng', 'gaej', 'gaec', 'gaek', 'gaet', 'gaep', 'gaeh', 'gya', 'gyag', 'gyagg', 'gyags', 'gyan', 'gyanj', 'gyanh', 'gyad', 'gyal', 'gyalg', 'gyalm', 'gyalb', 'gyals', 'gyalt', 'gyalp', 'gyalh', 'gyam', 'gyab', 'gyabs', 'gyas', 'gyass', 'gyang', 'gyaj', 'gyac', 'gyak', 'gyat', 'gyap', 'gyah', 'gyae', 'gyaeg', 'gyaegg', 'gyaegs', 'gyaen', 'gyaenj', 'gyaenh', 'gyaed', 'gyael', 'gyaelg', 'gyaelm', 'gyaelb', 'gyaels', 'gyaelt', 'gyaelp', 'gyaelh', 'gyaem', 'gyaeb', 'gyaebs', 'gyaes', 'gyaess', 'gyaeng', 'gyaej', 'gyaec', 'gyaek', 'gyaet', 'gyaep', 'gyaeh', 'geo', 'geog', 'geogg', 'geogs', 'geon', 'geonj', 'geonh', 'geod', 'geol', 'geolg', 'geolm', 'geolb', 'geols', 'geolt', 'geolp', 'geolh', 'geom', 'geob', 'geobs', 'geos', 'geoss', 'geong', 'geoj', 'geoc', 'geok', 'geot', 'geop', 'geoh', 'ge', 'geg', 'gegg', 'gegs', 'gen', 'genj', 'genh', 'ged', 'gel', 'gelg', 'gelm', 'gelb', 'gels', 'gelt', 'gelp', 'gelh', 'gem', 'geb', 'gebs', 'ges', 'gess', 'geng', 'gej', 'gec', 'gek', 'get', 'gep', 'geh', 'gyeo', 'gyeog', 'gyeogg', 'gyeogs', 'gyeon', 'gyeonj', 'gyeonh', 'gyeod', 'gyeol', 'gyeolg', 'gyeolm', 'gyeolb', 'gyeols', 'gyeolt', 'gyeolp', 'gyeolh', 'gyeom', 'gyeob', 'gyeobs', 'gyeos', 'gyeoss', 'gyeong', 'gyeoj', 'gyeoc', 'gyeok', 'gyeot', 'gyeop', 'gyeoh', 'gye', 'gyeg', 'gyegg', 'gyegs', 'gyen', 'gyenj', 'gyenh', 'gyed', 'gyel', 'gyelg', 'gyelm', 'gyelb', 'gyels', 'gyelt', 'gyelp', 'gyelh', 'gyem', 'gyeb', 'gyebs', 'gyes', 'gyess', 'gyeng', 'gyej', 'gyec', 'gyek', 'gyet', 'gyep', 'gyeh', 'go', 'gog', 'gogg', 'gogs', 'gon', 'gonj', 'gonh', 'god', 'gol', 'golg', 'golm', 'golb', 'gols', 'golt', 'golp', 'golh', 'gom', 'gob', 'gobs', 'gos', 'goss', 'gong', 'goj', 'goc', 'gok', 'got', 'gop', 'goh', 'gwa', 'gwag', 'gwagg', 'gwags'];
<?php return ['Zhui ', 'Ping ', 'Bian ', 'Zhou ', 'Zhen ', 'Senchigura ', 'Ci ', 'Ying ', 'Qi ', 'Xian ', 'Lou ', 'Di ', 'Ou ', 'Meng ', 'Zhuan ', 'Peng ', 'Lin ', 'Zeng ', 'Wu ', 'Pi ', 'Dan ', 'Weng ', 'Ying ', 'Yan ', 'Gan ', 'Dai ', 'Shen ', 'Tian ', 'Tian ', 'Han ', 'Chang ', 'Sheng ', 'Qing ', 'Sheng ', 'Chan ', 'Chan ', 'Rui ', 'Sheng ', 'Su ', 'Sen ', 'Yong ', 'Shuai ', 'Lu ', 'Fu ', 'Yong ', 'Beng ', 'Feng ', 'Ning ', 'Tian ', 'You ', 'Jia ', 'Shen ', 'Zha ', 'Dian ', 'Fu ', 'Nan ', 'Dian ', 'Ping ', 'Ting ', 'Hua ', 'Ting ', 'Quan ', 'Zi ', 'Meng ', 'Bi ', 'Qi ', 'Liu ', 'Xun ', 'Liu ', 'Chang ', 'Mu ', 'Yun ', 'Fan ', 'Fu ', 'Geng ', 'Tian ', 'Jie ', 'Jie ', 'Quan ', 'Wei ', 'Fu ', 'Tian ', 'Mu ', 'Tap ', 'Pan ', 'Jiang ', 'Wa ', 'Da ', 'Nan ', 'Liu ', 'Ben ', 'Zhen ', 'Chu ', 'Mu ', 'Mu ', 'Ce ', 'Cen ', 'Gai ', 'Bi ', 'Da ', 'Zhi ', 'Lue ', 'Qi ', 'Lue ', 'Pan ', 'Kesa ', 'Fan ', 'Hua ', 'Yu ', 'Yu ', 'Mu ', 'Jun ', 'Yi ', 'Liu ', 'Yu ', 'Die ', 'Chou ', 'Hua ', 'Dang ', 'Chuo ', 'Ji ', 'Wan ', 'Jiang ', 'Sheng ', 'Chang ', 'Tuan ', 'Lei ', 'Ji ', 'Cha ', 'Liu ', 'Tatamu ', 'Tuan ', 'Lin ', 'Jiang ', 'Jiang ', 'Chou ', 'Bo ', 'Die ', 'Die ', 'Pi ', 'Nie ', 'Dan ', 'Shu ', 'Shu ', 'Zhi ', 'Yi ', 'Chuang ', 'Nai ', 'Ding ', 'Bi ', 'Jie ', 'Liao ', 'Gong ', 'Ge ', 'Jiu ', 'Zhou ', 'Xia ', 'Shan ', 'Xu ', 'Nue ', 'Li ', 'Yang ', 'Chen ', 'You ', 'Ba ', 'Jie ', 'Jue ', 'Zhi ', 'Xia ', 'Cui ', 'Bi ', 'Yi ', 'Li ', 'Zong ', 'Chuang ', 'Feng ', 'Zhu ', 'Pao ', 'Pi ', 'Gan ', 'Ke ', 'Ci ', 'Xie ', 'Qi ', 'Dan ', 'Zhen ', 'Fa ', 'Zhi ', 'Teng ', 'Ju ', 'Ji ', 'Fei ', 'Qu ', 'Dian ', 'Jia ', 'Xian ', 'Cha ', 'Bing ', 'Ni ', 'Zheng ', 'Yong ', 'Jing ', 'Quan ', 'Chong ', 'Tong ', 'Yi ', 'Kai ', 'Wei ', 'Hui ', 'Duo ', 'Yang ', 'Chi ', 'Zhi ', 'Hen ', 'Ya ', 'Mei ', 'Dou ', 'Jing ', 'Xiao ', 'Tong ', 'Tu ', 'Mang ', 'Pi ', 'Xiao ', 'Suan ', 'Pu ', 'Li ', 'Zhi ', 'Cuo ', 'Duo ', 'Wu ', 'Sha ', 'Lao ', 'Shou ', 'Huan ', 'Xian ', 'Yi ', 'Peng ', 'Zhang ', 'Guan ', 'Tan ', 'Fei ', 'Ma ', 'Lin ', 'Chi ', 'Ji ', 'Dian ', 'An ', 'Chi ', 'Bi ', 'Bei ', 'Min ', 'Gu ', 'Dui ', 'E ', 'Wei '];
<?php return ['syon', 'syonj', 'syonh', 'syod', 'syol', 'syolg', 'syolm', 'syolb', 'syols', 'syolt', 'syolp', 'syolh', 'syom', 'syob', 'syobs', 'syos', 'syoss', 'syong', 'syoj', 'syoc', 'syok', 'syot', 'syop', 'syoh', 'su', 'sug', 'sugg', 'sugs', 'sun', 'sunj', 'sunh', 'sud', 'sul', 'sulg', 'sulm', 'sulb', 'suls', 'sult', 'sulp', 'sulh', 'sum', 'sub', 'subs', 'sus', 'suss', 'sung', 'suj', 'suc', 'suk', 'sut', 'sup', 'suh', 'sweo', 'sweog', 'sweogg', 'sweogs', 'sweon', 'sweonj', 'sweonh', 'sweod', 'sweol', 'sweolg', 'sweolm', 'sweolb', 'sweols', 'sweolt', 'sweolp', 'sweolh', 'sweom', 'sweob', 'sweobs', 'sweos', 'sweoss', 'sweong', 'sweoj', 'sweoc', 'sweok', 'sweot', 'sweop', 'sweoh', 'swe', 'sweg', 'swegg', 'swegs', 'swen', 'swenj', 'swenh', 'swed', 'swel', 'swelg', 'swelm', 'swelb', 'swels', 'swelt', 'swelp', 'swelh', 'swem', 'sweb', 'swebs', 'swes', 'swess', 'sweng', 'swej', 'swec', 'swek', 'swet', 'swep', 'sweh', 'swi', 'swig', 'swigg', 'swigs', 'swin', 'swinj', 'swinh', 'swid', 'swil', 'swilg', 'swilm', 'swilb', 'swils', 'swilt', 'swilp', 'swilh', 'swim', 'swib', 'swibs', 'swis', 'swiss', 'swing', 'swij', 'swic', 'swik', 'swit', 'swip', 'swih', 'syu', 'syug', 'syugg', 'syugs', 'syun', 'syunj', 'syunh', 'syud', 'syul', 'syulg', 'syulm', 'syulb', 'syuls', 'syult', 'syulp', 'syulh', 'syum', 'syub', 'syubs', 'syus', 'syuss', 'syung', 'syuj', 'syuc', 'syuk', 'syut', 'syup', 'syuh', 'seu', 'seug', 'seugg', 'seugs', 'seun', 'seunj', 'seunh', 'seud', 'seul', 'seulg', 'seulm', 'seulb', 'seuls', 'seult', 'seulp', 'seulh', 'seum', 'seub', 'seubs', 'seus', 'seuss', 'seung', 'seuj', 'seuc', 'seuk', 'seut', 'seup', 'seuh', 'syi', 'syig', 'syigg', 'syigs', 'syin', 'syinj', 'syinh', 'syid', 'syil', 'syilg', 'syilm', 'syilb', 'syils', 'syilt', 'syilp', 'syilh', 'syim', 'syib', 'syibs', 'syis', 'syiss', 'sying', 'syij', 'syic', 'syik', 'syit', 'syip', 'syih', 'si', 'sig', 'sigg', 'sigs', 'sin', 'sinj', 'sinh', 'sid', 'sil', 'silg', 'silm', 'silb', 'sils', 'silt', 'silp', 'silh', 'sim', 'sib', 'sibs', 'sis', 'siss', 'sing', 'sij', 'sic', 'sik', 'sit', 'sip', 'sih', 'ssa', 'ssag', 'ssagg', 'ssags', 'ssan', 'ssanj', 'ssanh', 'ssad'];
<?php return ['dwaen', 'dwaenj', 'dwaenh', 'dwaed', 'dwael', 'dwaelg', 'dwaelm', 'dwaelb', 'dwaels', 'dwaelt', 'dwaelp', 'dwaelh', 'dwaem', 'dwaeb', 'dwaebs', 'dwaes', 'dwaess', 'dwaeng', 'dwaej', 'dwaec', 'dwaek', 'dwaet', 'dwaep', 'dwaeh', 'doe', 'doeg', 'doegg', 'doegs', 'doen', 'doenj', 'doenh', 'doed', 'doel', 'doelg', 'doelm', 'doelb', 'doels', 'doelt', 'doelp', 'doelh', 'doem', 'doeb', 'doebs', 'does', 'doess', 'doeng', 'doej', 'doec', 'doek', 'doet', 'doep', 'doeh', 'dyo', 'dyog', 'dyogg', 'dyogs', 'dyon', 'dyonj', 'dyonh', 'dyod', 'dyol', 'dyolg', 'dyolm', 'dyolb', 'dyols', 'dyolt', 'dyolp', 'dyolh', 'dyom', 'dyob', 'dyobs', 'dyos', 'dyoss', 'dyong', 'dyoj', 'dyoc', 'dyok', 'dyot', 'dyop', 'dyoh', 'du', 'dug', 'dugg', 'dugs', 'dun', 'dunj', 'dunh', 'dud', 'dul', 'dulg', 'dulm', 'dulb', 'duls', 'dult', 'dulp', 'dulh', 'dum', 'dub', 'dubs', 'dus', 'duss', 'dung', 'duj', 'duc', 'duk', 'dut', 'dup', 'duh', 'dweo', 'dweog', 'dweogg', 'dweogs', 'dweon', 'dweonj', 'dweonh', 'dweod', 'dweol', 'dweolg', 'dweolm', 'dweolb', 'dweols', 'dweolt', 'dweolp', 'dweolh', 'dweom', 'dweob', 'dweobs', 'dweos', 'dweoss', 'dweong', 'dweoj', 'dweoc', 'dweok', 'dweot', 'dweop', 'dweoh', 'dwe', 'dweg', 'dwegg', 'dwegs', 'dwen', 'dwenj', 'dwenh', 'dwed', 'dwel', 'dwelg', 'dwelm', 'dwelb', 'dwels', 'dwelt', 'dwelp', 'dwelh', 'dwem', 'dweb', 'dwebs', 'dwes', 'dwess', 'dweng', 'dwej', 'dwec', 'dwek', 'dwet', 'dwep', 'dweh', 'dwi', 'dwig', 'dwigg', 'dwigs', 'dwin', 'dwinj', 'dwinh', 'dwid', 'dwil', 'dwilg', 'dwilm', 'dwilb', 'dwils', 'dwilt', 'dwilp', 'dwilh', 'dwim', 'dwib', 'dwibs', 'dwis', 'dwiss', 'dwing', 'dwij', 'dwic', 'dwik', 'dwit', 'dwip', 'dwih', 'dyu', 'dyug', 'dyugg', 'dyugs', 'dyun', 'dyunj', 'dyunh', 'dyud', 'dyul', 'dyulg', 'dyulm', 'dyulb', 'dyuls', 'dyult', 'dyulp', 'dyulh', 'dyum', 'dyub', 'dyubs', 'dyus', 'dyuss', 'dyung', 'dyuj', 'dyuc', 'dyuk', 'dyut', 'dyup', 'dyuh', 'deu', 'deug', 'deugg', 'deugs', 'deun', 'deunj', 'deunh', 'deud', 'deul', 'deulg', 'deulm', 'deulb', 'deuls', 'deult', 'deulp', 'deulh', 'deum', 'deub', 'deubs', 'deus', 'deuss', 'deung', 'deuj', 'deuc', 'deuk', 'deut', 'deup', 'deuh', 'dyi', 'dyig', 'dyigg', 'dyigs', 'dyin', 'dyinj', 'dyinh', 'dyid'];
<?php return ['Xia ', 'Yuan ', 'Zong ', 'Xu ', 'Nawa ', 'Odoshi ', 'Geng ', 'Sen ', 'Ying ', 'Jin ', 'Yi ', 'Zhui ', 'Ni ', 'Bang ', 'Gu ', 'Pan ', 'Zhou ', 'Jian ', 'Cuo ', 'Quan ', 'Shuang ', 'Yun ', 'Xia ', 'Shuai ', 'Xi ', 'Rong ', 'Tao ', 'Fu ', 'Yun ', 'Zhen ', 'Gao ', 'Ru ', 'Hu ', 'Zai ', 'Teng ', 'Xian ', 'Su ', 'Zhen ', 'Zong ', 'Tao ', 'Horo ', 'Cai ', 'Bi ', 'Feng ', 'Cu ', 'Li ', 'Suo ', 'Yin ', 'Xi ', 'Zong ', 'Lei ', 'Zhuan ', 'Qian ', 'Man ', 'Zhi ', 'Lu ', 'Mo ', 'Piao ', 'Lian ', 'Mi ', 'Xuan ', 'Zong ', 'Ji ', 'Shan ', 'Sui ', 'Fan ', 'Shuai ', 'Beng ', 'Yi ', 'Sao ', 'Mou ', 'Zhou ', 'Qiang ', 'Hun ', 'Sem ', 'Xi ', 'Jung ', 'Xiu ', 'Ran ', 'Xuan ', 'Hui ', 'Qiao ', 'Zeng ', 'Zuo ', 'Zhi ', 'Shan ', 'San ', 'Lin ', 'Yu ', 'Fan ', 'Liao ', 'Chuo ', 'Zun ', 'Jian ', 'Rao ', 'Chan ', 'Rui ', 'Xiu ', 'Hui ', 'Hua ', 'Zuan ', 'Xi ', 'Qiang ', 'Un ', 'Da ', 'Sheng ', 'Hui ', 'Xi ', 'Se ', 'Jian ', 'Jiang ', 'Huan ', 'Zao ', 'Cong ', 'Jie ', 'Jiao ', 'Bo ', 'Chan ', 'Yi ', 'Nao ', 'Sui ', 'Yi ', 'Shai ', 'Xu ', 'Ji ', 'Bin ', 'Qian ', 'Lan ', 'Pu ', 'Xun ', 'Zuan ', 'Qi ', 'Peng ', 'Li ', 'Mo ', 'Lei ', 'Xie ', 'Zuan ', 'Kuang ', 'You ', 'Xu ', 'Lei ', 'Xian ', 'Chan ', 'Kou ', 'Lu ', 'Chan ', 'Ying ', 'Cai ', 'Xiang ', 'Xian ', 'Zui ', 'Zuan ', 'Luo ', 'Xi ', 'Dao ', 'Lan ', 'Lei ', 'Lian ', 'Si ', 'Jiu ', 'Yu ', 'Hong ', 'Zhou ', 'Xian ', 'He ', 'Yue ', 'Ji ', 'Wan ', 'Kuang ', 'Ji ', 'Ren ', 'Wei ', 'Yun ', 'Hong ', 'Chun ', 'Pi ', 'Sha ', 'Gang ', 'Na ', 'Ren ', 'Zong ', 'Lun ', 'Fen ', 'Zhi ', 'Wen ', 'Fang ', 'Zhu ', 'Yin ', 'Niu ', 'Shu ', 'Xian ', 'Gan ', 'Xie ', 'Fu ', 'Lian ', 'Zu ', 'Shen ', 'Xi ', 'Zhi ', 'Zhong ', 'Zhou ', 'Ban ', 'Fu ', 'Zhuo ', 'Shao ', 'Yi ', 'Jing ', 'Dai ', 'Bang ', 'Rong ', 'Jie ', 'Ku ', 'Rao ', 'Die ', 'Heng ', 'Hui ', 'Gei ', 'Xuan ', 'Jiang ', 'Luo ', 'Jue ', 'Jiao ', 'Tong ', 'Geng ', 'Xiao ', 'Juan ', 'Xiu ', 'Xi ', 'Sui ', 'Tao ', 'Ji ', 'Ti ', 'Ji ', 'Xu ', 'Ling ', '[?] ', 'Xu ', 'Qi ', 'Fei ', 'Chuo ', 'Zhang ', 'Gun ', 'Sheng ', 'Wei ', 'Mian ', 'Shou ', 'Beng ', 'Chou ', 'Tao ', 'Liu ', 'Quan ', 'Zong ', 'Zhan ', 'Wan ', 'Lu '];
<?php return ['Lun ', 'Kua ', 'Ling ', 'Bei ', 'Lu ', 'Li ', 'Qiang ', 'Pou ', 'Juan ', 'Min ', 'Zui ', 'Peng ', 'An ', 'Pi ', 'Xian ', 'Ya ', 'Zhui ', 'Lei ', 'A ', 'Kong ', 'Ta ', 'Kun ', 'Du ', 'Wei ', 'Chui ', 'Zi ', 'Zheng ', 'Ben ', 'Nie ', 'Cong ', 'Qun ', 'Tan ', 'Ding ', 'Qi ', 'Qian ', 'Zhuo ', 'Qi ', 'Yu ', 'Jin ', 'Guan ', 'Mao ', 'Chang ', 'Tian ', 'Xi ', 'Lian ', 'Tao ', 'Gu ', 'Cuo ', 'Shu ', 'Zhen ', 'Lu ', 'Meng ', 'Lu ', 'Hua ', 'Biao ', 'Ga ', 'Lai ', 'Ken ', 'Kazari ', 'Bu ', 'Nai ', 'Wan ', 'Zan ', '[?] ', 'De ', 'Xian ', '[?] ', 'Huo ', 'Liang ', '[?] ', 'Men ', 'Kai ', 'Ying ', 'Di ', 'Lian ', 'Guo ', 'Xian ', 'Du ', 'Tu ', 'Wei ', 'Cong ', 'Fu ', 'Rou ', 'Ji ', 'E ', 'Rou ', 'Chen ', 'Ti ', 'Zha ', 'Hong ', 'Yang ', 'Duan ', 'Xia ', 'Yu ', 'Keng ', 'Xing ', 'Huang ', 'Wei ', 'Fu ', 'Zhao ', 'Cha ', 'Qie ', 'She ', 'Hong ', 'Kui ', 'Tian ', 'Mou ', 'Qiao ', 'Qiao ', 'Hou ', 'Tou ', 'Cong ', 'Huan ', 'Ye ', 'Min ', 'Jian ', 'Duan ', 'Jian ', 'Song ', 'Kui ', 'Hu ', 'Xuan ', 'Duo ', 'Jie ', 'Zhen ', 'Bian ', 'Zhong ', 'Zi ', 'Xiu ', 'Ye ', 'Mei ', 'Pai ', 'Ai ', 'Jie ', '[?] ', 'Mei ', 'Chuo ', 'Ta ', 'Bang ', 'Xia ', 'Lian ', 'Suo ', 'Xi ', 'Liu ', 'Zu ', 'Ye ', 'Nou ', 'Weng ', 'Rong ', 'Tang ', 'Suo ', 'Qiang ', 'Ge ', 'Shuo ', 'Chui ', 'Bo ', 'Pan ', 'Sa ', 'Bi ', 'Sang ', 'Gang ', 'Zi ', 'Wu ', 'Ying ', 'Huang ', 'Tiao ', 'Liu ', 'Kai ', 'Sun ', 'Sha ', 'Sou ', 'Wan ', 'Hao ', 'Zhen ', 'Zhen ', 'Luo ', 'Yi ', 'Yuan ', 'Tang ', 'Nie ', 'Xi ', 'Jia ', 'Ge ', 'Ma ', 'Juan ', 'Kasugai ', 'Habaki ', 'Suo ', '[?] ', '[?] ', '[?] ', 'Na ', 'Lu ', 'Suo ', 'Ou ', 'Zu ', 'Tuan ', 'Xiu ', 'Guan ', 'Xuan ', 'Lian ', 'Shou ', 'Ao ', 'Man ', 'Mo ', 'Luo ', 'Bi ', 'Wei ', 'Liu ', 'Di ', 'Qiao ', 'Cong ', 'Yi ', 'Lu ', 'Ao ', 'Keng ', 'Qiang ', 'Cui ', 'Qi ', 'Chang ', 'Tang ', 'Man ', 'Yong ', 'Chan ', 'Feng ', 'Jing ', 'Biao ', 'Shu ', 'Lou ', 'Xiu ', 'Cong ', 'Long ', 'Zan ', 'Jian ', 'Cao ', 'Li ', 'Xia ', 'Xi ', 'Kang ', '[?] ', 'Beng ', '[?] ', '[?] ', 'Zheng ', 'Lu ', 'Hua ', 'Ji ', 'Pu ', 'Hui ', 'Qiang ', 'Po ', 'Lin ', 'Suo ', 'Xiu ', 'San ', 'Cheng '];
<?php return ['Wan ', 'Guo ', 'Lu ', 'Hao ', 'Jie ', 'Yi ', 'Chou ', 'Ju ', 'Ju ', 'Cheng ', 'Zuo ', 'Liang ', 'Qiang ', 'Zhi ', 'Zhui ', 'Ya ', 'Ju ', 'Bei ', 'Jiao ', 'Zhuo ', 'Zi ', 'Bin ', 'Peng ', 'Ding ', 'Chu ', 'Chang ', 'Kunugi ', 'Momiji ', 'Jian ', 'Gui ', 'Xi ', 'Du ', 'Qian ', 'Kunugi ', 'Soko ', 'Shide ', 'Luo ', 'Zhi ', 'Ken ', 'Myeng ', 'Tafu ', '[?] ', 'Peng ', 'Zhan ', '[?] ', 'Tuo ', 'Sen ', 'Duo ', 'Ye ', 'Fou ', 'Wei ', 'Wei ', 'Duan ', 'Jia ', 'Zong ', 'Jian ', 'Yi ', 'Shen ', 'Xi ', 'Yan ', 'Yan ', 'Chuan ', 'Zhan ', 'Chun ', 'Yu ', 'He ', 'Zha ', 'Wo ', 'Pian ', 'Bi ', 'Yao ', 'Huo ', 'Xu ', 'Ruo ', 'Yang ', 'La ', 'Yan ', 'Ben ', 'Hun ', 'Kui ', 'Jie ', 'Kui ', 'Si ', 'Feng ', 'Xie ', 'Tuo ', 'Zhi ', 'Jian ', 'Mu ', 'Mao ', 'Chu ', 'Hu ', 'Hu ', 'Lian ', 'Leng ', 'Ting ', 'Nan ', 'Yu ', 'You ', 'Mei ', 'Song ', 'Xuan ', 'Xuan ', 'Ying ', 'Zhen ', 'Pian ', 'Ye ', 'Ji ', 'Jie ', 'Ye ', 'Chu ', 'Shun ', 'Yu ', 'Cou ', 'Wei ', 'Mei ', 'Di ', 'Ji ', 'Jie ', 'Kai ', 'Qiu ', 'Ying ', 'Rou ', 'Heng ', 'Lou ', 'Le ', 'Hazou ', 'Katsura ', 'Pin ', 'Muro ', 'Gai ', 'Tan ', 'Lan ', 'Yun ', 'Yu ', 'Chen ', 'Lu ', 'Ju ', 'Sakaki ', '[?] ', 'Pi ', 'Xie ', 'Jia ', 'Yi ', 'Zhan ', 'Fu ', 'Nai ', 'Mi ', 'Lang ', 'Rong ', 'Gu ', 'Jian ', 'Ju ', 'Ta ', 'Yao ', 'Zhen ', 'Bang ', 'Sha ', 'Yuan ', 'Zi ', 'Ming ', 'Su ', 'Jia ', 'Yao ', 'Jie ', 'Huang ', 'Gan ', 'Fei ', 'Zha ', 'Qian ', 'Ma ', 'Sun ', 'Yuan ', 'Xie ', 'Rong ', 'Shi ', 'Zhi ', 'Cui ', 'Yun ', 'Ting ', 'Liu ', 'Rong ', 'Tang ', 'Que ', 'Zhai ', 'Si ', 'Sheng ', 'Ta ', 'Ke ', 'Xi ', 'Gu ', 'Qi ', 'Kao ', 'Gao ', 'Sun ', 'Pan ', 'Tao ', 'Ge ', 'Xun ', 'Dian ', 'Nou ', 'Ji ', 'Shuo ', 'Gou ', 'Chui ', 'Qiang ', 'Cha ', 'Qian ', 'Huai ', 'Mei ', 'Xu ', 'Gang ', 'Gao ', 'Zhuo ', 'Tuo ', 'Hashi ', 'Yang ', 'Dian ', 'Jia ', 'Jian ', 'Zui ', 'Kashi ', 'Ori ', 'Bin ', 'Zhu ', '[?] ', 'Xi ', 'Qi ', 'Lian ', 'Hui ', 'Yong ', 'Qian ', 'Guo ', 'Gai ', 'Gai ', 'Tuan ', 'Hua ', 'Cu ', 'Sen ', 'Cui ', 'Beng ', 'You ', 'Hu ', 'Jiang ', 'Hu ', 'Huan ', 'Kui ', 'Yi ', 'Nie ', 'Gao ', 'Kang ', 'Gui ', 'Gui ', 'Cao ', 'Man ', 'Jin '];
<?php return ['Shu ', 'Xuan ', 'Feng ', 'Shen ', 'Zhen ', 'Fu ', 'Xian ', 'Zhe ', 'Wu ', 'Fu ', 'Li ', 'Lang ', 'Bi ', 'Chu ', 'Yuan ', 'You ', 'Jie ', 'Dan ', 'Yan ', 'Ting ', 'Dian ', 'Shui ', 'Hui ', 'Gua ', 'Zhi ', 'Song ', 'Fei ', 'Ju ', 'Mi ', 'Qi ', 'Qi ', 'Yu ', 'Jun ', 'Zha ', 'Meng ', 'Qiang ', 'Si ', 'Xi ', 'Lun ', 'Li ', 'Die ', 'Tiao ', 'Tao ', 'Kun ', 'Gan ', 'Han ', 'Yu ', 'Bang ', 'Fei ', 'Pi ', 'Wei ', 'Dun ', 'Yi ', 'Yuan ', 'Su ', 'Quan ', 'Qian ', 'Rui ', 'Ni ', 'Qing ', 'Wei ', 'Liang ', 'Guo ', 'Wan ', 'Dong ', 'E ', 'Ban ', 'Di ', 'Wang ', 'Can ', 'Yang ', 'Ying ', 'Guo ', 'Chan ', '[?] ', 'La ', 'Ke ', 'Ji ', 'He ', 'Ting ', 'Mai ', 'Xu ', 'Mian ', 'Yu ', 'Jie ', 'Shi ', 'Xuan ', 'Huang ', 'Yan ', 'Bian ', 'Rou ', 'Wei ', 'Fu ', 'Yuan ', 'Mei ', 'Wei ', 'Fu ', 'Ruan ', 'Xie ', 'You ', 'Qiu ', 'Mao ', 'Xia ', 'Ying ', 'Shi ', 'Chong ', 'Tang ', 'Zhu ', 'Zong ', 'Ti ', 'Fu ', 'Yuan ', 'Hui ', 'Meng ', 'La ', 'Du ', 'Hu ', 'Qiu ', 'Die ', 'Li ', 'Gua ', 'Yun ', 'Ju ', 'Nan ', 'Lou ', 'Qun ', 'Rong ', 'Ying ', 'Jiang ', '[?] ', 'Lang ', 'Pang ', 'Si ', 'Xi ', 'Ci ', 'Xi ', 'Yuan ', 'Weng ', 'Lian ', 'Sou ', 'Ban ', 'Rong ', 'Rong ', 'Ji ', 'Wu ', 'Qiu ', 'Han ', 'Qin ', 'Yi ', 'Bi ', 'Hua ', 'Tang ', 'Yi ', 'Du ', 'Nai ', 'He ', 'Hu ', 'Hui ', 'Ma ', 'Ming ', 'Yi ', 'Wen ', 'Ying ', 'Teng ', 'Yu ', 'Cang ', 'So ', 'Ebi ', 'Man ', '[?] ', 'Shang ', 'Zhe ', 'Cao ', 'Chi ', 'Di ', 'Ao ', 'Lu ', 'Wei ', 'Zhi ', 'Tang ', 'Chen ', 'Piao ', 'Qu ', 'Pi ', 'Yu ', 'Jian ', 'Luo ', 'Lou ', 'Qin ', 'Zhong ', 'Yin ', 'Jiang ', 'Shuai ', 'Wen ', 'Jiao ', 'Wan ', 'Zhi ', 'Zhe ', 'Ma ', 'Ma ', 'Guo ', 'Liu ', 'Mao ', 'Xi ', 'Cong ', 'Li ', 'Man ', 'Xiao ', 'Kamakiri ', 'Zhang ', 'Mang ', 'Xiang ', 'Mo ', 'Zui ', 'Si ', 'Qiu ', 'Te ', 'Zhi ', 'Peng ', 'Peng ', 'Jiao ', 'Qu ', 'Bie ', 'Liao ', 'Pan ', 'Gui ', 'Xi ', 'Ji ', 'Zhuan ', 'Huang ', 'Fei ', 'Lao ', 'Jue ', 'Jue ', 'Hui ', 'Yin ', 'Chan ', 'Jiao ', 'Shan ', 'Rao ', 'Xiao ', 'Mou ', 'Chong ', 'Xun ', 'Si ', '[?] ', 'Cheng ', 'Dang ', 'Li ', 'Xie ', 'Shan ', 'Yi ', 'Jing ', 'Da ', 'Chan ', 'Qi '];
<?php return ['cwik', 'cwit', 'cwip', 'cwih', 'cyu', 'cyug', 'cyugg', 'cyugs', 'cyun', 'cyunj', 'cyunh', 'cyud', 'cyul', 'cyulg', 'cyulm', 'cyulb', 'cyuls', 'cyult', 'cyulp', 'cyulh', 'cyum', 'cyub', 'cyubs', 'cyus', 'cyuss', 'cyung', 'cyuj', 'cyuc', 'cyuk', 'cyut', 'cyup', 'cyuh', 'ceu', 'ceug', 'ceugg', 'ceugs', 'ceun', 'ceunj', 'ceunh', 'ceud', 'ceul', 'ceulg', 'ceulm', 'ceulb', 'ceuls', 'ceult', 'ceulp', 'ceulh', 'ceum', 'ceub', 'ceubs', 'ceus', 'ceuss', 'ceung', 'ceuj', 'ceuc', 'ceuk', 'ceut', 'ceup', 'ceuh', 'cyi', 'cyig', 'cyigg', 'cyigs', 'cyin', 'cyinj', 'cyinh', 'cyid', 'cyil', 'cyilg', 'cyilm', 'cyilb', 'cyils', 'cyilt', 'cyilp', 'cyilh', 'cyim', 'cyib', 'cyibs', 'cyis', 'cyiss', 'cying', 'cyij', 'cyic', 'cyik', 'cyit', 'cyip', 'cyih', 'ci', 'cig', 'cigg', 'cigs', 'cin', 'cinj', 'cinh', 'cid', 'cil', 'cilg', 'cilm', 'cilb', 'cils', 'cilt', 'cilp', 'cilh', 'cim', 'cib', 'cibs', 'cis', 'ciss', 'cing', 'cij', 'cic', 'cik', 'cit', 'cip', 'cih', 'ka', 'kag', 'kagg', 'kags', 'kan', 'kanj', 'kanh', 'kad', 'kal', 'kalg', 'kalm', 'kalb', 'kals', 'kalt', 'kalp', 'kalh', 'kam', 'kab', 'kabs', 'kas', 'kass', 'kang', 'kaj', 'kac', 'kak', 'kat', 'kap', 'kah', 'kae', 'kaeg', 'kaegg', 'kaegs', 'kaen', 'kaenj', 'kaenh', 'kaed', 'kael', 'kaelg', 'kaelm', 'kaelb', 'kaels', 'kaelt', 'kaelp', 'kaelh', 'kaem', 'kaeb', 'kaebs', 'kaes', 'kaess', 'kaeng', 'kaej', 'kaec', 'kaek', 'kaet', 'kaep', 'kaeh', 'kya', 'kyag', 'kyagg', 'kyags', 'kyan', 'kyanj', 'kyanh', 'kyad', 'kyal', 'kyalg', 'kyalm', 'kyalb', 'kyals', 'kyalt', 'kyalp', 'kyalh', 'kyam', 'kyab', 'kyabs', 'kyas', 'kyass', 'kyang', 'kyaj', 'kyac', 'kyak', 'kyat', 'kyap', 'kyah', 'kyae', 'kyaeg', 'kyaegg', 'kyaegs', 'kyaen', 'kyaenj', 'kyaenh', 'kyaed', 'kyael', 'kyaelg', 'kyaelm', 'kyaelb', 'kyaels', 'kyaelt', 'kyaelp', 'kyaelh', 'kyaem', 'kyaeb', 'kyaebs', 'kyaes', 'kyaess', 'kyaeng', 'kyaej', 'kyaec', 'kyaek', 'kyaet', 'kyaep', 'kyaeh', 'keo', 'keog', 'keogg', 'keogs', 'keon', 'keonj', 'keonh', 'keod', 'keol', 'keolg', 'keolm', 'keolb', 'keols', 'keolt', 'keolp', 'keolh', 'keom', 'keob', 'keobs', 'keos', 'keoss', 'keong', 'keoj', 'keoc', 'keok', 'keot', 'keop', 'keoh'];
<?php return ['You ', 'Yan ', 'Gu ', 'Gu ', 'Bai ', 'Han ', 'Suo ', 'Chun ', 'Yi ', 'Ai ', 'Jia ', 'Tu ', 'Xian ', 'Huan ', 'Li ', 'Xi ', 'Tang ', 'Zuo ', 'Qiu ', 'Che ', 'Wu ', 'Zao ', 'Ya ', 'Dou ', 'Qi ', 'Di ', 'Qin ', 'Ma ', 'Mal ', 'Hong ', 'Dou ', 'Kes ', 'Lao ', 'Liang ', 'Suo ', 'Zao ', 'Huan ', 'Lang ', 'Sha ', 'Ji ', 'Zuo ', 'Wo ', 'Feng ', 'Yin ', 'Hu ', 'Qi ', 'Shou ', 'Wei ', 'Shua ', 'Chang ', 'Er ', 'Li ', 'Qiang ', 'An ', 'Jie ', 'Yo ', 'Nian ', 'Yu ', 'Tian ', 'Lai ', 'Sha ', 'Xi ', 'Tuo ', 'Hu ', 'Ai ', 'Zhou ', 'Nou ', 'Ken ', 'Zhuo ', 'Zhuo ', 'Shang ', 'Di ', 'Heng ', 'Lan ', 'A ', 'Xiao ', 'Xiang ', 'Tun ', 'Wu ', 'Wen ', 'Cui ', 'Sha ', 'Hu ', 'Qi ', 'Qi ', 'Tao ', 'Dan ', 'Dan ', 'Ye ', 'Zi ', 'Bi ', 'Cui ', 'Chuo ', 'He ', 'Ya ', 'Qi ', 'Zhe ', 'Pei ', 'Liang ', 'Xian ', 'Pi ', 'Sha ', 'La ', 'Ze ', 'Qing ', 'Gua ', 'Pa ', 'Zhe ', 'Se ', 'Zhuan ', 'Nie ', 'Guo ', 'Luo ', 'Yan ', 'Di ', 'Quan ', 'Tan ', 'Bo ', 'Ding ', 'Lang ', 'Xiao ', '[?] ', 'Tang ', 'Chi ', 'Ti ', 'An ', 'Jiu ', 'Dan ', 'Ke ', 'Yong ', 'Wei ', 'Nan ', 'Shan ', 'Yu ', 'Zhe ', 'La ', 'Jie ', 'Hou ', 'Han ', 'Die ', 'Zhou ', 'Chai ', 'Wai ', 'Re ', 'Yu ', 'Yin ', 'Zan ', 'Yao ', 'Wo ', 'Mian ', 'Hu ', 'Yun ', 'Chuan ', 'Hui ', 'Huan ', 'Huan ', 'Xi ', 'He ', 'Ji ', 'Kui ', 'Zhong ', 'Wei ', 'Sha ', 'Xu ', 'Huang ', 'Du ', 'Nie ', 'Xuan ', 'Liang ', 'Yu ', 'Sang ', 'Chi ', 'Qiao ', 'Yan ', 'Dan ', 'Pen ', 'Can ', 'Li ', 'Yo ', 'Zha ', 'Wei ', 'Miao ', 'Ying ', 'Pen ', 'Phos ', 'Kui ', 'Xi ', 'Yu ', 'Jie ', 'Lou ', 'Ku ', 'Sao ', 'Huo ', 'Ti ', 'Yao ', 'He ', 'A ', 'Xiu ', 'Qiang ', 'Se ', 'Yong ', 'Su ', 'Hong ', 'Xie ', 'Yi ', 'Suo ', 'Ma ', 'Cha ', 'Hai ', 'Ke ', 'Ta ', 'Sang ', 'Tian ', 'Ru ', 'Sou ', 'Wa ', 'Ji ', 'Pang ', 'Wu ', 'Xian ', 'Shi ', 'Ge ', 'Zi ', 'Jie ', 'Luo ', 'Weng ', 'Wa ', 'Si ', 'Chi ', 'Hao ', 'Suo ', 'Jia ', 'Hai ', 'Suo ', 'Qin ', 'Nie ', 'He ', 'Cis ', 'Sai ', 'Ng ', 'Ge ', 'Na ', 'Dia ', 'Ai ', '[?] ', 'Tong ', 'Bi ', 'Ao ', 'Ao ', 'Lian ', 'Cui ', 'Zhe ', 'Mo ', 'Sou ', 'Sou ', 'Tan '];
<?php return ['kka', 'kk', 'nu', 'no', 'ne', 'nee', 'ni', 'na', 'mu', 'mo', 'me', 'mee', 'mi', 'ma', 'yu', 'yo', 'ye', 'yee', 'yi', 'ya', 'ju', 'ju', 'jo', 'je', 'jee', 'ji', 'ji', 'ja', 'jju', 'jjo', 'jje', 'jjee', 'jji', 'jja', 'lu', 'lo', 'le', 'lee', 'li', 'la', 'dlu', 'dlo', 'dle', 'dlee', 'dli', 'dla', 'lhu', 'lho', 'lhe', 'lhee', 'lhi', 'lha', 'tlhu', 'tlho', 'tlhe', 'tlhee', 'tlhi', 'tlha', 'tlu', 'tlo', 'tle', 'tlee', 'tli', 'tla', 'zu', 'zo', 'ze', 'zee', 'zi', 'za', 'z', 'z', 'dzu', 'dzo', 'dze', 'dzee', 'dzi', 'dza', 'su', 'so', 'se', 'see', 'si', 'sa', 'shu', 'sho', 'she', 'shee', 'shi', 'sha', 'sh', 'tsu', 'tso', 'tse', 'tsee', 'tsi', 'tsa', 'chu', 'cho', 'che', 'chee', 'chi', 'cha', 'ttsu', 'ttso', 'ttse', 'ttsee', 'ttsi', 'ttsa', 'X', '.', 'qai', 'ngai', 'nngi', 'nngii', 'nngo', 'nngoo', 'nnga', 'nngaa', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ' ', 'b', 'l', 'f', 's', 'n', 'h', 'd', 't', 'c', 'q', 'm', 'g', 'ng', 'z', 'r', 'a', 'o', 'u', 'e', 'i', 'ch', 'th', 'ph', 'p', 'x', 'p', '<', '>', '[?]', '[?]', '[?]', 'f', 'v', 'u', 'yr', 'y', 'w', 'th', 'th', 'a', 'o', 'ac', 'ae', 'o', 'o', 'o', 'oe', 'on', 'r', 'k', 'c', 'k', 'g', 'ng', 'g', 'g', 'w', 'h', 'h', 'h', 'h', 'n', 'n', 'n', 'i', 'e', 'j', 'g', 'ae', 'a', 'eo', 'p', 'z', 's', 's', 's', 'c', 'z', 't', 't', 'd', 'b', 'b', 'p', 'p', 'e', 'm', 'm', 'm', 'l', 'l', 'ng', 'ng', 'd', 'o', 'ear', 'ior', 'qu', 'qu', 'qu', 's', 'yr', 'yr', 'yr', 'q', 'x', '.', ':', '+', '17', '18', '19', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '~', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '..', '--', '-', '_', '_', '(', ') ', '{', '} ', '[', '] ', '[(', ')] ', '<<', '>> ', '<', '> ', '[', '] ', '{', '}', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', ',', ',', '.', '', ';', ':', '?', '!', '-', '(', ')', '{', '}', '{', '}', '#', '&', '*', '+', '-', '<', '>', '=', '', '\\', '$', '%', '@', '[?]', '[?]', '[?]', '[?]', '', '', '', '[?]', '', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', ''];
<?php return ['Hai ', 'Ren ', 'Tian ', 'Jiao ', 'Jia ', 'Bing ', 'Yao ', 'Tong ', 'Ci ', 'Xiang ', 'Yang ', 'Yang ', 'Er ', 'Yan ', 'Le ', 'Yi ', 'Can ', 'Bo ', 'Nei ', 'E ', 'Bu ', 'Jun ', 'Dou ', 'Su ', 'Yu ', 'Shi ', 'Yao ', 'Hun ', 'Guo ', 'Shi ', 'Jian ', 'Zhui ', 'Bing ', 'Xian ', 'Bu ', 'Ye ', 'Tan ', 'Fei ', 'Zhang ', 'Wei ', 'Guan ', 'E ', 'Nuan ', 'Hun ', 'Hu ', 'Huang ', 'Tie ', 'Hui ', 'Jian ', 'Hou ', 'He ', 'Xing ', 'Fen ', 'Wei ', 'Gu ', 'Cha ', 'Song ', 'Tang ', 'Bo ', 'Gao ', 'Xi ', 'Kui ', 'Liu ', 'Sou ', 'Tao ', 'Ye ', 'Yun ', 'Mo ', 'Tang ', 'Man ', 'Bi ', 'Yu ', 'Xiu ', 'Jin ', 'San ', 'Kui ', 'Zhuan ', 'Shan ', 'Chi ', 'Dan ', 'Yi ', 'Ji ', 'Rao ', 'Cheng ', 'Yong ', 'Tao ', 'Hui ', 'Xiang ', 'Zhan ', 'Fen ', 'Hai ', 'Meng ', 'Yan ', 'Mo ', 'Chan ', 'Xiang ', 'Luo ', 'Zuan ', 'Nang ', 'Shi ', 'Ding ', 'Ji ', 'Tuo ', 'Xing ', 'Tun ', 'Xi ', 'Ren ', 'Yu ', 'Chi ', 'Fan ', 'Yin ', 'Jian ', 'Shi ', 'Bao ', 'Si ', 'Duo ', 'Yi ', 'Er ', 'Rao ', 'Xiang ', 'Jia ', 'Le ', 'Jiao ', 'Yi ', 'Bing ', 'Bo ', 'Dou ', 'E ', 'Yu ', 'Nei ', 'Jun ', 'Guo ', 'Hun ', 'Xian ', 'Guan ', 'Cha ', 'Kui ', 'Gu ', 'Sou ', 'Chan ', 'Ye ', 'Mo ', 'Bo ', 'Liu ', 'Xiu ', 'Jin ', 'Man ', 'San ', 'Zhuan ', 'Nang ', 'Shou ', 'Kui ', 'Guo ', 'Xiang ', 'Fen ', 'Ba ', 'Ni ', 'Bi ', 'Bo ', 'Tu ', 'Han ', 'Fei ', 'Jian ', 'An ', 'Ai ', 'Fu ', 'Xian ', 'Wen ', 'Xin ', 'Fen ', 'Bin ', 'Xing ', 'Ma ', 'Yu ', 'Feng ', 'Han ', 'Di ', 'Tuo ', 'Tuo ', 'Chi ', 'Xun ', 'Zhu ', 'Zhi ', 'Pei ', 'Xin ', 'Ri ', 'Sa ', 'Yin ', 'Wen ', 'Zhi ', 'Dan ', 'Lu ', 'You ', 'Bo ', 'Bao ', 'Kuai ', 'Tuo ', 'Yi ', 'Qu ', '[?] ', 'Qu ', 'Jiong ', 'Bo ', 'Zhao ', 'Yuan ', 'Peng ', 'Zhou ', 'Ju ', 'Zhu ', 'Nu ', 'Ju ', 'Pi ', 'Zang ', 'Jia ', 'Ling ', 'Zhen ', 'Tai ', 'Fu ', 'Yang ', 'Shi ', 'Bi ', 'Tuo ', 'Tuo ', 'Si ', 'Liu ', 'Ma ', 'Pian ', 'Tao ', 'Zhi ', 'Rong ', 'Teng ', 'Dong ', 'Xun ', 'Quan ', 'Shen ', 'Jiong ', 'Er ', 'Hai ', 'Bo ', 'Zhu ', 'Yin ', 'Luo ', 'Shuu ', 'Dan ', 'Xie ', 'Liu ', 'Ju ', 'Song ', 'Qin ', 'Mang ', 'Liang ', 'Han ', 'Tu ', 'Xuan ', 'Tui ', 'Jun '];
<?php return ['ddyels', 'ddyelt', 'ddyelp', 'ddyelh', 'ddyem', 'ddyeb', 'ddyebs', 'ddyes', 'ddyess', 'ddyeng', 'ddyej', 'ddyec', 'ddyek', 'ddyet', 'ddyep', 'ddyeh', 'ddo', 'ddog', 'ddogg', 'ddogs', 'ddon', 'ddonj', 'ddonh', 'ddod', 'ddol', 'ddolg', 'ddolm', 'ddolb', 'ddols', 'ddolt', 'ddolp', 'ddolh', 'ddom', 'ddob', 'ddobs', 'ddos', 'ddoss', 'ddong', 'ddoj', 'ddoc', 'ddok', 'ddot', 'ddop', 'ddoh', 'ddwa', 'ddwag', 'ddwagg', 'ddwags', 'ddwan', 'ddwanj', 'ddwanh', 'ddwad', 'ddwal', 'ddwalg', 'ddwalm', 'ddwalb', 'ddwals', 'ddwalt', 'ddwalp', 'ddwalh', 'ddwam', 'ddwab', 'ddwabs', 'ddwas', 'ddwass', 'ddwang', 'ddwaj', 'ddwac', 'ddwak', 'ddwat', 'ddwap', 'ddwah', 'ddwae', 'ddwaeg', 'ddwaegg', 'ddwaegs', 'ddwaen', 'ddwaenj', 'ddwaenh', 'ddwaed', 'ddwael', 'ddwaelg', 'ddwaelm', 'ddwaelb', 'ddwaels', 'ddwaelt', 'ddwaelp', 'ddwaelh', 'ddwaem', 'ddwaeb', 'ddwaebs', 'ddwaes', 'ddwaess', 'ddwaeng', 'ddwaej', 'ddwaec', 'ddwaek', 'ddwaet', 'ddwaep', 'ddwaeh', 'ddoe', 'ddoeg', 'ddoegg', 'ddoegs', 'ddoen', 'ddoenj', 'ddoenh', 'ddoed', 'ddoel', 'ddoelg', 'ddoelm', 'ddoelb', 'ddoels', 'ddoelt', 'ddoelp', 'ddoelh', 'ddoem', 'ddoeb', 'ddoebs', 'ddoes', 'ddoess', 'ddoeng', 'ddoej', 'ddoec', 'ddoek', 'ddoet', 'ddoep', 'ddoeh', 'ddyo', 'ddyog', 'ddyogg', 'ddyogs', 'ddyon', 'ddyonj', 'ddyonh', 'ddyod', 'ddyol', 'ddyolg', 'ddyolm', 'ddyolb', 'ddyols', 'ddyolt', 'ddyolp', 'ddyolh', 'ddyom', 'ddyob', 'ddyobs', 'ddyos', 'ddyoss', 'ddyong', 'ddyoj', 'ddyoc', 'ddyok', 'ddyot', 'ddyop', 'ddyoh', 'ddu', 'ddug', 'ddugg', 'ddugs', 'ddun', 'ddunj', 'ddunh', 'ddud', 'ddul', 'ddulg', 'ddulm', 'ddulb', 'dduls', 'ddult', 'ddulp', 'ddulh', 'ddum', 'ddub', 'ddubs', 'ddus', 'dduss', 'ddung', 'dduj', 'dduc', 'dduk', 'ddut', 'ddup', 'dduh', 'ddweo', 'ddweog', 'ddweogg', 'ddweogs', 'ddweon', 'ddweonj', 'ddweonh', 'ddweod', 'ddweol', 'ddweolg', 'ddweolm', 'ddweolb', 'ddweols', 'ddweolt', 'ddweolp', 'ddweolh', 'ddweom', 'ddweob', 'ddweobs', 'ddweos', 'ddweoss', 'ddweong', 'ddweoj', 'ddweoc', 'ddweok', 'ddweot', 'ddweop', 'ddweoh', 'ddwe', 'ddweg', 'ddwegg', 'ddwegs', 'ddwen', 'ddwenj', 'ddwenh', 'ddwed', 'ddwel', 'ddwelg', 'ddwelm', 'ddwelb', 'ddwels', 'ddwelt', 'ddwelp', 'ddwelh', 'ddwem', 'ddweb', 'ddwebs', 'ddwes', 'ddwess', 'ddweng', 'ddwej', 'ddwec', 'ddwek', 'ddwet', 'ddwep', 'ddweh', 'ddwi', 'ddwig', 'ddwigg', 'ddwigs', 'ddwin', 'ddwinj', 'ddwinh', 'ddwid', 'ddwil', 'ddwilg', 'ddwilm', 'ddwilb', 'ddwils', 'ddwilt', 'ddwilp', 'ddwilh'];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '#', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Di ', 'Qi ', 'Jiao ', 'Chong ', 'Jiao ', 'Kai ', 'Tan ', 'San ', 'Cao ', 'Jia ', 'Ai ', 'Xiao ', 'Piao ', 'Lou ', 'Ga ', 'Gu ', 'Xiao ', 'Hu ', 'Hui ', 'Guo ', 'Ou ', 'Xian ', 'Ze ', 'Chang ', 'Xu ', 'Po ', 'De ', 'Ma ', 'Ma ', 'Hu ', 'Lei ', 'Du ', 'Ga ', 'Tang ', 'Ye ', 'Beng ', 'Ying ', 'Saai ', 'Jiao ', 'Mi ', 'Xiao ', 'Hua ', 'Mai ', 'Ran ', 'Zuo ', 'Peng ', 'Lao ', 'Xiao ', 'Ji ', 'Zhu ', 'Chao ', 'Kui ', 'Zui ', 'Xiao ', 'Si ', 'Hao ', 'Fu ', 'Liao ', 'Qiao ', 'Xi ', 'Xiu ', 'Tan ', 'Tan ', 'Mo ', 'Xun ', 'E ', 'Zun ', 'Fan ', 'Chi ', 'Hui ', 'Zan ', 'Chuang ', 'Cu ', 'Dan ', 'Yu ', 'Tun ', 'Cheng ', 'Jiao ', 'Ye ', 'Xi ', 'Qi ', 'Hao ', 'Lian ', 'Xu ', 'Deng ', 'Hui ', 'Yin ', 'Pu ', 'Jue ', 'Qin ', 'Xun ', 'Nie ', 'Lu ', 'Si ', 'Yan ', 'Ying ', 'Da ', 'Dan ', 'Yu ', 'Zhou ', 'Jin ', 'Nong ', 'Yue ', 'Hui ', 'Qi ', 'E ', 'Zao ', 'Yi ', 'Shi ', 'Jiao ', 'Yuan ', 'Ai ', 'Yong ', 'Jue ', 'Kuai ', 'Yu ', 'Pen ', 'Dao ', 'Ge ', 'Xin ', 'Dun ', 'Dang ', 'Sin ', 'Sai ', 'Pi ', 'Pi ', 'Yin ', 'Zui ', 'Ning ', 'Di ', 'Lan ', 'Ta ', 'Huo ', 'Ru ', 'Hao ', 'Xia ', 'Ya ', 'Duo ', 'Xi ', 'Chou ', 'Ji ', 'Jin ', 'Hao ', 'Ti ', 'Chang ', '[?] ', '[?] ', 'Ca ', 'Ti ', 'Lu ', 'Hui ', 'Bo ', 'You ', 'Nie ', 'Yin ', 'Hu ', 'Mo ', 'Huang ', 'Zhe ', 'Li ', 'Liu ', 'Haai ', 'Nang ', 'Xiao ', 'Mo ', 'Yan ', 'Li ', 'Lu ', 'Long ', 'Fu ', 'Dan ', 'Chen ', 'Pin ', 'Pi ', 'Xiang ', 'Huo ', 'Mo ', 'Xi ', 'Duo ', 'Ku ', 'Yan ', 'Chan ', 'Ying ', 'Rang ', 'Dian ', 'La ', 'Ta ', 'Xiao ', 'Jiao ', 'Chuo ', 'Huan ', 'Huo ', 'Zhuan ', 'Nie ', 'Xiao ', 'Ca ', 'Li ', 'Chan ', 'Chai ', 'Li ', 'Yi ', 'Luo ', 'Nang ', 'Zan ', 'Su ', 'Xi ', 'So ', 'Jian ', 'Za ', 'Zhu ', 'Lan ', 'Nie ', 'Nang ', '[?] ', '[?] ', 'Wei ', 'Hui ', 'Yin ', 'Qiu ', 'Si ', 'Nin ', 'Jian ', 'Hui ', 'Xin ', 'Yin ', 'Nan ', 'Tuan ', 'Tuan ', 'Dun ', 'Kang ', 'Yuan ', 'Jiong ', 'Pian ', 'Yun ', 'Cong ', 'Hu ', 'Hui ', 'Yuan ', 'You ', 'Guo ', 'Kun ', 'Cong ', 'Wei ', 'Tu ', 'Wei ', 'Lun ', 'Guo ', 'Qun ', 'Ri ', 'Ling ', 'Gu ', 'Guo ', 'Tai ', 'Guo ', 'Tu ', 'You '];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '(1)', '(2)', '(3)', '(4)', '(5)', '(6)', '(7)', '(8)', '(9)', '(10)', '(11)', '(12)', '(13)', '(14)', '(15)', '(16)', '(17)', '(18)', '(19)', '(20)', '1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.', '11.', '12.', '13.', '14.', '15.', '16.', '17.', '18.', '19.', '20.', '(a)', '(b)', '(c)', '(d)', '(e)', '(f)', '(g)', '(h)', '(i)', '(j)', '(k)', '(l)', '(m)', '(n)', '(o)', '(p)', '(q)', '(r)', '(s)', '(t)', '(u)', '(v)', '(w)', '(x)', '(y)', '(z)', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '0'];
<?php return ['//', '/', ',', '!', '!', '-', ',', ',', ';', '?', '~', '{', '}', '*', '[?]', '', '\'', '', 'b', 'g', 'g', 'd', 'd', 'h', 'w', 'z', 'H', 't', 't', 'y', 'yh', 'k', 'l', 'm', 'n', 's', 's', '`', 'p', 'p', 'S', 'q', 'r', 'sh', 't', '[?]', '[?]', '[?]', 'a', 'a', 'a', 'A', 'A', 'A', 'e', 'e', 'e', 'E', 'i', 'i', 'u', 'u', 'u', 'o', '', '`', '\'', '', '', 'X', 'Q', '@', '@', '|', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'h', 'sh', 'n', 'r', 'b', 'L', 'k', '\'', 'v', 'm', 'f', 'dh', 'th', 'l', 'g', 'ny', 's', 'd', 'z', 't', 'y', 'p', 'j', 'ch', 'tt', 'hh', 'kh', 'th', 'z', 'sh', 's', 'd', 't', 'z', '`', 'gh', 'q', 'w', 'a', 'aa', 'i', 'ee', 'u', 'oo', 'e', 'ey', 'o', 'oa', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '*', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '|', '', '', '', '', '', '', '[?]', '[?]', '', '!', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[', '[?]', '<', '> ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Yao ', 'Lao ', '[?] ', 'Kao ', 'Mao ', 'Zhe ', 'Qi ', 'Gou ', 'Gou ', 'Gou ', 'Die ', 'Die ', 'Er ', 'Shua ', 'Ruan ', 'Er ', 'Nai ', 'Zhuan ', 'Lei ', 'Ting ', 'Zi ', 'Geng ', 'Chao ', 'Hao ', 'Yun ', 'Pa ', 'Pi ', 'Chi ', 'Si ', 'Chu ', 'Jia ', 'Ju ', 'He ', 'Chu ', 'Lao ', 'Lun ', 'Ji ', 'Tang ', 'Ou ', 'Lou ', 'Nou ', 'Gou ', 'Pang ', 'Ze ', 'Lou ', 'Ji ', 'Lao ', 'Huo ', 'You ', 'Mo ', 'Huai ', 'Er ', 'Zhe ', 'Ting ', 'Ye ', 'Da ', 'Song ', 'Qin ', 'Yun ', 'Chi ', 'Dan ', 'Dan ', 'Hong ', 'Geng ', 'Zhi ', '[?] ', 'Nie ', 'Dan ', 'Zhen ', 'Che ', 'Ling ', 'Zheng ', 'You ', 'Wa ', 'Liao ', 'Long ', 'Zhi ', 'Ning ', 'Tiao ', 'Er ', 'Ya ', 'Die ', 'Gua ', '[?] ', 'Lian ', 'Hao ', 'Sheng ', 'Lie ', 'Pin ', 'Jing ', 'Ju ', 'Bi ', 'Di ', 'Guo ', 'Wen ', 'Xu ', 'Ping ', 'Cong ', 'Shikato ', '[?] ', 'Ting ', 'Yu ', 'Cong ', 'Kui ', 'Tsuraneru ', 'Kui ', 'Cong ', 'Lian ', 'Weng ', 'Kui ', 'Lian ', 'Lian ', 'Cong ', 'Ao ', 'Sheng ', 'Song ', 'Ting ', 'Kui ', 'Nie ', 'Zhi ', 'Dan ', 'Ning ', 'Qie ', 'Ji ', 'Ting ', 'Ting ', 'Long ', 'Yu ', 'Yu ', 'Zhao ', 'Si ', 'Su ', 'Yi ', 'Su ', 'Si ', 'Zhao ', 'Zhao ', 'Rou ', 'Yi ', 'Le ', 'Ji ', 'Qiu ', 'Ken ', 'Cao ', 'Ge ', 'Di ', 'Huan ', 'Huang ', 'Yi ', 'Ren ', 'Xiao ', 'Ru ', 'Zhou ', 'Yuan ', 'Du ', 'Gang ', 'Rong ', 'Gan ', 'Cha ', 'Wo ', 'Chang ', 'Gu ', 'Zhi ', 'Han ', 'Fu ', 'Fei ', 'Fen ', 'Pei ', 'Pang ', 'Jian ', 'Fang ', 'Zhun ', 'You ', 'Na ', 'Hang ', 'Ken ', 'Ran ', 'Gong ', 'Yu ', 'Wen ', 'Yao ', 'Jin ', 'Pi ', 'Qian ', 'Xi ', 'Xi ', 'Fei ', 'Ken ', 'Jing ', 'Tai ', 'Shen ', 'Zhong ', 'Zhang ', 'Xie ', 'Shen ', 'Wei ', 'Zhou ', 'Die ', 'Dan ', 'Fei ', 'Ba ', 'Bo ', 'Qu ', 'Tian ', 'Bei ', 'Gua ', 'Tai ', 'Zi ', 'Ku ', 'Zhi ', 'Ni ', 'Ping ', 'Zi ', 'Fu ', 'Pang ', 'Zhen ', 'Xian ', 'Zuo ', 'Pei ', 'Jia ', 'Sheng ', 'Zhi ', 'Bao ', 'Mu ', 'Qu ', 'Hu ', 'Ke ', 'Yi ', 'Yin ', 'Xu ', 'Yang ', 'Long ', 'Dong ', 'Ka ', 'Lu ', 'Jing ', 'Nu ', 'Yan ', 'Pang ', 'Kua ', 'Yi ', 'Guang ', 'Gai ', 'Ge ', 'Dong ', 'Zhi ', 'Xiao ', 'Xiong ', 'Xiong ', 'Er ', 'E ', 'Xing ', 'Pian ', 'Neng ', 'Zi ', 'Gui '];
<?php return ['[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '-', '[?]', '[?]', '/', '\\', '*', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '|', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ':', '[?]', '[?]', '[?]', '[?]', '[?]', '~', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '<=', '>=', '<=', '>=', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['syae', 'syaeg', 'syaegg', 'syaegs', 'syaen', 'syaenj', 'syaenh', 'syaed', 'syael', 'syaelg', 'syaelm', 'syaelb', 'syaels', 'syaelt', 'syaelp', 'syaelh', 'syaem', 'syaeb', 'syaebs', 'syaes', 'syaess', 'syaeng', 'syaej', 'syaec', 'syaek', 'syaet', 'syaep', 'syaeh', 'seo', 'seog', 'seogg', 'seogs', 'seon', 'seonj', 'seonh', 'seod', 'seol', 'seolg', 'seolm', 'seolb', 'seols', 'seolt', 'seolp', 'seolh', 'seom', 'seob', 'seobs', 'seos', 'seoss', 'seong', 'seoj', 'seoc', 'seok', 'seot', 'seop', 'seoh', 'se', 'seg', 'segg', 'segs', 'sen', 'senj', 'senh', 'sed', 'sel', 'selg', 'selm', 'selb', 'sels', 'selt', 'selp', 'selh', 'sem', 'seb', 'sebs', 'ses', 'sess', 'seng', 'sej', 'sec', 'sek', 'set', 'sep', 'seh', 'syeo', 'syeog', 'syeogg', 'syeogs', 'syeon', 'syeonj', 'syeonh', 'syeod', 'syeol', 'syeolg', 'syeolm', 'syeolb', 'syeols', 'syeolt', 'syeolp', 'syeolh', 'syeom', 'syeob', 'syeobs', 'syeos', 'syeoss', 'syeong', 'syeoj', 'syeoc', 'syeok', 'syeot', 'syeop', 'syeoh', 'sye', 'syeg', 'syegg', 'syegs', 'syen', 'syenj', 'syenh', 'syed', 'syel', 'syelg', 'syelm', 'syelb', 'syels', 'syelt', 'syelp', 'syelh', 'syem', 'syeb', 'syebs', 'syes', 'syess', 'syeng', 'syej', 'syec', 'syek', 'syet', 'syep', 'syeh', 'so', 'sog', 'sogg', 'sogs', 'son', 'sonj', 'sonh', 'sod', 'sol', 'solg', 'solm', 'solb', 'sols', 'solt', 'solp', 'solh', 'som', 'sob', 'sobs', 'sos', 'soss', 'song', 'soj', 'soc', 'sok', 'sot', 'sop', 'soh', 'swa', 'swag', 'swagg', 'swags', 'swan', 'swanj', 'swanh', 'swad', 'swal', 'swalg', 'swalm', 'swalb', 'swals', 'swalt', 'swalp', 'swalh', 'swam', 'swab', 'swabs', 'swas', 'swass', 'swang', 'swaj', 'swac', 'swak', 'swat', 'swap', 'swah', 'swae', 'swaeg', 'swaegg', 'swaegs', 'swaen', 'swaenj', 'swaenh', 'swaed', 'swael', 'swaelg', 'swaelm', 'swaelb', 'swaels', 'swaelt', 'swaelp', 'swaelh', 'swaem', 'swaeb', 'swaebs', 'swaes', 'swaess', 'swaeng', 'swaej', 'swaec', 'swaek', 'swaet', 'swaep', 'swaeh', 'soe', 'soeg', 'soegg', 'soegs', 'soen', 'soenj', 'soenh', 'soed', 'soel', 'soelg', 'soelm', 'soelb', 'soels', 'soelt', 'soelp', 'soelh', 'soem', 'soeb', 'soebs', 'soes', 'soess', 'soeng', 'soej', 'soec', 'soek', 'soet', 'soep', 'soeh', 'syo', 'syog', 'syogg', 'syogs'];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '{', '} ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['Za ', 'Bi ', 'Shi ', 'Bu ', 'Ding ', 'Shuai ', 'Fan ', 'Nie ', 'Shi ', 'Fen ', 'Pa ', 'Zhi ', 'Xi ', 'Hu ', 'Dan ', 'Wei ', 'Zhang ', 'Tang ', 'Dai ', 'Ma ', 'Pei ', 'Pa ', 'Tie ', 'Fu ', 'Lian ', 'Zhi ', 'Zhou ', 'Bo ', 'Zhi ', 'Di ', 'Mo ', 'Yi ', 'Yi ', 'Ping ', 'Qia ', 'Juan ', 'Ru ', 'Shuai ', 'Dai ', 'Zheng ', 'Shui ', 'Qiao ', 'Zhen ', 'Shi ', 'Qun ', 'Xi ', 'Bang ', 'Dai ', 'Gui ', 'Chou ', 'Ping ', 'Zhang ', 'Sha ', 'Wan ', 'Dai ', 'Wei ', 'Chang ', 'Sha ', 'Qi ', 'Ze ', 'Guo ', 'Mao ', 'Du ', 'Hou ', 'Zheng ', 'Xu ', 'Mi ', 'Wei ', 'Wo ', 'Fu ', 'Yi ', 'Bang ', 'Ping ', 'Tazuna ', 'Gong ', 'Pan ', 'Huang ', 'Dao ', 'Mi ', 'Jia ', 'Teng ', 'Hui ', 'Zhong ', 'Shan ', 'Man ', 'Mu ', 'Biao ', 'Guo ', 'Ze ', 'Mu ', 'Bang ', 'Zhang ', 'Jiong ', 'Chan ', 'Fu ', 'Zhi ', 'Hu ', 'Fan ', 'Chuang ', 'Bi ', 'Hei ', '[?] ', 'Mi ', 'Qiao ', 'Chan ', 'Fen ', 'Meng ', 'Bang ', 'Chou ', 'Mie ', 'Chu ', 'Jie ', 'Xian ', 'Lan ', 'Gan ', 'Ping ', 'Nian ', 'Qian ', 'Bing ', 'Bing ', 'Xing ', 'Gan ', 'Yao ', 'Huan ', 'You ', 'You ', 'Ji ', 'Yan ', 'Pi ', 'Ting ', 'Ze ', 'Guang ', 'Zhuang ', 'Mo ', 'Qing ', 'Bi ', 'Qin ', 'Dun ', 'Chuang ', 'Gui ', 'Ya ', 'Bai ', 'Jie ', 'Xu ', 'Lu ', 'Wu ', '[?] ', 'Ku ', 'Ying ', 'Di ', 'Pao ', 'Dian ', 'Ya ', 'Miao ', 'Geng ', 'Ci ', 'Fu ', 'Tong ', 'Pang ', 'Fei ', 'Xiang ', 'Yi ', 'Zhi ', 'Tiao ', 'Zhi ', 'Xiu ', 'Du ', 'Zuo ', 'Xiao ', 'Tu ', 'Gui ', 'Ku ', 'Pang ', 'Ting ', 'You ', 'Bu ', 'Ding ', 'Cheng ', 'Lai ', 'Bei ', 'Ji ', 'An ', 'Shu ', 'Kang ', 'Yong ', 'Tuo ', 'Song ', 'Shu ', 'Qing ', 'Yu ', 'Yu ', 'Miao ', 'Sou ', 'Ce ', 'Xiang ', 'Fei ', 'Jiu ', 'He ', 'Hui ', 'Liu ', 'Sha ', 'Lian ', 'Lang ', 'Sou ', 'Jian ', 'Pou ', 'Qing ', 'Jiu ', 'Jiu ', 'Qin ', 'Ao ', 'Kuo ', 'Lou ', 'Yin ', 'Liao ', 'Dai ', 'Lu ', 'Yi ', 'Chu ', 'Chan ', 'Tu ', 'Si ', 'Xin ', 'Miao ', 'Chang ', 'Wu ', 'Fei ', 'Guang ', 'Koc ', 'Kuai ', 'Bi ', 'Qiang ', 'Xie ', 'Lin ', 'Lin ', 'Liao ', 'Lu ', '[?] ', 'Ying ', 'Xian ', 'Ting ', 'Yong ', 'Li ', 'Ting ', 'Yin ', 'Xun ', 'Yan ', 'Ting ', 'Di ', 'Po ', 'Jian ', 'Hui ', 'Nai ', 'Hui ', 'Gong ', 'Nian '];
<?php return ['Fu ', 'Zhuo ', 'Mao ', 'Fan ', 'Qie ', 'Mao ', 'Mao ', 'Ba ', 'Zi ', 'Mo ', 'Zi ', 'Di ', 'Chi ', 'Ji ', 'Jing ', 'Long ', '[?] ', 'Niao ', '[?] ', 'Xue ', 'Ying ', 'Qiong ', 'Ge ', 'Ming ', 'Li ', 'Rong ', 'Yin ', 'Gen ', 'Qian ', 'Chai ', 'Chen ', 'Yu ', 'Xiu ', 'Zi ', 'Lie ', 'Wu ', 'Ji ', 'Kui ', 'Ce ', 'Chong ', 'Ci ', 'Gou ', 'Guang ', 'Mang ', 'Chi ', 'Jiao ', 'Jiao ', 'Fu ', 'Yu ', 'Zhu ', 'Zi ', 'Jiang ', 'Hui ', 'Yin ', 'Cha ', 'Fa ', 'Rong ', 'Ru ', 'Chong ', 'Mang ', 'Tong ', 'Zhong ', '[?] ', 'Zhu ', 'Xun ', 'Huan ', 'Kua ', 'Quan ', 'Gai ', 'Da ', 'Jing ', 'Xing ', 'Quan ', 'Cao ', 'Jing ', 'Er ', 'An ', 'Shou ', 'Chi ', 'Ren ', 'Jian ', 'Ti ', 'Huang ', 'Ping ', 'Li ', 'Jin ', 'Lao ', 'Shu ', 'Zhuang ', 'Da ', 'Jia ', 'Rao ', 'Bi ', 'Ze ', 'Qiao ', 'Hui ', 'Qi ', 'Dang ', '[?] ', 'Rong ', 'Hun ', 'Ying ', 'Luo ', 'Ying ', 'Xun ', 'Jin ', 'Sun ', 'Yin ', 'Mai ', 'Hong ', 'Zhou ', 'Yao ', 'Du ', 'Wei ', 'Chu ', 'Dou ', 'Fu ', 'Ren ', 'Yin ', 'He ', 'Bi ', 'Bu ', 'Yun ', 'Di ', 'Tu ', 'Sui ', 'Sui ', 'Cheng ', 'Chen ', 'Wu ', 'Bie ', 'Xi ', 'Geng ', 'Li ', 'Fu ', 'Zhu ', 'Mo ', 'Li ', 'Zhuang ', 'Ji ', 'Duo ', 'Qiu ', 'Sha ', 'Suo ', 'Chen ', 'Feng ', 'Ju ', 'Mei ', 'Meng ', 'Xing ', 'Jing ', 'Che ', 'Xin ', 'Jun ', 'Yan ', 'Ting ', 'Diao ', 'Cuo ', 'Wan ', 'Han ', 'You ', 'Cuo ', 'Jia ', 'Wang ', 'You ', 'Niu ', 'Shao ', 'Xian ', 'Lang ', 'Fu ', 'E ', 'Mo ', 'Wen ', 'Jie ', 'Nan ', 'Mu ', 'Kan ', 'Lai ', 'Lian ', 'Shi ', 'Wo ', 'Usagi ', 'Lian ', 'Huo ', 'You ', 'Ying ', 'Ying ', 'Nuc ', 'Chun ', 'Mang ', 'Mang ', 'Ci ', 'Wan ', 'Jing ', 'Di ', 'Qu ', 'Dong ', 'Jian ', 'Zou ', 'Gu ', 'La ', 'Lu ', 'Ju ', 'Wei ', 'Jun ', 'Nie ', 'Kun ', 'He ', 'Pu ', 'Zi ', 'Gao ', 'Guo ', 'Fu ', 'Lun ', 'Chang ', 'Chou ', 'Song ', 'Chui ', 'Zhan ', 'Men ', 'Cai ', 'Ba ', 'Li ', 'Tu ', 'Bo ', 'Han ', 'Bao ', 'Qin ', 'Juan ', 'Xi ', 'Qin ', 'Di ', 'Jie ', 'Pu ', 'Dang ', 'Jin ', 'Zhao ', 'Tai ', 'Geng ', 'Hua ', 'Gu ', 'Ling ', 'Fei ', 'Jin ', 'An ', 'Wang ', 'Beng ', 'Zhou ', 'Yan ', 'Ju ', 'Jian ', 'Lin ', 'Tan ', 'Shu ', 'Tian ', 'Dao '];
<?php return ['Hu ', 'Ye ', 'Ding ', 'Qing ', 'Pan ', 'Xiang ', 'Shun ', 'Han ', 'Xu ', 'Yi ', 'Xu ', 'Gu ', 'Song ', 'Kui ', 'Qi ', 'Hang ', 'Yu ', 'Wan ', 'Ban ', 'Dun ', 'Di ', 'Dan ', 'Pan ', 'Po ', 'Ling ', 'Ce ', 'Jing ', 'Lei ', 'He ', 'Qiao ', 'E ', 'E ', 'Wei ', 'Jie ', 'Gua ', 'Shen ', 'Yi ', 'Shen ', 'Hai ', 'Dui ', 'Pian ', 'Ping ', 'Lei ', 'Fu ', 'Jia ', 'Tou ', 'Hui ', 'Kui ', 'Jia ', 'Le ', 'Tian ', 'Cheng ', 'Ying ', 'Jun ', 'Hu ', 'Han ', 'Jing ', 'Tui ', 'Tui ', 'Pin ', 'Lai ', 'Tui ', 'Zi ', 'Zi ', 'Chui ', 'Ding ', 'Lai ', 'Yan ', 'Han ', 'Jian ', 'Ke ', 'Cui ', 'Jiong ', 'Qin ', 'Yi ', 'Sai ', 'Ti ', 'E ', 'E ', 'Yan ', 'Hun ', 'Kan ', 'Yong ', 'Zhuan ', 'Yan ', 'Xian ', 'Xin ', 'Yi ', 'Yuan ', 'Sang ', 'Dian ', 'Dian ', 'Jiang ', 'Ku ', 'Lei ', 'Liao ', 'Piao ', 'Yi ', 'Man ', 'Qi ', 'Rao ', 'Hao ', 'Qiao ', 'Gu ', 'Xun ', 'Qian ', 'Hui ', 'Zhan ', 'Ru ', 'Hong ', 'Bin ', 'Xian ', 'Pin ', 'Lu ', 'Lan ', 'Nie ', 'Quan ', 'Ye ', 'Ding ', 'Qing ', 'Han ', 'Xiang ', 'Shun ', 'Xu ', 'Xu ', 'Wan ', 'Gu ', 'Dun ', 'Qi ', 'Ban ', 'Song ', 'Hang ', 'Yu ', 'Lu ', 'Ling ', 'Po ', 'Jing ', 'Jie ', 'Jia ', 'Tian ', 'Han ', 'Ying ', 'Jiong ', 'Hai ', 'Yi ', 'Pin ', 'Hui ', 'Tui ', 'Han ', 'Ying ', 'Ying ', 'Ke ', 'Ti ', 'Yong ', 'E ', 'Zhuan ', 'Yan ', 'E ', 'Nie ', 'Man ', 'Dian ', 'Sang ', 'Hao ', 'Lei ', 'Zhan ', 'Ru ', 'Pin ', 'Quan ', 'Feng ', 'Biao ', 'Oroshi ', 'Fu ', 'Xia ', 'Zhan ', 'Biao ', 'Sa ', 'Ba ', 'Tai ', 'Lie ', 'Gua ', 'Xuan ', 'Shao ', 'Ju ', 'Bi ', 'Si ', 'Wei ', 'Yang ', 'Yao ', 'Sou ', 'Kai ', 'Sao ', 'Fan ', 'Liu ', 'Xi ', 'Liao ', 'Piao ', 'Piao ', 'Liu ', 'Biao ', 'Biao ', 'Biao ', 'Liao ', '[?] ', 'Se ', 'Feng ', 'Biao ', 'Feng ', 'Yang ', 'Zhan ', 'Biao ', 'Sa ', 'Ju ', 'Si ', 'Sou ', 'Yao ', 'Liu ', 'Piao ', 'Biao ', 'Biao ', 'Fei ', 'Fan ', 'Fei ', 'Fei ', 'Shi ', 'Shi ', 'Can ', 'Ji ', 'Ding ', 'Si ', 'Tuo ', 'Zhan ', 'Sun ', 'Xiang ', 'Tun ', 'Ren ', 'Yu ', 'Juan ', 'Chi ', 'Yin ', 'Fan ', 'Fan ', 'Sun ', 'Yin ', 'Zhu ', 'Yi ', 'Zhai ', 'Bi ', 'Jie ', 'Tao ', 'Liu ', 'Ci ', 'Tie ', 'Si ', 'Bao ', 'Shi ', 'Duo '];
<?php return ['Tani ', 'Jiao ', '[?] ', 'Zhang ', 'Qiao ', 'Dun ', 'Xian ', 'Yu ', 'Zhui ', 'He ', 'Huo ', 'Zhai ', 'Lei ', 'Ke ', 'Chu ', 'Ji ', 'Que ', 'Dang ', 'Yi ', 'Jiang ', 'Pi ', 'Pi ', 'Yu ', 'Pin ', 'Qi ', 'Ai ', 'Kai ', 'Jian ', 'Yu ', 'Ruan ', 'Meng ', 'Pao ', 'Ci ', '[?] ', '[?] ', 'Mie ', 'Ca ', 'Xian ', 'Kuang ', 'Lei ', 'Lei ', 'Zhi ', 'Li ', 'Li ', 'Fan ', 'Que ', 'Pao ', 'Ying ', 'Li ', 'Long ', 'Long ', 'Mo ', 'Bo ', 'Shuang ', 'Guan ', 'Lan ', 'Zan ', 'Yan ', 'Shi ', 'Shi ', 'Li ', 'Reng ', 'She ', 'Yue ', 'Si ', 'Qi ', 'Ta ', 'Ma ', 'Xie ', 'Xian ', 'Xian ', 'Zhi ', 'Qi ', 'Zhi ', 'Beng ', 'Dui ', 'Zhong ', '[?] ', 'Yi ', 'Shi ', 'You ', 'Zhi ', 'Tiao ', 'Fu ', 'Fu ', 'Mi ', 'Zu ', 'Zhi ', 'Suan ', 'Mei ', 'Zuo ', 'Qu ', 'Hu ', 'Zhu ', 'Shen ', 'Sui ', 'Ci ', 'Chai ', 'Mi ', 'Lu ', 'Yu ', 'Xiang ', 'Wu ', 'Tiao ', 'Piao ', 'Zhu ', 'Gui ', 'Xia ', 'Zhi ', 'Ji ', 'Gao ', 'Zhen ', 'Gao ', 'Shui ', 'Jin ', 'Chen ', 'Gai ', 'Kun ', 'Di ', 'Dao ', 'Huo ', 'Tao ', 'Qi ', 'Gu ', 'Guan ', 'Zui ', 'Ling ', 'Lu ', 'Bing ', 'Jin ', 'Dao ', 'Zhi ', 'Lu ', 'Shan ', 'Bei ', 'Zhe ', 'Hui ', 'You ', 'Xi ', 'Yin ', 'Zi ', 'Huo ', 'Zhen ', 'Fu ', 'Yuan ', 'Wu ', 'Xian ', 'Yang ', 'Ti ', 'Yi ', 'Mei ', 'Si ', 'Di ', '[?] ', 'Zhuo ', 'Zhen ', 'Yong ', 'Ji ', 'Gao ', 'Tang ', 'Si ', 'Ma ', 'Ta ', '[?] ', 'Xuan ', 'Qi ', 'Yu ', 'Xi ', 'Ji ', 'Si ', 'Chan ', 'Tan ', 'Kuai ', 'Sui ', 'Li ', 'Nong ', 'Ni ', 'Dao ', 'Li ', 'Rang ', 'Yue ', 'Ti ', 'Zan ', 'Lei ', 'Rou ', 'Yu ', 'Yu ', 'Chi ', 'Xie ', 'Qin ', 'He ', 'Tu ', 'Xiu ', 'Si ', 'Ren ', 'Tu ', 'Zi ', 'Cha ', 'Gan ', 'Yi ', 'Xian ', 'Bing ', 'Nian ', 'Qiu ', 'Qiu ', 'Chong ', 'Fen ', 'Hao ', 'Yun ', 'Ke ', 'Miao ', 'Zhi ', 'Geng ', 'Bi ', 'Zhi ', 'Yu ', 'Mi ', 'Ku ', 'Ban ', 'Pi ', 'Ni ', 'Li ', 'You ', 'Zu ', 'Pi ', 'Ba ', 'Ling ', 'Mo ', 'Cheng ', 'Nian ', 'Qin ', 'Yang ', 'Zuo ', 'Zhi ', 'Zhi ', 'Shu ', 'Ju ', 'Zi ', 'Huo ', 'Ji ', 'Cheng ', 'Tong ', 'Zhi ', 'Huo ', 'He ', 'Yin ', 'Zi ', 'Zhi ', 'Jie ', 'Ren ', 'Du ', 'Yi ', 'Zhu ', 'Hui ', 'Nong ', 'Fu '];
<?php return ['Ji ', 'Zhi ', 'Gua ', 'Ken ', 'Che ', 'Ti ', 'Ti ', 'Fu ', 'Chong ', 'Xie ', 'Bian ', 'Die ', 'Kun ', 'Duan ', 'Xiu ', 'Xiu ', 'He ', 'Yuan ', 'Bao ', 'Bao ', 'Fu ', 'Yu ', 'Tuan ', 'Yan ', 'Hui ', 'Bei ', 'Chu ', 'Lu ', 'Ena ', 'Hitoe ', 'Yun ', 'Da ', 'Gou ', 'Da ', 'Huai ', 'Rong ', 'Yuan ', 'Ru ', 'Nai ', 'Jiong ', 'Suo ', 'Ban ', 'Tun ', 'Chi ', 'Sang ', 'Niao ', 'Ying ', 'Jie ', 'Qian ', 'Huai ', 'Ku ', 'Lian ', 'Bao ', 'Li ', 'Zhe ', 'Shi ', 'Lu ', 'Yi ', 'Die ', 'Xie ', 'Xian ', 'Wei ', 'Biao ', 'Cao ', 'Ji ', 'Jiang ', 'Sen ', 'Bao ', 'Xiang ', 'Chihaya ', 'Pu ', 'Jian ', 'Zhuan ', 'Jian ', 'Zui ', 'Ji ', 'Dan ', 'Za ', 'Fan ', 'Bo ', 'Xiang ', 'Xin ', 'Bie ', 'Rao ', 'Man ', 'Lan ', 'Ao ', 'Duo ', 'Gui ', 'Cao ', 'Sui ', 'Nong ', 'Chan ', 'Lian ', 'Bi ', 'Jin ', 'Dang ', 'Shu ', 'Tan ', 'Bi ', 'Lan ', 'Pu ', 'Ru ', 'Zhi ', '[?] ', 'Shu ', 'Wa ', 'Shi ', 'Bai ', 'Xie ', 'Bo ', 'Chen ', 'Lai ', 'Long ', 'Xi ', 'Xian ', 'Lan ', 'Zhe ', 'Dai ', 'Tasuki ', 'Zan ', 'Shi ', 'Jian ', 'Pan ', 'Yi ', 'Ran ', 'Ya ', 'Xi ', 'Xi ', 'Yao ', 'Feng ', 'Tan ', '[?] ', 'Biao ', 'Fu ', 'Ba ', 'He ', 'Ji ', 'Ji ', 'Jian ', 'Guan ', 'Bian ', 'Yan ', 'Gui ', 'Jue ', 'Pian ', 'Mao ', 'Mi ', 'Mi ', 'Mie ', 'Shi ', 'Si ', 'Zhan ', 'Luo ', 'Jue ', 'Mi ', 'Tiao ', 'Lian ', 'Yao ', 'Zhi ', 'Jun ', 'Xi ', 'Shan ', 'Wei ', 'Xi ', 'Tian ', 'Yu ', 'Lan ', 'E ', 'Du ', 'Qin ', 'Pang ', 'Ji ', 'Ming ', 'Ying ', 'Gou ', 'Qu ', 'Zhan ', 'Jin ', 'Guan ', 'Deng ', 'Jian ', 'Luo ', 'Qu ', 'Jian ', 'Wei ', 'Jue ', 'Qu ', 'Luo ', 'Lan ', 'Shen ', 'Di ', 'Guan ', 'Jian ', 'Guan ', 'Yan ', 'Gui ', 'Mi ', 'Shi ', 'Zhan ', 'Lan ', 'Jue ', 'Ji ', 'Xi ', 'Di ', 'Tian ', 'Yu ', 'Gou ', 'Jin ', 'Qu ', 'Jiao ', 'Jiu ', 'Jin ', 'Cu ', 'Jue ', 'Zhi ', 'Chao ', 'Ji ', 'Gu ', 'Dan ', 'Zui ', 'Di ', 'Shang ', 'Hua ', 'Quan ', 'Ge ', 'Chi ', 'Jie ', 'Gui ', 'Gong ', 'Hong ', 'Jie ', 'Hun ', 'Qiu ', 'Xing ', 'Su ', 'Ni ', 'Ji ', 'Lu ', 'Zhi ', 'Zha ', 'Bi ', 'Xing ', 'Hu ', 'Shang ', 'Gong ', 'Zhi ', 'Xue ', 'Chu ', 'Xi ', 'Yi ', 'Lu ', 'Jue ', 'Xi ', 'Yan ', 'Xi '];
<?php return ['Yu ', 'Cui ', 'Ya ', 'Zhu ', 'Cu ', 'Dan ', 'Shen ', 'Zhung ', 'Ji ', 'Yu ', 'Hou ', 'Feng ', 'La ', 'Yang ', 'Shen ', 'Tu ', 'Yu ', 'Gua ', 'Wen ', 'Huan ', 'Ku ', 'Jia ', 'Yin ', 'Yi ', 'Lu ', 'Sao ', 'Jue ', 'Chi ', 'Xi ', 'Guan ', 'Yi ', 'Wen ', 'Ji ', 'Chuang ', 'Ban ', 'Lei ', 'Liu ', 'Chai ', 'Shou ', 'Nue ', 'Dian ', 'Da ', 'Pie ', 'Tan ', 'Zhang ', 'Biao ', 'Shen ', 'Cu ', 'Luo ', 'Yi ', 'Zong ', 'Chou ', 'Zhang ', 'Zhai ', 'Sou ', 'Suo ', 'Que ', 'Diao ', 'Lou ', 'Lu ', 'Mo ', 'Jin ', 'Yin ', 'Ying ', 'Huang ', 'Fu ', 'Liao ', 'Long ', 'Qiao ', 'Liu ', 'Lao ', 'Xian ', 'Fei ', 'Dan ', 'Yin ', 'He ', 'Yan ', 'Ban ', 'Xian ', 'Guan ', 'Guai ', 'Nong ', 'Yu ', 'Wei ', 'Yi ', 'Yong ', 'Pi ', 'Lei ', 'Li ', 'Shu ', 'Dan ', 'Lin ', 'Dian ', 'Lin ', 'Lai ', 'Pie ', 'Ji ', 'Chi ', 'Yang ', 'Xian ', 'Jie ', 'Zheng ', '[?] ', 'Li ', 'Huo ', 'Lai ', 'Shaku ', 'Dian ', 'Xian ', 'Ying ', 'Yin ', 'Qu ', 'Yong ', 'Tan ', 'Dian ', 'Luo ', 'Luan ', 'Luan ', 'Bo ', '[?] ', 'Gui ', 'Po ', 'Fa ', 'Deng ', 'Fa ', 'Bai ', 'Bai ', 'Qie ', 'Bi ', 'Zao ', 'Zao ', 'Mao ', 'De ', 'Pa ', 'Jie ', 'Huang ', 'Gui ', 'Ci ', 'Ling ', 'Gao ', 'Mo ', 'Ji ', 'Jiao ', 'Peng ', 'Gao ', 'Ai ', 'E ', 'Hao ', 'Han ', 'Bi ', 'Wan ', 'Chou ', 'Qian ', 'Xi ', 'Ai ', 'Jiong ', 'Hao ', 'Huang ', 'Hao ', 'Ze ', 'Cui ', 'Hao ', 'Xiao ', 'Ye ', 'Po ', 'Hao ', 'Jiao ', 'Ai ', 'Xing ', 'Huang ', 'Li ', 'Piao ', 'He ', 'Jiao ', 'Pi ', 'Gan ', 'Pao ', 'Zhou ', 'Jun ', 'Qiu ', 'Cun ', 'Que ', 'Zha ', 'Gu ', 'Jun ', 'Jun ', 'Zhou ', 'Zha ', 'Gu ', 'Zhan ', 'Du ', 'Min ', 'Qi ', 'Ying ', 'Yu ', 'Bei ', 'Zhao ', 'Zhong ', 'Pen ', 'He ', 'Ying ', 'He ', 'Yi ', 'Bo ', 'Wan ', 'He ', 'Ang ', 'Zhan ', 'Yan ', 'Jian ', 'He ', 'Yu ', 'Kui ', 'Fan ', 'Gai ', 'Dao ', 'Pan ', 'Fu ', 'Qiu ', 'Sheng ', 'Dao ', 'Lu ', 'Zhan ', 'Meng ', 'Li ', 'Jin ', 'Xu ', 'Jian ', 'Pan ', 'Guan ', 'An ', 'Lu ', 'Shu ', 'Zhou ', 'Dang ', 'An ', 'Gu ', 'Li ', 'Mu ', 'Cheng ', 'Gan ', 'Xu ', 'Mang ', 'Mang ', 'Zhi ', 'Qi ', 'Ruan ', 'Tian ', 'Xiang ', 'Dun ', 'Xin ', 'Xi ', 'Pan ', 'Feng ', 'Dun ', 'Min '];
<?php return ['Zhou ', 'Ji ', 'Yi ', 'Hui ', 'Hui ', 'Zui ', 'Cheng ', 'Yin ', 'Wei ', 'Hou ', 'Jian ', 'Yang ', 'Lie ', 'Si ', 'Ji ', 'Er ', 'Xing ', 'Fu ', 'Sa ', 'Suo ', 'Zhi ', 'Yin ', 'Wu ', 'Xi ', 'Kao ', 'Zhu ', 'Jiang ', 'Luo ', '[?] ', 'An ', 'Dong ', 'Yi ', 'Mou ', 'Lei ', 'Yi ', 'Mi ', 'Quan ', 'Jin ', 'Mo ', 'Wei ', 'Xiao ', 'Xie ', 'Hong ', 'Xu ', 'Shuo ', 'Kuang ', 'Tao ', 'Qie ', 'Ju ', 'Er ', 'Zhou ', 'Ru ', 'Ping ', 'Xun ', 'Xiong ', 'Zhi ', 'Guang ', 'Huan ', 'Ming ', 'Huo ', 'Wa ', 'Qia ', 'Pai ', 'Wu ', 'Qu ', 'Liu ', 'Yi ', 'Jia ', 'Jing ', 'Qian ', 'Jiang ', 'Jiao ', 'Cheng ', 'Shi ', 'Zhuo ', 'Ce ', 'Pal ', 'Kuai ', 'Ji ', 'Liu ', 'Chan ', 'Hun ', 'Hu ', 'Nong ', 'Xun ', 'Jin ', 'Lie ', 'Qiu ', 'Wei ', 'Zhe ', 'Jun ', 'Han ', 'Bang ', 'Mang ', 'Zhuo ', 'You ', 'Xi ', 'Bo ', 'Dou ', 'Wan ', 'Hong ', 'Yi ', 'Pu ', 'Ying ', 'Lan ', 'Hao ', 'Lang ', 'Han ', 'Li ', 'Geng ', 'Fu ', 'Wu ', 'Lian ', 'Chun ', 'Feng ', 'Yi ', 'Yu ', 'Tong ', 'Lao ', 'Hai ', 'Jin ', 'Jia ', 'Chong ', 'Weng ', 'Mei ', 'Sui ', 'Cheng ', 'Pei ', 'Xian ', 'Shen ', 'Tu ', 'Kun ', 'Pin ', 'Nie ', 'Han ', 'Jing ', 'Xiao ', 'She ', 'Nian ', 'Tu ', 'Yong ', 'Xiao ', 'Xian ', 'Ting ', 'E ', 'Su ', 'Tun ', 'Juan ', 'Cen ', 'Ti ', 'Li ', 'Shui ', 'Si ', 'Lei ', 'Shui ', 'Tao ', 'Du ', 'Lao ', 'Lai ', 'Lian ', 'Wei ', 'Wo ', 'Yun ', 'Huan ', 'Di ', '[?] ', 'Run ', 'Jian ', 'Zhang ', 'Se ', 'Fu ', 'Guan ', 'Xing ', 'Shou ', 'Shuan ', 'Ya ', 'Chuo ', 'Zhang ', 'Ye ', 'Kong ', 'Wo ', 'Han ', 'Tuo ', 'Dong ', 'He ', 'Wo ', 'Ju ', 'Gan ', 'Liang ', 'Hun ', 'Ta ', 'Zhuo ', 'Dian ', 'Qie ', 'De ', 'Juan ', 'Zi ', 'Xi ', 'Yao ', 'Qi ', 'Gu ', 'Guo ', 'Han ', 'Lin ', 'Tang ', 'Zhou ', 'Peng ', 'Hao ', 'Chang ', 'Shu ', 'Qi ', 'Fang ', 'Chi ', 'Lu ', 'Nao ', 'Ju ', 'Tao ', 'Cong ', 'Lei ', 'Zhi ', 'Peng ', 'Fei ', 'Song ', 'Tian ', 'Pi ', 'Dan ', 'Yu ', 'Ni ', 'Yu ', 'Lu ', 'Gan ', 'Mi ', 'Jing ', 'Ling ', 'Lun ', 'Yin ', 'Cui ', 'Qu ', 'Huai ', 'Yu ', 'Nian ', 'Shen ', 'Piao ', 'Chun ', 'Wa ', 'Yuan ', 'Lai ', 'Hun ', 'Qing ', 'Yan ', 'Qian ', 'Tian ', 'Miao ', 'Zhi ', 'Yin ', 'Mi '];
<?php return ['Yao ', 'Yu ', 'Chong ', 'Xi ', 'Xi ', 'Jiu ', 'Yu ', 'Yu ', 'Xing ', 'Ju ', 'Jiu ', 'Xin ', 'She ', 'She ', 'Yadoru ', 'Jiu ', 'Shi ', 'Tan ', 'Shu ', 'Shi ', 'Tian ', 'Dan ', 'Pu ', 'Pu ', 'Guan ', 'Hua ', 'Tan ', 'Chuan ', 'Shun ', 'Xia ', 'Wu ', 'Zhou ', 'Dao ', 'Gang ', 'Shan ', 'Yi ', '[?] ', 'Pa ', 'Tai ', 'Fan ', 'Ban ', 'Chuan ', 'Hang ', 'Fang ', 'Ban ', 'Que ', 'Hesaki ', 'Zhong ', 'Jian ', 'Cang ', 'Ling ', 'Zhu ', 'Ze ', 'Duo ', 'Bo ', 'Xian ', 'Ge ', 'Chuan ', 'Jia ', 'Lu ', 'Hong ', 'Pang ', 'Xi ', '[?] ', 'Fu ', 'Zao ', 'Feng ', 'Li ', 'Shao ', 'Yu ', 'Lang ', 'Ting ', '[?] ', 'Wei ', 'Bo ', 'Meng ', 'Nian ', 'Ju ', 'Huang ', 'Shou ', 'Zong ', 'Bian ', 'Mao ', 'Die ', '[?] ', 'Bang ', 'Cha ', 'Yi ', 'Sao ', 'Cang ', 'Cao ', 'Lou ', 'Dai ', 'Sori ', 'Yao ', 'Tong ', 'Yofune ', 'Dang ', 'Tan ', 'Lu ', 'Yi ', 'Jie ', 'Jian ', 'Huo ', 'Meng ', 'Qi ', 'Lu ', 'Lu ', 'Chan ', 'Shuang ', 'Gen ', 'Liang ', 'Jian ', 'Jian ', 'Se ', 'Yan ', 'Fu ', 'Ping ', 'Yan ', 'Yan ', 'Cao ', 'Cao ', 'Yi ', 'Le ', 'Ting ', 'Qiu ', 'Ai ', 'Nai ', 'Tiao ', 'Jiao ', 'Jie ', 'Peng ', 'Wan ', 'Yi ', 'Chai ', 'Mian ', 'Mie ', 'Gan ', 'Qian ', 'Yu ', 'Yu ', 'Shuo ', 'Qiong ', 'Tu ', 'Xia ', 'Qi ', 'Mang ', 'Zi ', 'Hui ', 'Sui ', 'Zhi ', 'Xiang ', 'Bi ', 'Fu ', 'Tun ', 'Wei ', 'Wu ', 'Zhi ', 'Qi ', 'Shan ', 'Wen ', 'Qian ', 'Ren ', 'Fou ', 'Kou ', 'Jie ', 'Lu ', 'Xu ', 'Ji ', 'Qin ', 'Qi ', 'Yuan ', 'Fen ', 'Ba ', 'Rui ', 'Xin ', 'Ji ', 'Hua ', 'Hua ', 'Fang ', 'Wu ', 'Jue ', 'Gou ', 'Zhi ', 'Yun ', 'Qin ', 'Ao ', 'Chu ', 'Mao ', 'Ya ', 'Fei ', 'Reng ', 'Hang ', 'Cong ', 'Yin ', 'You ', 'Bian ', 'Yi ', 'Susa ', 'Wei ', 'Li ', 'Pi ', 'E ', 'Xian ', 'Chang ', 'Cang ', 'Meng ', 'Su ', 'Yi ', 'Yuan ', 'Ran ', 'Ling ', 'Tai ', 'Tiao ', 'Di ', 'Miao ', 'Qiong ', 'Li ', 'Yong ', 'Ke ', 'Mu ', 'Pei ', 'Bao ', 'Gou ', 'Min ', 'Yi ', 'Yi ', 'Ju ', 'Pi ', 'Ruo ', 'Ku ', 'Zhu ', 'Ni ', 'Bo ', 'Bing ', 'Shan ', 'Qiu ', 'Yao ', 'Xian ', 'Ben ', 'Hong ', 'Ying ', 'Zha ', 'Dong ', 'Ju ', 'Die ', 'Nie ', 'Gan ', 'Hu ', 'Ping ', 'Mei ', 'Fu ', 'Sheng ', 'Gu ', 'Bi ', 'Wei '];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
<?php return ['kax', 'ka', 'kap', 'kuox', 'kuo', 'kuop', 'kot', 'kox', 'ko', 'kop', 'ket', 'kex', 'ke', 'kep', 'kut', 'kux', 'ku', 'kup', 'kurx', 'kur', 'ggit', 'ggix', 'ggi', 'ggiex', 'ggie', 'ggiep', 'ggat', 'ggax', 'gga', 'ggap', 'gguot', 'gguox', 'gguo', 'gguop', 'ggot', 'ggox', 'ggo', 'ggop', 'gget', 'ggex', 'gge', 'ggep', 'ggut', 'ggux', 'ggu', 'ggup', 'ggurx', 'ggur', 'mgiex', 'mgie', 'mgat', 'mgax', 'mga', 'mgap', 'mguox', 'mguo', 'mguop', 'mgot', 'mgox', 'mgo', 'mgop', 'mgex', 'mge', 'mgep', 'mgut', 'mgux', 'mgu', 'mgup', 'mgurx', 'mgur', 'hxit', 'hxix', 'hxi', 'hxip', 'hxiet', 'hxiex', 'hxie', 'hxiep', 'hxat', 'hxax', 'hxa', 'hxap', 'hxuot', 'hxuox', 'hxuo', 'hxuop', 'hxot', 'hxox', 'hxo', 'hxop', 'hxex', 'hxe', 'hxep', 'ngiex', 'ngie', 'ngiep', 'ngat', 'ngax', 'nga', 'ngap', 'nguot', 'nguox', 'nguo', 'ngot', 'ngox', 'ngo', 'ngop', 'ngex', 'nge', 'ngep', 'hit', 'hiex', 'hie', 'hat', 'hax', 'ha', 'hap', 'huot', 'huox', 'huo', 'huop', 'hot', 'hox', 'ho', 'hop', 'hex', 'he', 'hep', 'wat', 'wax', 'wa', 'wap', 'wuox', 'wuo', 'wuop', 'wox', 'wo', 'wop', 'wex', 'we', 'wep', 'zit', 'zix', 'zi', 'zip', 'ziex', 'zie', 'ziep', 'zat', 'zax', 'za', 'zap', 'zuox', 'zuo', 'zuop', 'zot', 'zox', 'zo', 'zop', 'zex', 'ze', 'zep', 'zut', 'zux', 'zu', 'zup', 'zurx', 'zur', 'zyt', 'zyx', 'zy', 'zyp', 'zyrx', 'zyr', 'cit', 'cix', 'ci', 'cip', 'ciet', 'ciex', 'cie', 'ciep', 'cat', 'cax', 'ca', 'cap', 'cuox', 'cuo', 'cuop', 'cot', 'cox', 'co', 'cop', 'cex', 'ce', 'cep', 'cut', 'cux', 'cu', 'cup', 'curx', 'cur', 'cyt', 'cyx', 'cy', 'cyp', 'cyrx', 'cyr', 'zzit', 'zzix', 'zzi', 'zzip', 'zziet', 'zziex', 'zzie', 'zziep', 'zzat', 'zzax', 'zza', 'zzap', 'zzox', 'zzo', 'zzop', 'zzex', 'zze', 'zzep', 'zzux', 'zzu', 'zzup', 'zzurx', 'zzur', 'zzyt', 'zzyx', 'zzy', 'zzyp', 'zzyrx', 'zzyr', 'nzit', 'nzix', 'nzi', 'nzip', 'nziex', 'nzie', 'nziep', 'nzat', 'nzax', 'nza', 'nzap', 'nzuox', 'nzuo', 'nzox', 'nzop', 'nzex', 'nze', 'nzux', 'nzu'];
<?php return ['tyal', 'tyalg', 'tyalm', 'tyalb', 'tyals', 'tyalt', 'tyalp', 'tyalh', 'tyam', 'tyab', 'tyabs', 'tyas', 'tyass', 'tyang', 'tyaj', 'tyac', 'tyak', 'tyat', 'tyap', 'tyah', 'tyae', 'tyaeg', 'tyaegg', 'tyaegs', 'tyaen', 'tyaenj', 'tyaenh', 'tyaed', 'tyael', 'tyaelg', 'tyaelm', 'tyaelb', 'tyaels', 'tyaelt', 'tyaelp', 'tyaelh', 'tyaem', 'tyaeb', 'tyaebs', 'tyaes', 'tyaess', 'tyaeng', 'tyaej', 'tyaec', 'tyaek', 'tyaet', 'tyaep', 'tyaeh', 'teo', 'teog', 'teogg', 'teogs', 'teon', 'teonj', 'teonh', 'teod', 'teol', 'teolg', 'teolm', 'teolb', 'teols', 'teolt', 'teolp', 'teolh', 'teom', 'teob', 'teobs', 'teos', 'teoss', 'teong', 'teoj', 'teoc', 'teok', 'teot', 'teop', 'teoh', 'te', 'teg', 'tegg', 'tegs', 'ten', 'tenj', 'tenh', 'ted', 'tel', 'telg', 'telm', 'telb', 'tels', 'telt', 'telp', 'telh', 'tem', 'teb', 'tebs', 'tes', 'tess', 'teng', 'tej', 'tec', 'tek', 'tet', 'tep', 'teh', 'tyeo', 'tyeog', 'tyeogg', 'tyeogs', 'tyeon', 'tyeonj', 'tyeonh', 'tyeod', 'tyeol', 'tyeolg', 'tyeolm', 'tyeolb', 'tyeols', 'tyeolt', 'tyeolp', 'tyeolh', 'tyeom', 'tyeob', 'tyeobs', 'tyeos', 'tyeoss', 'tyeong', 'tyeoj', 'tyeoc', 'tyeok', 'tyeot', 'tyeop', 'tyeoh', 'tye', 'tyeg', 'tyegg', 'tyegs', 'tyen', 'tyenj', 'tyenh', 'tyed', 'tyel', 'tyelg', 'tyelm', 'tyelb', 'tyels', 'tyelt', 'tyelp', 'tyelh', 'tyem', 'tyeb', 'tyebs', 'tyes', 'tyess', 'tyeng', 'tyej', 'tyec', 'tyek', 'tyet', 'tyep', 'tyeh', 'to', 'tog', 'togg', 'togs', 'ton', 'tonj', 'tonh', 'tod', 'tol', 'tolg', 'tolm', 'tolb', 'tols', 'tolt', 'tolp', 'tolh', 'tom', 'tob', 'tobs', 'tos', 'toss', 'tong', 'toj', 'toc', 'tok', 'tot', 'top', 'toh', 'twa', 'twag', 'twagg', 'twags', 'twan', 'twanj', 'twanh', 'twad', 'twal', 'twalg', 'twalm', 'twalb', 'twals', 'twalt', 'twalp', 'twalh', 'twam', 'twab', 'twabs', 'twas', 'twass', 'twang', 'twaj', 'twac', 'twak', 'twat', 'twap', 'twah', 'twae', 'twaeg', 'twaegg', 'twaegs', 'twaen', 'twaenj', 'twaenh', 'twaed', 'twael', 'twaelg', 'twaelm', 'twaelb', 'twaels', 'twaelt', 'twaelp', 'twaelh', 'twaem', 'twaeb', 'twaebs', 'twaes', 'twaess', 'twaeng', 'twaej', 'twaec', 'twaek', 'twaet', 'twaep', 'twaeh', 'toe', 'toeg', 'toegg', 'toegs', 'toen', 'toenj', 'toenh', 'toed', 'toel', 'toelg', 'toelm', 'toelb'];
<?php return ['sseum', 'sseub', 'sseubs', 'sseus', 'sseuss', 'sseung', 'sseuj', 'sseuc', 'sseuk', 'sseut', 'sseup', 'sseuh', 'ssyi', 'ssyig', 'ssyigg', 'ssyigs', 'ssyin', 'ssyinj', 'ssyinh', 'ssyid', 'ssyil', 'ssyilg', 'ssyilm', 'ssyilb', 'ssyils', 'ssyilt', 'ssyilp', 'ssyilh', 'ssyim', 'ssyib', 'ssyibs', 'ssyis', 'ssyiss', 'ssying', 'ssyij', 'ssyic', 'ssyik', 'ssyit', 'ssyip', 'ssyih', 'ssi', 'ssig', 'ssigg', 'ssigs', 'ssin', 'ssinj', 'ssinh', 'ssid', 'ssil', 'ssilg', 'ssilm', 'ssilb', 'ssils', 'ssilt', 'ssilp', 'ssilh', 'ssim', 'ssib', 'ssibs', 'ssis', 'ssiss', 'ssing', 'ssij', 'ssic', 'ssik', 'ssit', 'ssip', 'ssih', 'a', 'ag', 'agg', 'ags', 'an', 'anj', 'anh', 'ad', 'al', 'alg', 'alm', 'alb', 'als', 'alt', 'alp', 'alh', 'am', 'ab', 'abs', 'as', 'ass', 'ang', 'aj', 'ac', 'ak', 'at', 'ap', 'ah', 'ae', 'aeg', 'aegg', 'aegs', 'aen', 'aenj', 'aenh', 'aed', 'ael', 'aelg', 'aelm', 'aelb', 'aels', 'aelt', 'aelp', 'aelh', 'aem', 'aeb', 'aebs', 'aes', 'aess', 'aeng', 'aej', 'aec', 'aek', 'aet', 'aep', 'aeh', 'ya', 'yag', 'yagg', 'yags', 'yan', 'yanj', 'yanh', 'yad', 'yal', 'yalg', 'yalm', 'yalb', 'yals', 'yalt', 'yalp', 'yalh', 'yam', 'yab', 'yabs', 'yas', 'yass', 'yang', 'yaj', 'yac', 'yak', 'yat', 'yap', 'yah', 'yae', 'yaeg', 'yaegg', 'yaegs', 'yaen', 'yaenj', 'yaenh', 'yaed', 'yael', 'yaelg', 'yaelm', 'yaelb', 'yaels', 'yaelt', 'yaelp', 'yaelh', 'yaem', 'yaeb', 'yaebs', 'yaes', 'yaess', 'yaeng', 'yaej', 'yaec', 'yaek', 'yaet', 'yaep', 'yaeh', 'eo', 'eog', 'eogg', 'eogs', 'eon', 'eonj', 'eonh', 'eod', 'eol', 'eolg', 'eolm', 'eolb', 'eols', 'eolt', 'eolp', 'eolh', 'eom', 'eob', 'eobs', 'eos', 'eoss', 'eong', 'eoj', 'eoc', 'eok', 'eot', 'eop', 'eoh', 'e', 'eg', 'egg', 'egs', 'en', 'enj', 'enh', 'ed', 'el', 'elg', 'elm', 'elb', 'els', 'elt', 'elp', 'elh', 'em', 'eb', 'ebs', 'es', 'ess', 'eng', 'ej', 'ec', 'ek', 'et', 'ep', 'eh', 'yeo', 'yeog', 'yeogg', 'yeogs', 'yeon', 'yeonj', 'yeonh', 'yeod', 'yeol', 'yeolg', 'yeolm', 'yeolb', 'yeols', 'yeolt', 'yeolp', 'yeolh', 'yeom', 'yeob', 'yeobs', 'yeos'];
<?php return ['reoss', 'reong', 'reoj', 'reoc', 'reok', 'reot', 'reop', 'reoh', 're', 'reg', 'regg', 'regs', 'ren', 'renj', 'renh', 'red', 'rel', 'relg', 'relm', 'relb', 'rels', 'relt', 'relp', 'relh', 'rem', 'reb', 'rebs', 'res', 'ress', 'reng', 'rej', 'rec', 'rek', 'ret', 'rep', 'reh', 'ryeo', 'ryeog', 'ryeogg', 'ryeogs', 'ryeon', 'ryeonj', 'ryeonh', 'ryeod', 'ryeol', 'ryeolg', 'ryeolm', 'ryeolb', 'ryeols', 'ryeolt', 'ryeolp', 'ryeolh', 'ryeom', 'ryeob', 'ryeobs', 'ryeos', 'ryeoss', 'ryeong', 'ryeoj', 'ryeoc', 'ryeok', 'ryeot', 'ryeop', 'ryeoh', 'rye', 'ryeg', 'ryegg', 'ryegs', 'ryen', 'ryenj', 'ryenh', 'ryed', 'ryel', 'ryelg', 'ryelm', 'ryelb', 'ryels', 'ryelt', 'ryelp', 'ryelh', 'ryem', 'ryeb', 'ryebs', 'ryes', 'ryess', 'ryeng', 'ryej', 'ryec', 'ryek', 'ryet', 'ryep', 'ryeh', 'ro', 'rog', 'rogg', 'rogs', 'ron', 'ronj', 'ronh', 'rod', 'rol', 'rolg', 'rolm', 'rolb', 'rols', 'rolt', 'rolp', 'rolh', 'rom', 'rob', 'robs', 'ros', 'ross', 'rong', 'roj', 'roc', 'rok', 'rot', 'rop', 'roh', 'rwa', 'rwag', 'rwagg', 'rwags', 'rwan', 'rwanj', 'rwanh', 'rwad', 'rwal', 'rwalg', 'rwalm', 'rwalb', 'rwals', 'rwalt', 'rwalp', 'rwalh', 'rwam', 'rwab', 'rwabs', 'rwas', 'rwass', 'rwang', 'rwaj', 'rwac', 'rwak', 'rwat', 'rwap', 'rwah', 'rwae', 'rwaeg', 'rwaegg', 'rwaegs', 'rwaen', 'rwaenj', 'rwaenh', 'rwaed', 'rwael', 'rwaelg', 'rwaelm', 'rwaelb', 'rwaels', 'rwaelt', 'rwaelp', 'rwaelh', 'rwaem', 'rwaeb', 'rwaebs', 'rwaes', 'rwaess', 'rwaeng', 'rwaej', 'rwaec', 'rwaek', 'rwaet', 'rwaep', 'rwaeh', 'roe', 'roeg', 'roegg', 'roegs', 'roen', 'roenj', 'roenh', 'roed', 'roel', 'roelg', 'roelm', 'roelb', 'roels', 'roelt', 'roelp', 'roelh', 'roem', 'roeb', 'roebs', 'roes', 'roess', 'roeng', 'roej', 'roec', 'roek', 'roet', 'roep', 'roeh', 'ryo', 'ryog', 'ryogg', 'ryogs', 'ryon', 'ryonj', 'ryonh', 'ryod', 'ryol', 'ryolg', 'ryolm', 'ryolb', 'ryols', 'ryolt', 'ryolp', 'ryolh', 'ryom', 'ryob', 'ryobs', 'ryos', 'ryoss', 'ryong', 'ryoj', 'ryoc', 'ryok', 'ryot', 'ryop', 'ryoh', 'ru', 'rug', 'rugg', 'rugs', 'run', 'runj', 'runh', 'rud', 'rul', 'rulg', 'rulm', 'rulb', 'ruls', 'rult', 'rulp', 'rulh', 'rum', 'rub', 'rubs', 'rus', 'russ', 'rung', 'ruj', 'ruc'];
<?php return ['[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', '[?]', 'e', 'ai', '[?]', '[?]', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', '[?]', 'l', 'll', '[?]', '', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '\'', 'aa', 'i', 'ii', 'u', 'uu', 'R', '[?]', '[?]', '[?]', 'e', 'ai', '[?]', '[?]', 'o', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '+', '[?]', '[?]', '[?]', '[?]', 'rr', 'rh', '[?]', 'yy', 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', '[?]', '[?]', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', 'k', '[?]', '[?]', '[?]', 'ng', 'c', '[?]', 'j', '[?]', 'ny', 'tt', '[?]', '[?]', '[?]', 'nn', 't', '[?]', '[?]', '[?]', 'n', 'nnn', 'p', '[?]', '[?]', '[?]', 'm', 'y', 'r', 'rr', 'l', 'll', 'lll', 'v', '[?]', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', 'ii', 'u', 'uu', '[?]', '[?]', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+10+', '+100+', '+1000+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Mou ', 'Ye ', 'Wei ', '[?] ', 'Teng ', 'Zou ', 'Shan ', 'Jian ', 'Bo ', 'Ku ', 'Huang ', 'Huo ', 'Ge ', 'Ying ', 'Mi ', 'Xiao ', 'Mi ', 'Xi ', 'Qiang ', 'Chen ', 'Nue ', 'Ti ', 'Su ', 'Bang ', 'Chi ', 'Qian ', 'Shi ', 'Jiang ', 'Yuan ', 'Xie ', 'Xue ', 'Tao ', 'Yao ', 'Yao ', '[?] ', 'Yu ', 'Biao ', 'Cong ', 'Qing ', 'Li ', 'Mo ', 'Mo ', 'Shang ', 'Zhe ', 'Miu ', 'Jian ', 'Ze ', 'Jie ', 'Lian ', 'Lou ', 'Can ', 'Ou ', 'Guan ', 'Xi ', 'Zhuo ', 'Ao ', 'Ao ', 'Jin ', 'Zhe ', 'Yi ', 'Hu ', 'Jiang ', 'Man ', 'Chao ', 'Han ', 'Hua ', 'Chan ', 'Xu ', 'Zeng ', 'Se ', 'Xi ', 'She ', 'Dui ', 'Zheng ', 'Nao ', 'Lan ', 'E ', 'Ying ', 'Jue ', 'Ji ', 'Zun ', 'Jiao ', 'Bo ', 'Hui ', 'Zhuan ', 'Mu ', 'Zen ', 'Zha ', 'Shi ', 'Qiao ', 'Tan ', 'Zen ', 'Pu ', 'Sheng ', 'Xuan ', 'Zao ', 'Tan ', 'Dang ', 'Sui ', 'Qian ', 'Ji ', 'Jiao ', 'Jing ', 'Lian ', 'Nou ', 'Yi ', 'Ai ', 'Zhan ', 'Pi ', 'Hui ', 'Hua ', 'Yi ', 'Yi ', 'Shan ', 'Rang ', 'Nou ', 'Qian ', 'Zhui ', 'Ta ', 'Hu ', 'Zhou ', 'Hao ', 'Ye ', 'Ying ', 'Jian ', 'Yu ', 'Jian ', 'Hui ', 'Du ', 'Zhe ', 'Xuan ', 'Zan ', 'Lei ', 'Shen ', 'Wei ', 'Chan ', 'Li ', 'Yi ', 'Bian ', 'Zhe ', 'Yan ', 'E ', 'Chou ', 'Wei ', 'Chou ', 'Yao ', 'Chan ', 'Rang ', 'Yin ', 'Lan ', 'Chen ', 'Huo ', 'Zhe ', 'Huan ', 'Zan ', 'Yi ', 'Dang ', 'Zhan ', 'Yan ', 'Du ', 'Yan ', 'Ji ', 'Ding ', 'Fu ', 'Ren ', 'Ji ', 'Jie ', 'Hong ', 'Tao ', 'Rang ', 'Shan ', 'Qi ', 'Tuo ', 'Xun ', 'Yi ', 'Xun ', 'Ji ', 'Ren ', 'Jiang ', 'Hui ', 'Ou ', 'Ju ', 'Ya ', 'Ne ', 'Xu ', 'E ', 'Lun ', 'Xiong ', 'Song ', 'Feng ', 'She ', 'Fang ', 'Jue ', 'Zheng ', 'Gu ', 'He ', 'Ping ', 'Zu ', 'Shi ', 'Xiong ', 'Zha ', 'Su ', 'Zhen ', 'Di ', 'Zou ', 'Ci ', 'Qu ', 'Zhao ', 'Bi ', 'Yi ', 'Yi ', 'Kuang ', 'Lei ', 'Shi ', 'Gua ', 'Shi ', 'Jie ', 'Hui ', 'Cheng ', 'Zhu ', 'Shen ', 'Hua ', 'Dan ', 'Gou ', 'Quan ', 'Gui ', 'Xun ', 'Yi ', 'Zheng ', 'Gai ', 'Xiang ', 'Cha ', 'Hun ', 'Xu ', 'Zhou ', 'Jie ', 'Wu ', 'Yu ', 'Qiao ', 'Wu ', 'Gao ', 'You ', 'Hui ', 'Kuang ', 'Shuo ', 'Song ', 'Ai ', 'Qing ', 'Zhu ', 'Zou ', 'Nuo ', 'Du ', 'Zhuo ', 'Fei ', 'Ke ', 'Wei '];
<?php return ['dyil', 'dyilg', 'dyilm', 'dyilb', 'dyils', 'dyilt', 'dyilp', 'dyilh', 'dyim', 'dyib', 'dyibs', 'dyis', 'dyiss', 'dying', 'dyij', 'dyic', 'dyik', 'dyit', 'dyip', 'dyih', 'di', 'dig', 'digg', 'digs', 'din', 'dinj', 'dinh', 'did', 'dil', 'dilg', 'dilm', 'dilb', 'dils', 'dilt', 'dilp', 'dilh', 'dim', 'dib', 'dibs', 'dis', 'diss', 'ding', 'dij', 'dic', 'dik', 'dit', 'dip', 'dih', 'dda', 'ddag', 'ddagg', 'ddags', 'ddan', 'ddanj', 'ddanh', 'ddad', 'ddal', 'ddalg', 'ddalm', 'ddalb', 'ddals', 'ddalt', 'ddalp', 'ddalh', 'ddam', 'ddab', 'ddabs', 'ddas', 'ddass', 'ddang', 'ddaj', 'ddac', 'ddak', 'ddat', 'ddap', 'ddah', 'ddae', 'ddaeg', 'ddaegg', 'ddaegs', 'ddaen', 'ddaenj', 'ddaenh', 'ddaed', 'ddael', 'ddaelg', 'ddaelm', 'ddaelb', 'ddaels', 'ddaelt', 'ddaelp', 'ddaelh', 'ddaem', 'ddaeb', 'ddaebs', 'ddaes', 'ddaess', 'ddaeng', 'ddaej', 'ddaec', 'ddaek', 'ddaet', 'ddaep', 'ddaeh', 'ddya', 'ddyag', 'ddyagg', 'ddyags', 'ddyan', 'ddyanj', 'ddyanh', 'ddyad', 'ddyal', 'ddyalg', 'ddyalm', 'ddyalb', 'ddyals', 'ddyalt', 'ddyalp', 'ddyalh', 'ddyam', 'ddyab', 'ddyabs', 'ddyas', 'ddyass', 'ddyang', 'ddyaj', 'ddyac', 'ddyak', 'ddyat', 'ddyap', 'ddyah', 'ddyae', 'ddyaeg', 'ddyaegg', 'ddyaegs', 'ddyaen', 'ddyaenj', 'ddyaenh', 'ddyaed', 'ddyael', 'ddyaelg', 'ddyaelm', 'ddyaelb', 'ddyaels', 'ddyaelt', 'ddyaelp', 'ddyaelh', 'ddyaem', 'ddyaeb', 'ddyaebs', 'ddyaes', 'ddyaess', 'ddyaeng', 'ddyaej', 'ddyaec', 'ddyaek', 'ddyaet', 'ddyaep', 'ddyaeh', 'ddeo', 'ddeog', 'ddeogg', 'ddeogs', 'ddeon', 'ddeonj', 'ddeonh', 'ddeod', 'ddeol', 'ddeolg', 'ddeolm', 'ddeolb', 'ddeols', 'ddeolt', 'ddeolp', 'ddeolh', 'ddeom', 'ddeob', 'ddeobs', 'ddeos', 'ddeoss', 'ddeong', 'ddeoj', 'ddeoc', 'ddeok', 'ddeot', 'ddeop', 'ddeoh', 'dde', 'ddeg', 'ddegg', 'ddegs', 'dden', 'ddenj', 'ddenh', 'dded', 'ddel', 'ddelg', 'ddelm', 'ddelb', 'ddels', 'ddelt', 'ddelp', 'ddelh', 'ddem', 'ddeb', 'ddebs', 'ddes', 'ddess', 'ddeng', 'ddej', 'ddec', 'ddek', 'ddet', 'ddep', 'ddeh', 'ddyeo', 'ddyeog', 'ddyeogg', 'ddyeogs', 'ddyeon', 'ddyeonj', 'ddyeonh', 'ddyeod', 'ddyeol', 'ddyeolg', 'ddyeolm', 'ddyeolb', 'ddyeols', 'ddyeolt', 'ddyeolp', 'ddyeolh', 'ddyeom', 'ddyeob', 'ddyeobs', 'ddyeos', 'ddyeoss', 'ddyeong', 'ddyeoj', 'ddyeoc', 'ddyeok', 'ddyeot', 'ddyeop', 'ddyeoh', 'ddye', 'ddyeg', 'ddyegg', 'ddyegs', 'ddyen', 'ddyenj', 'ddyenh', 'ddyed', 'ddyel', 'ddyelg', 'ddyelm', 'ddyelb'];
<?php return ['Yi ', 'Ding ', 'Kao ', 'Qi ', 'Shang ', 'Xia ', '[?] ', 'Mo ', 'Zhang ', 'San ', 'Shang ', 'Xia ', 'Ji ', 'Bu ', 'Yu ', 'Mian ', 'Gai ', 'Chou ', 'Chou ', 'Zhuan ', 'Qie ', 'Pi ', 'Shi ', 'Shi ', 'Qiu ', 'Bing ', 'Ye ', 'Cong ', 'Dong ', 'Si ', 'Cheng ', 'Diu ', 'Qiu ', 'Liang ', 'Diu ', 'You ', 'Liang ', 'Yan ', 'Bing ', 'Sang ', 'Gun ', 'Jiu ', 'Ge ', 'Ya ', 'Qiang ', 'Zhong ', 'Ji ', 'Jie ', 'Feng ', 'Guan ', 'Chuan ', 'Chan ', 'Lin ', 'Zhuo ', 'Zhu ', 'Ha ', 'Wan ', 'Dan ', 'Wei ', 'Zhu ', 'Jing ', 'Li ', 'Ju ', 'Pie ', 'Fu ', 'Yi ', 'Yi ', 'Nai ', 'Shime ', 'Jiu ', 'Jiu ', 'Zhe ', 'Yao ', 'Yi ', '[?] ', 'Zhi ', 'Wu ', 'Zha ', 'Hu ', 'Fa ', 'Le ', 'Zhong ', 'Ping ', 'Pang ', 'Qiao ', 'Hu ', 'Guai ', 'Cheng ', 'Cheng ', 'Yi ', 'Yin ', '[?] ', 'Mie ', 'Jiu ', 'Qi ', 'Ye ', 'Xi ', 'Xiang ', 'Gai ', 'Diu ', 'Hal ', '[?] ', 'Shu ', 'Twul ', 'Shi ', 'Ji ', 'Nang ', 'Jia ', 'Kel ', 'Shi ', '[?] ', 'Ol ', 'Mai ', 'Luan ', 'Cal ', 'Ru ', 'Xue ', 'Yan ', 'Fu ', 'Sha ', 'Na ', 'Gan ', 'Sol ', 'El ', 'Cwul ', '[?] ', 'Gan ', 'Chi ', 'Gui ', 'Gan ', 'Luan ', 'Lin ', 'Yi ', 'Jue ', 'Liao ', 'Ma ', 'Yu ', 'Zheng ', 'Shi ', 'Shi ', 'Er ', 'Chu ', 'Yu ', 'Yu ', 'Yu ', 'Yun ', 'Hu ', 'Qi ', 'Wu ', 'Jing ', 'Si ', 'Sui ', 'Gen ', 'Gen ', 'Ya ', 'Xie ', 'Ya ', 'Qi ', 'Ya ', 'Ji ', 'Tou ', 'Wang ', 'Kang ', 'Ta ', 'Jiao ', 'Hai ', 'Yi ', 'Chan ', 'Heng ', 'Mu ', '[?] ', 'Xiang ', 'Jing ', 'Ting ', 'Liang ', 'Xiang ', 'Jing ', 'Ye ', 'Qin ', 'Bo ', 'You ', 'Xie ', 'Dan ', 'Lian ', 'Duo ', 'Wei ', 'Ren ', 'Ren ', 'Ji ', 'La ', 'Wang ', 'Yi ', 'Shi ', 'Ren ', 'Le ', 'Ding ', 'Ze ', 'Jin ', 'Pu ', 'Chou ', 'Ba ', 'Zhang ', 'Jin ', 'Jie ', 'Bing ', 'Reng ', 'Cong ', 'Fo ', 'San ', 'Lun ', 'Sya ', 'Cang ', 'Zi ', 'Shi ', 'Ta ', 'Zhang ', 'Fu ', 'Xian ', 'Xian ', 'Tuo ', 'Hong ', 'Tong ', 'Ren ', 'Qian ', 'Gan ', 'Yi ', 'Di ', 'Dai ', 'Ling ', 'Yi ', 'Chao ', 'Chang ', 'Sa ', '[?] ', 'Yi ', 'Mu ', 'Men ', 'Ren ', 'Jia ', 'Chao ', 'Yang ', 'Qian ', 'Zhong ', 'Pi ', 'Wan ', 'Wu ', 'Jian ', 'Jie ', 'Yao ', 'Feng ', 'Cang ', 'Ren ', 'Wang ', 'Fen ', 'Di ', 'Fang '];
<?php return ['Dao ', 'Diao ', 'Dao ', 'Ren ', 'Ren ', 'Chuang ', 'Fen ', 'Qie ', 'Yi ', 'Ji ', 'Kan ', 'Qian ', 'Cun ', 'Chu ', 'Wen ', 'Ji ', 'Dan ', 'Xing ', 'Hua ', 'Wan ', 'Jue ', 'Li ', 'Yue ', 'Lie ', 'Liu ', 'Ze ', 'Gang ', 'Chuang ', 'Fu ', 'Chu ', 'Qu ', 'Ju ', 'Shan ', 'Min ', 'Ling ', 'Zhong ', 'Pan ', 'Bie ', 'Jie ', 'Jie ', 'Bao ', 'Li ', 'Shan ', 'Bie ', 'Chan ', 'Jing ', 'Gua ', 'Gen ', 'Dao ', 'Chuang ', 'Kui ', 'Ku ', 'Duo ', 'Er ', 'Zhi ', 'Shua ', 'Quan ', 'Cha ', 'Ci ', 'Ke ', 'Jie ', 'Gui ', 'Ci ', 'Gui ', 'Kai ', 'Duo ', 'Ji ', 'Ti ', 'Jing ', 'Lou ', 'Gen ', 'Ze ', 'Yuan ', 'Cuo ', 'Xue ', 'Ke ', 'La ', 'Qian ', 'Cha ', 'Chuang ', 'Gua ', 'Jian ', 'Cuo ', 'Li ', 'Ti ', 'Fei ', 'Pou ', 'Chan ', 'Qi ', 'Chuang ', 'Zi ', 'Gang ', 'Wan ', 'Bo ', 'Ji ', 'Duo ', 'Qing ', 'Yan ', 'Zhuo ', 'Jian ', 'Ji ', 'Bo ', 'Yan ', 'Ju ', 'Huo ', 'Sheng ', 'Jian ', 'Duo ', 'Duan ', 'Wu ', 'Gua ', 'Fu ', 'Sheng ', 'Jian ', 'Ge ', 'Zha ', 'Kai ', 'Chuang ', 'Juan ', 'Chan ', 'Tuan ', 'Lu ', 'Li ', 'Fou ', 'Shan ', 'Piao ', 'Kou ', 'Jiao ', 'Gua ', 'Qiao ', 'Jue ', 'Hua ', 'Zha ', 'Zhuo ', 'Lian ', 'Ju ', 'Pi ', 'Liu ', 'Gui ', 'Jiao ', 'Gui ', 'Jian ', 'Jian ', 'Tang ', 'Huo ', 'Ji ', 'Jian ', 'Yi ', 'Jian ', 'Zhi ', 'Chan ', 'Cuan ', 'Mo ', 'Li ', 'Zhu ', 'Li ', 'Ya ', 'Quan ', 'Ban ', 'Gong ', 'Jia ', 'Wu ', 'Mai ', 'Lie ', 'Jin ', 'Keng ', 'Xie ', 'Zhi ', 'Dong ', 'Zhu ', 'Nu ', 'Jie ', 'Qu ', 'Shao ', 'Yi ', 'Zhu ', 'Miao ', 'Li ', 'Jing ', 'Lao ', 'Lao ', 'Juan ', 'Kou ', 'Yang ', 'Wa ', 'Xiao ', 'Mou ', 'Kuang ', 'Jie ', 'Lie ', 'He ', 'Shi ', 'Ke ', 'Jing ', 'Hao ', 'Bo ', 'Min ', 'Chi ', 'Lang ', 'Yong ', 'Yong ', 'Mian ', 'Ke ', 'Xun ', 'Juan ', 'Qing ', 'Lu ', 'Pou ', 'Meng ', 'Lai ', 'Le ', 'Kai ', 'Mian ', 'Dong ', 'Xu ', 'Xu ', 'Kan ', 'Wu ', 'Yi ', 'Xun ', 'Weng ', 'Sheng ', 'Lao ', 'Mu ', 'Lu ', 'Piao ', 'Shi ', 'Ji ', 'Qin ', 'Qiang ', 'Jiao ', 'Quan ', 'Yang ', 'Yi ', 'Jue ', 'Fan ', 'Juan ', 'Tong ', 'Ju ', 'Dan ', 'Xie ', 'Mai ', 'Xun ', 'Xun ', 'Lu ', 'Li ', 'Che ', 'Rang ', 'Quan ', 'Bao ', 'Shao ', 'Yun ', 'Jiu ', 'Bao ', 'Gou ', 'Wu '];
<?php return ['Pan ', 'Yang ', 'Lei ', 'Sa ', 'Shu ', 'Zan ', 'Nian ', 'Xian ', 'Jun ', 'Huo ', 'Li ', 'La ', 'Han ', 'Ying ', 'Lu ', 'Long ', 'Qian ', 'Qian ', 'Zan ', 'Qian ', 'Lan ', 'San ', 'Ying ', 'Mei ', 'Rang ', 'Chan ', '[?] ', 'Cuan ', 'Xi ', 'She ', 'Luo ', 'Jun ', 'Mi ', 'Li ', 'Zan ', 'Luan ', 'Tan ', 'Zuan ', 'Li ', 'Dian ', 'Wa ', 'Dang ', 'Jiao ', 'Jue ', 'Lan ', 'Li ', 'Nang ', 'Zhi ', 'Gui ', 'Gui ', 'Qi ', 'Xin ', 'Pu ', 'Sui ', 'Shou ', 'Kao ', 'You ', 'Gai ', 'Yi ', 'Gong ', 'Gan ', 'Ban ', 'Fang ', 'Zheng ', 'Bo ', 'Dian ', 'Kou ', 'Min ', 'Wu ', 'Gu ', 'He ', 'Ce ', 'Xiao ', 'Mi ', 'Chu ', 'Ge ', 'Di ', 'Xu ', 'Jiao ', 'Min ', 'Chen ', 'Jiu ', 'Zhen ', 'Duo ', 'Yu ', 'Chi ', 'Ao ', 'Bai ', 'Xu ', 'Jiao ', 'Duo ', 'Lian ', 'Nie ', 'Bi ', 'Chang ', 'Dian ', 'Duo ', 'Yi ', 'Gan ', 'San ', 'Ke ', 'Yan ', 'Dun ', 'Qi ', 'Dou ', 'Xiao ', 'Duo ', 'Jiao ', 'Jing ', 'Yang ', 'Xia ', 'Min ', 'Shu ', 'Ai ', 'Qiao ', 'Ai ', 'Zheng ', 'Di ', 'Zhen ', 'Fu ', 'Shu ', 'Liao ', 'Qu ', 'Xiong ', 'Xi ', 'Jiao ', 'Sen ', 'Jiao ', 'Zhuo ', 'Yi ', 'Lian ', 'Bi ', 'Li ', 'Xiao ', 'Xiao ', 'Wen ', 'Xue ', 'Qi ', 'Qi ', 'Zhai ', 'Bin ', 'Jue ', 'Zhai ', '[?] ', 'Fei ', 'Ban ', 'Ban ', 'Lan ', 'Yu ', 'Lan ', 'Wei ', 'Dou ', 'Sheng ', 'Liao ', 'Jia ', 'Hu ', 'Xie ', 'Jia ', 'Yu ', 'Zhen ', 'Jiao ', 'Wo ', 'Tou ', 'Chu ', 'Jin ', 'Chi ', 'Yin ', 'Fu ', 'Qiang ', 'Zhan ', 'Qu ', 'Zhuo ', 'Zhan ', 'Duan ', 'Zhuo ', 'Si ', 'Xin ', 'Zhuo ', 'Zhuo ', 'Qin ', 'Lin ', 'Zhuo ', 'Chu ', 'Duan ', 'Zhu ', 'Fang ', 'Xie ', 'Hang ', 'Yu ', 'Shi ', 'Pei ', 'You ', 'Mye ', 'Pang ', 'Qi ', 'Zhan ', 'Mao ', 'Lu ', 'Pei ', 'Pi ', 'Liu ', 'Fu ', 'Fang ', 'Xuan ', 'Jing ', 'Jing ', 'Ni ', 'Zu ', 'Zhao ', 'Yi ', 'Liu ', 'Shao ', 'Jian ', 'Es ', 'Yi ', 'Qi ', 'Zhi ', 'Fan ', 'Piao ', 'Fan ', 'Zhan ', 'Guai ', 'Sui ', 'Yu ', 'Wu ', 'Ji ', 'Ji ', 'Ji ', 'Huo ', 'Ri ', 'Dan ', 'Jiu ', 'Zhi ', 'Zao ', 'Xie ', 'Tiao ', 'Xun ', 'Xu ', 'Xu ', 'Xu ', 'Gan ', 'Han ', 'Tai ', 'Di ', 'Xu ', 'Chan ', 'Shi ', 'Kuang ', 'Yang ', 'Shi ', 'Wang ', 'Min ', 'Min ', 'Tun ', 'Chun ', 'Wu '];
<?php return ['Po ', 'Feng ', 'Zhuan ', 'Fu ', 'She ', 'Ke ', 'Jiang ', 'Jiang ', 'Zhuan ', 'Wei ', 'Zun ', 'Xun ', 'Shu ', 'Dui ', 'Dao ', 'Xiao ', 'Ji ', 'Shao ', 'Er ', 'Er ', 'Er ', 'Ga ', 'Jian ', 'Shu ', 'Chen ', 'Shang ', 'Shang ', 'Mo ', 'Ga ', 'Chang ', 'Liao ', 'Xian ', 'Xian ', '[?] ', 'Wang ', 'Wang ', 'You ', 'Liao ', 'Liao ', 'Yao ', 'Mang ', 'Wang ', 'Wang ', 'Wang ', 'Ga ', 'Yao ', 'Duo ', 'Kui ', 'Zhong ', 'Jiu ', 'Gan ', 'Gu ', 'Gan ', 'Tui ', 'Gan ', 'Gan ', 'Shi ', 'Yin ', 'Chi ', 'Kao ', 'Ni ', 'Jin ', 'Wei ', 'Niao ', 'Ju ', 'Pi ', 'Ceng ', 'Xi ', 'Bi ', 'Ju ', 'Jie ', 'Tian ', 'Qu ', 'Ti ', 'Jie ', 'Wu ', 'Diao ', 'Shi ', 'Shi ', 'Ping ', 'Ji ', 'Xie ', 'Chen ', 'Xi ', 'Ni ', 'Zhan ', 'Xi ', '[?] ', 'Man ', 'E ', 'Lou ', 'Ping ', 'Ti ', 'Fei ', 'Shu ', 'Xie ', 'Tu ', 'Lu ', 'Lu ', 'Xi ', 'Ceng ', 'Lu ', 'Ju ', 'Xie ', 'Ju ', 'Jue ', 'Liao ', 'Jue ', 'Shu ', 'Xi ', 'Che ', 'Tun ', 'Ni ', 'Shan ', '[?] ', 'Xian ', 'Li ', 'Xue ', 'Nata ', '[?] ', 'Long ', 'Yi ', 'Qi ', 'Ren ', 'Wu ', 'Han ', 'Shen ', 'Yu ', 'Chu ', 'Sui ', 'Qi ', '[?] ', 'Yue ', 'Ban ', 'Yao ', 'Ang ', 'Ya ', 'Wu ', 'Jie ', 'E ', 'Ji ', 'Qian ', 'Fen ', 'Yuan ', 'Qi ', 'Cen ', 'Qian ', 'Qi ', 'Cha ', 'Jie ', 'Qu ', 'Gang ', 'Xian ', 'Ao ', 'Lan ', 'Dao ', 'Ba ', 'Zuo ', 'Zuo ', 'Yang ', 'Ju ', 'Gang ', 'Ke ', 'Gou ', 'Xue ', 'Bei ', 'Li ', 'Tiao ', 'Ju ', 'Yan ', 'Fu ', 'Xiu ', 'Jia ', 'Ling ', 'Tuo ', 'Pei ', 'You ', 'Dai ', 'Kuang ', 'Yue ', 'Qu ', 'Hu ', 'Po ', 'Min ', 'An ', 'Tiao ', 'Ling ', 'Chi ', 'Yuri ', 'Dong ', 'Cem ', 'Kui ', 'Xiu ', 'Mao ', 'Tong ', 'Xue ', 'Yi ', 'Kura ', 'He ', 'Ke ', 'Luo ', 'E ', 'Fu ', 'Xun ', 'Die ', 'Lu ', 'An ', 'Er ', 'Gai ', 'Quan ', 'Tong ', 'Yi ', 'Mu ', 'Shi ', 'An ', 'Wei ', 'Hu ', 'Zhi ', 'Mi ', 'Li ', 'Ji ', 'Tong ', 'Wei ', 'You ', 'Sang ', 'Xia ', 'Li ', 'Yao ', 'Jiao ', 'Zheng ', 'Luan ', 'Jiao ', 'E ', 'E ', 'Yu ', 'Ye ', 'Bu ', 'Qiao ', 'Qun ', 'Feng ', 'Feng ', 'Nao ', 'Li ', 'You ', 'Xian ', 'Hong ', 'Dao ', 'Shen ', 'Cheng ', 'Tu ', 'Geng ', 'Jun ', 'Hao ', 'Xia ', 'Yin ', 'Yu '];
<?php return ['Xiao ', 'Suo ', 'Li ', 'Zheng ', 'Chu ', 'Guo ', 'Gao ', 'Tie ', 'Xiu ', 'Cuo ', 'Lue ', 'Feng ', 'Xin ', 'Liu ', 'Kai ', 'Jian ', 'Rui ', 'Ti ', 'Lang ', 'Qian ', 'Ju ', 'A ', 'Qiang ', 'Duo ', 'Tian ', 'Cuo ', 'Mao ', 'Ben ', 'Qi ', 'De ', 'Kua ', 'Kun ', 'Chang ', 'Xi ', 'Gu ', 'Luo ', 'Chui ', 'Zhui ', 'Jin ', 'Zhi ', 'Xian ', 'Juan ', 'Huo ', 'Pou ', 'Tan ', 'Ding ', 'Jian ', 'Ju ', 'Meng ', 'Zi ', 'Qie ', 'Ying ', 'Kai ', 'Qiang ', 'Song ', 'E ', 'Cha ', 'Qiao ', 'Zhong ', 'Duan ', 'Sou ', 'Huang ', 'Huan ', 'Ai ', 'Du ', 'Mei ', 'Lou ', 'Zi ', 'Fei ', 'Mei ', 'Mo ', 'Zhen ', 'Bo ', 'Ge ', 'Nie ', 'Tang ', 'Juan ', 'Nie ', 'Na ', 'Liu ', 'Hao ', 'Bang ', 'Yi ', 'Jia ', 'Bin ', 'Rong ', 'Biao ', 'Tang ', 'Man ', 'Luo ', 'Beng ', 'Yong ', 'Jing ', 'Di ', 'Zu ', 'Xuan ', 'Liu ', 'Tan ', 'Jue ', 'Liao ', 'Pu ', 'Lu ', 'Dui ', 'Lan ', 'Pu ', 'Cuan ', 'Qiang ', 'Deng ', 'Huo ', 'Lei ', 'Huan ', 'Zhuo ', 'Lian ', 'Yi ', 'Cha ', 'Biao ', 'La ', 'Chan ', 'Xiang ', 'Chang ', 'Chang ', 'Jiu ', 'Ao ', 'Die ', 'Qu ', 'Liao ', 'Mi ', 'Chang ', 'Men ', 'Ma ', 'Shuan ', 'Shan ', 'Huo ', 'Men ', 'Yan ', 'Bi ', 'Han ', 'Bi ', 'San ', 'Kai ', 'Kang ', 'Beng ', 'Hong ', 'Run ', 'San ', 'Xian ', 'Xian ', 'Jian ', 'Min ', 'Xia ', 'Yuru ', 'Dou ', 'Zha ', 'Nao ', 'Jian ', 'Peng ', 'Xia ', 'Ling ', 'Bian ', 'Bi ', 'Run ', 'He ', 'Guan ', 'Ge ', 'Ge ', 'Fa ', 'Chu ', 'Hong ', 'Gui ', 'Min ', 'Se ', 'Kun ', 'Lang ', 'Lu ', 'Ting ', 'Sha ', 'Ju ', 'Yue ', 'Yue ', 'Chan ', 'Qu ', 'Lin ', 'Chang ', 'Shai ', 'Kun ', 'Yan ', 'Min ', 'Yan ', 'E ', 'Hun ', 'Yu ', 'Wen ', 'Xiang ', 'Bao ', 'Xiang ', 'Qu ', 'Yao ', 'Wen ', 'Ban ', 'An ', 'Wei ', 'Yin ', 'Kuo ', 'Que ', 'Lan ', 'Du ', '[?] ', 'Phwung ', 'Tian ', 'Nie ', 'Ta ', 'Kai ', 'He ', 'Que ', 'Chuang ', 'Guan ', 'Dou ', 'Qi ', 'Kui ', 'Tang ', 'Guan ', 'Piao ', 'Kan ', 'Xi ', 'Hui ', 'Chan ', 'Pi ', 'Dang ', 'Huan ', 'Ta ', 'Wen ', '[?] ', 'Men ', 'Shuan ', 'Shan ', 'Yan ', 'Han ', 'Bi ', 'Wen ', 'Chuang ', 'Run ', 'Wei ', 'Xian ', 'Hong ', 'Jian ', 'Min ', 'Kang ', 'Men ', 'Zha ', 'Nao ', 'Gui ', 'Wen ', 'Ta ', 'Min ', 'Lu ', 'Kai '];
<?php return ['Cheng ', 'Tiao ', 'Zhi ', 'Cui ', 'Mei ', 'Xie ', 'Cui ', 'Xie ', 'Mo ', 'Mai ', 'Ji ', 'Obiyaakasu ', '[?] ', 'Kuai ', 'Sa ', 'Zang ', 'Qi ', 'Nao ', 'Mi ', 'Nong ', 'Luan ', 'Wan ', 'Bo ', 'Wen ', 'Guan ', 'Qiu ', 'Jiao ', 'Jing ', 'Rou ', 'Heng ', 'Cuo ', 'Lie ', 'Shan ', 'Ting ', 'Mei ', 'Chun ', 'Shen ', 'Xie ', 'De ', 'Zui ', 'Cu ', 'Xiu ', 'Xin ', 'Tuo ', 'Pao ', 'Cheng ', 'Nei ', 'Fu ', 'Dou ', 'Tuo ', 'Niao ', 'Noy ', 'Pi ', 'Gu ', 'Gua ', 'Li ', 'Lian ', 'Zhang ', 'Cui ', 'Jie ', 'Liang ', 'Zhou ', 'Pi ', 'Biao ', 'Lun ', 'Pian ', 'Guo ', 'Kui ', 'Chui ', 'Dan ', 'Tian ', 'Nei ', 'Jing ', 'Jie ', 'La ', 'Yi ', 'An ', 'Ren ', 'Shen ', 'Chuo ', 'Fu ', 'Fu ', 'Ju ', 'Fei ', 'Qiang ', 'Wan ', 'Dong ', 'Pi ', 'Guo ', 'Zong ', 'Ding ', 'Wu ', 'Mei ', 'Ruan ', 'Zhuan ', 'Zhi ', 'Cou ', 'Gua ', 'Ou ', 'Di ', 'An ', 'Xing ', 'Nao ', 'Yu ', 'Chuan ', 'Nan ', 'Yun ', 'Zhong ', 'Rou ', 'E ', 'Sai ', 'Tu ', 'Yao ', 'Jian ', 'Wei ', 'Jiao ', 'Yu ', 'Jia ', 'Duan ', 'Bi ', 'Chang ', 'Fu ', 'Xian ', 'Ni ', 'Mian ', 'Wa ', 'Teng ', 'Tui ', 'Bang ', 'Qian ', 'Lu ', 'Wa ', 'Sou ', 'Tang ', 'Su ', 'Zhui ', 'Ge ', 'Yi ', 'Bo ', 'Liao ', 'Ji ', 'Pi ', 'Xie ', 'Gao ', 'Lu ', 'Bin ', 'Ou ', 'Chang ', 'Lu ', 'Guo ', 'Pang ', 'Chuai ', 'Piao ', 'Jiang ', 'Fu ', 'Tang ', 'Mo ', 'Xi ', 'Zhuan ', 'Lu ', 'Jiao ', 'Ying ', 'Lu ', 'Zhi ', 'Tara ', 'Chun ', 'Lian ', 'Tong ', 'Peng ', 'Ni ', 'Zha ', 'Liao ', 'Cui ', 'Gui ', 'Xiao ', 'Teng ', 'Fan ', 'Zhi ', 'Jiao ', 'Shan ', 'Wu ', 'Cui ', 'Run ', 'Xiang ', 'Sui ', 'Fen ', 'Ying ', 'Tan ', 'Zhua ', 'Dan ', 'Kuai ', 'Nong ', 'Tun ', 'Lian ', 'Bi ', 'Yong ', 'Jue ', 'Chu ', 'Yi ', 'Juan ', 'La ', 'Lian ', 'Sao ', 'Tun ', 'Gu ', 'Qi ', 'Cui ', 'Bin ', 'Xun ', 'Ru ', 'Huo ', 'Zang ', 'Xian ', 'Biao ', 'Xing ', 'Kuan ', 'La ', 'Yan ', 'Lu ', 'Huo ', 'Zang ', 'Luo ', 'Qu ', 'Zang ', 'Luan ', 'Ni ', 'Zang ', 'Chen ', 'Qian ', 'Wo ', 'Guang ', 'Zang ', 'Lin ', 'Guang ', 'Zi ', 'Jiao ', 'Nie ', 'Chou ', 'Ji ', 'Gao ', 'Chou ', 'Mian ', 'Nie ', 'Zhi ', 'Zhi ', 'Ge ', 'Jian ', 'Die ', 'Zhi ', 'Xiu ', 'Tai ', 'Zhen ', 'Jiu ', 'Xian ', 'Yu ', 'Cha '];
<?php return ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''];
<?php return ['Zhong ', 'Qi ', 'Pei ', 'Yu ', 'Diao ', 'Dun ', 'Wen ', 'Yi ', 'Xin ', 'Kang ', 'Yi ', 'Ji ', 'Ai ', 'Wu ', 'Ji ', 'Fu ', 'Fa ', 'Xiu ', 'Jin ', 'Bei ', 'Dan ', 'Fu ', 'Tang ', 'Zhong ', 'You ', 'Huo ', 'Hui ', 'Yu ', 'Cui ', 'Chuan ', 'San ', 'Wei ', 'Chuan ', 'Che ', 'Ya ', 'Xian ', 'Shang ', 'Chang ', 'Lun ', 'Cang ', 'Xun ', 'Xin ', 'Wei ', 'Zhu ', '[?] ', 'Xuan ', 'Nu ', 'Bo ', 'Gu ', 'Ni ', 'Ni ', 'Xie ', 'Ban ', 'Xu ', 'Ling ', 'Zhou ', 'Shen ', 'Qu ', 'Si ', 'Beng ', 'Si ', 'Jia ', 'Pi ', 'Yi ', 'Si ', 'Ai ', 'Zheng ', 'Dian ', 'Han ', 'Mai ', 'Dan ', 'Zhu ', 'Bu ', 'Qu ', 'Bi ', 'Shao ', 'Ci ', 'Wei ', 'Di ', 'Zhu ', 'Zuo ', 'You ', 'Yang ', 'Ti ', 'Zhan ', 'He ', 'Bi ', 'Tuo ', 'She ', 'Yu ', 'Yi ', 'Fo ', 'Zuo ', 'Kou ', 'Ning ', 'Tong ', 'Ni ', 'Xuan ', 'Qu ', 'Yong ', 'Wa ', 'Qian ', '[?] ', 'Ka ', '[?] ', 'Pei ', 'Huai ', 'He ', 'Lao ', 'Xiang ', 'Ge ', 'Yang ', 'Bai ', 'Fa ', 'Ming ', 'Jia ', 'Er ', 'Bing ', 'Ji ', 'Hen ', 'Huo ', 'Gui ', 'Quan ', 'Tiao ', 'Jiao ', 'Ci ', 'Yi ', 'Shi ', 'Xing ', 'Shen ', 'Tuo ', 'Kan ', 'Zhi ', 'Gai ', 'Lai ', 'Yi ', 'Chi ', 'Kua ', 'Guang ', 'Li ', 'Yin ', 'Shi ', 'Mi ', 'Zhu ', 'Xu ', 'You ', 'An ', 'Lu ', 'Mou ', 'Er ', 'Lun ', 'Tong ', 'Cha ', 'Chi ', 'Xun ', 'Gong ', 'Zhou ', 'Yi ', 'Ru ', 'Jian ', 'Xia ', 'Jia ', 'Zai ', 'Lu ', 'Ko ', 'Jiao ', 'Zhen ', 'Ce ', 'Qiao ', 'Kuai ', 'Chai ', 'Ning ', 'Nong ', 'Jin ', 'Wu ', 'Hou ', 'Jiong ', 'Cheng ', 'Zhen ', 'Zuo ', 'Chou ', 'Qin ', 'Lu ', 'Ju ', 'Shu ', 'Ting ', 'Shen ', 'Tuo ', 'Bo ', 'Nan ', 'Hao ', 'Bian ', 'Tui ', 'Yu ', 'Xi ', 'Cu ', 'E ', 'Qiu ', 'Xu ', 'Kuang ', 'Ku ', 'Wu ', 'Jun ', 'Yi ', 'Fu ', 'Lang ', 'Zu ', 'Qiao ', 'Li ', 'Yong ', 'Hun ', 'Jing ', 'Xian ', 'San ', 'Pai ', 'Su ', 'Fu ', 'Xi ', 'Li ', 'Fu ', 'Ping ', 'Bao ', 'Yu ', 'Si ', 'Xia ', 'Xin ', 'Xiu ', 'Yu ', 'Ti ', 'Che ', 'Chou ', '[?] ', 'Yan ', 'Lia ', 'Li ', 'Lai ', '[?] ', 'Jian ', 'Xiu ', 'Fu ', 'He ', 'Ju ', 'Xiao ', 'Pai ', 'Jian ', 'Biao ', 'Chu ', 'Fei ', 'Feng ', 'Ya ', 'An ', 'Bei ', 'Yu ', 'Xin ', 'Bi ', 'Jian '];
<?php return ['[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', 'eN', 'e', 'e', 'ai', 'oN', 'o', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', 'nnn', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'rr', 'l', 'l', 'lll', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '\'', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'eN', 'e', 'e', 'ai', 'oN', 'o', 'o', 'au', '', '[?]', '[?]', 'AUM', '\'', '\'', '`', '\'', '[?]', '[?]', '[?]', 'q', 'khh', 'ghh', 'z', 'dddh', 'rh', 'f', 'yy', 'RR', 'LL', 'L', 'LL', ' / ', ' // ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'N', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', '[?]', '[?]', 'e', 'ai', '[?]', '[?]', 'o', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', '[?]', 'l', '[?]', '[?]', '[?]', 'sh', 'ss', 's', 'h', '[?]', '[?]', '\'', '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'RR', '[?]', '[?]', 'e', 'ai', '[?]', '[?]', 'o', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '[?]', '[?]', '[?]', '[?]', 'rr', 'rh', '[?]', 'yy', 'RR', 'LL', 'L', 'LL', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'r\'', 'r`', 'Rs', 'Rs', '1/', '2/', '3/', '4/', ' 1 - 1/', '/16', '', '[?]', '[?]', '[?]', '[?]'];
<?php return ['[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]'];
<?php return ['Di ', 'Zhuang ', 'Le ', 'Lang ', 'Chen ', 'Cong ', 'Li ', 'Xiu ', 'Qing ', 'Shuang ', 'Fan ', 'Tong ', 'Guan ', 'Ji ', 'Suo ', 'Lei ', 'Lu ', 'Liang ', 'Mi ', 'Lou ', 'Chao ', 'Su ', 'Ke ', 'Shu ', 'Tang ', 'Biao ', 'Lu ', 'Jiu ', 'Shu ', 'Zha ', 'Shu ', 'Zhang ', 'Men ', 'Mo ', 'Niao ', 'Yang ', 'Tiao ', 'Peng ', 'Zhu ', 'Sha ', 'Xi ', 'Quan ', 'Heng ', 'Jian ', 'Cong ', '[?] ', 'Hokuso ', 'Qiang ', 'Tara ', 'Ying ', 'Er ', 'Xin ', 'Zhi ', 'Qiao ', 'Zui ', 'Cong ', 'Pu ', 'Shu ', 'Hua ', 'Kui ', 'Zhen ', 'Zun ', 'Yue ', 'Zhan ', 'Xi ', 'Xun ', 'Dian ', 'Fa ', 'Gan ', 'Mo ', 'Wu ', 'Qiao ', 'Nao ', 'Lin ', 'Liu ', 'Qiao ', 'Xian ', 'Run ', 'Fan ', 'Zhan ', 'Tuo ', 'Lao ', 'Yun ', 'Shun ', 'Tui ', 'Cheng ', 'Tang ', 'Meng ', 'Ju ', 'Cheng ', 'Su ', 'Jue ', 'Jue ', 'Tan ', 'Hui ', 'Ji ', 'Nuo ', 'Xiang ', 'Tuo ', 'Ning ', 'Rui ', 'Zhu ', 'Chuang ', 'Zeng ', 'Fen ', 'Qiong ', 'Ran ', 'Heng ', 'Cen ', 'Gu ', 'Liu ', 'Lao ', 'Gao ', 'Chu ', 'Zusa ', 'Nude ', 'Ca ', 'San ', 'Ji ', 'Dou ', 'Shou ', 'Lu ', '[?] ', '[?] ', 'Yuan ', 'Ta ', 'Shu ', 'Jiang ', 'Tan ', 'Lin ', 'Nong ', 'Yin ', 'Xi ', 'Sui ', 'Shan ', 'Zui ', 'Xuan ', 'Cheng ', 'Gan ', 'Ju ', 'Zui ', 'Yi ', 'Qin ', 'Pu ', 'Yan ', 'Lei ', 'Feng ', 'Hui ', 'Dang ', 'Ji ', 'Sui ', 'Bo ', 'Bi ', 'Ding ', 'Chu ', 'Zhua ', 'Kuai ', 'Ji ', 'Jie ', 'Jia ', 'Qing ', 'Zhe ', 'Jian ', 'Qiang ', 'Dao ', 'Yi ', 'Biao ', 'Song ', 'She ', 'Lin ', 'Kunugi ', 'Cha ', 'Meng ', 'Yin ', 'Tao ', 'Tai ', 'Mian ', 'Qi ', 'Toan ', 'Bin ', 'Huo ', 'Ji ', 'Qian ', 'Mi ', 'Ning ', 'Yi ', 'Gao ', 'Jian ', 'Yin ', 'Er ', 'Qing ', 'Yan ', 'Qi ', 'Mi ', 'Zhao ', 'Gui ', 'Chun ', 'Ji ', 'Kui ', 'Po ', 'Deng ', 'Chu ', '[?] ', 'Mian ', 'You ', 'Zhi ', 'Guang ', 'Qian ', 'Lei ', 'Lei ', 'Sa ', 'Lu ', 'Li ', 'Cuan ', 'Lu ', 'Mie ', 'Hui ', 'Ou ', 'Lu ', 'Jie ', 'Gao ', 'Du ', 'Yuan ', 'Li ', 'Fei ', 'Zhuo ', 'Sou ', 'Lian ', 'Tamo ', 'Chu ', '[?] ', 'Zhu ', 'Lu ', 'Yan ', 'Li ', 'Zhu ', 'Chen ', 'Jie ', 'E ', 'Su ', 'Huai ', 'Nie ', 'Yu ', 'Long ', 'Lai ', '[?] ', 'Xian ', 'Kwi ', 'Ju ', 'Xiao ', 'Ling ', 'Ying ', 'Jian ', 'Yin ', 'You ', 'Ying '];
<?php return ['[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'i', 'ii', 'u', 'uu', 'R', 'L', '[?]', 'e', 'ee', 'ai', '[?]', 'o', 'oo', 'au', 'k', 'kh', 'g', 'gh', 'ng', 'c', 'ch', 'j', 'jh', 'ny', 'tt', 'tth', 'dd', 'ddh', 'nn', 't', 'th', 'd', 'dh', 'n', '[?]', 'p', 'ph', 'b', 'bh', 'm', 'y', 'r', 'rr', 'l', 'll', 'lll', 'v', 'sh', 'ss', 's', 'h', '[?]', '[?]', '[?]', '[?]', 'aa', 'i', 'ii', 'u', 'uu', 'R', '[?]', '[?]', 'e', 'ee', 'ai', '', 'o', 'oo', 'au', '', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '+', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'RR', 'LL', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'N', 'H', '[?]', 'a', 'aa', 'ae', 'aae', 'i', 'ii', 'u', 'uu', 'R', 'RR', 'L', 'LL', 'e', 'ee', 'ai', 'o', 'oo', 'au', '[?]', '[?]', '[?]', 'k', 'kh', 'g', 'gh', 'ng', 'nng', 'c', 'ch', 'j', 'jh', 'ny', 'jny', 'nyj', 'tt', 'tth', 'dd', 'ddh', 'nn', 'nndd', 't', 'th', 'd', 'dh', 'n', '[?]', 'nd', 'p', 'ph', 'b', 'bh', 'm', 'mb', 'y', 'r', '[?]', 'l', '[?]', '[?]', 'v', 'sh', 'ss', 's', 'h', 'll', 'f', '[?]', '[?]', '[?]', '', '[?]', '[?]', '[?]', '[?]', 'aa', 'ae', 'aae', 'i', 'ii', 'u', '[?]', 'uu', '[?]', 'R', 'e', 'ee', 'ai', 'o', 'oo', 'au', 'L', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', 'RR', 'LL', ' . ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['mil', 'milg', 'milm', 'milb', 'mils', 'milt', 'milp', 'milh', 'mim', 'mib', 'mibs', 'mis', 'miss', 'ming', 'mij', 'mic', 'mik', 'mit', 'mip', 'mih', 'ba', 'bag', 'bagg', 'bags', 'ban', 'banj', 'banh', 'bad', 'bal', 'balg', 'balm', 'balb', 'bals', 'balt', 'balp', 'balh', 'bam', 'bab', 'babs', 'bas', 'bass', 'bang', 'baj', 'bac', 'bak', 'bat', 'bap', 'bah', 'bae', 'baeg', 'baegg', 'baegs', 'baen', 'baenj', 'baenh', 'baed', 'bael', 'baelg', 'baelm', 'baelb', 'baels', 'baelt', 'baelp', 'baelh', 'baem', 'baeb', 'baebs', 'baes', 'baess', 'baeng', 'baej', 'baec', 'baek', 'baet', 'baep', 'baeh', 'bya', 'byag', 'byagg', 'byags', 'byan', 'byanj', 'byanh', 'byad', 'byal', 'byalg', 'byalm', 'byalb', 'byals', 'byalt', 'byalp', 'byalh', 'byam', 'byab', 'byabs', 'byas', 'byass', 'byang', 'byaj', 'byac', 'byak', 'byat', 'byap', 'byah', 'byae', 'byaeg', 'byaegg', 'byaegs', 'byaen', 'byaenj', 'byaenh', 'byaed', 'byael', 'byaelg', 'byaelm', 'byaelb', 'byaels', 'byaelt', 'byaelp', 'byaelh', 'byaem', 'byaeb', 'byaebs', 'byaes', 'byaess', 'byaeng', 'byaej', 'byaec', 'byaek', 'byaet', 'byaep', 'byaeh', 'beo', 'beog', 'beogg', 'beogs', 'beon', 'beonj', 'beonh', 'beod', 'beol', 'beolg', 'beolm', 'beolb', 'beols', 'beolt', 'beolp', 'beolh', 'beom', 'beob', 'beobs', 'beos', 'beoss', 'beong', 'beoj', 'beoc', 'beok', 'beot', 'beop', 'beoh', 'be', 'beg', 'begg', 'begs', 'ben', 'benj', 'benh', 'bed', 'bel', 'belg', 'belm', 'belb', 'bels', 'belt', 'belp', 'belh', 'bem', 'beb', 'bebs', 'bes', 'bess', 'beng', 'bej', 'bec', 'bek', 'bet', 'bep', 'beh', 'byeo', 'byeog', 'byeogg', 'byeogs', 'byeon', 'byeonj', 'byeonh', 'byeod', 'byeol', 'byeolg', 'byeolm', 'byeolb', 'byeols', 'byeolt', 'byeolp', 'byeolh', 'byeom', 'byeob', 'byeobs', 'byeos', 'byeoss', 'byeong', 'byeoj', 'byeoc', 'byeok', 'byeot', 'byeop', 'byeoh', 'bye', 'byeg', 'byegg', 'byegs', 'byen', 'byenj', 'byenh', 'byed', 'byel', 'byelg', 'byelm', 'byelb', 'byels', 'byelt', 'byelp', 'byelh', 'byem', 'byeb', 'byebs', 'byes', 'byess', 'byeng', 'byej', 'byec', 'byek', 'byet', 'byep', 'byeh', 'bo', 'bog', 'bogg', 'bogs', 'bon', 'bonj', 'bonh', 'bod', 'bol', 'bolg', 'bolm', 'bolb'];
<?php return ['swa', 'swa', 'swaa', 'swaa', 'swaa', 's', 's', 'sw', 's', 'sk', 'skw', 'sW', 'spwa', 'stwa', 'skwa', 'scwa', 'she', 'shi', 'shii', 'sho', 'shoo', 'sha', 'shaa', 'shwe', 'shwe', 'shwi', 'shwi', 'shwii', 'shwii', 'shwo', 'shwo', 'shwoo', 'shwoo', 'shwa', 'shwa', 'shwaa', 'shwaa', 'sh', 'ye', 'yaai', 'yi', 'yii', 'yo', 'yoo', 'yoo', 'ya', 'yaa', 'ywe', 'ywe', 'ywi', 'ywi', 'ywii', 'ywii', 'ywo', 'ywo', 'ywoo', 'ywoo', 'ywa', 'ywa', 'ywaa', 'ywaa', 'ywaa', 'y', 'y', 'y', 'yi', 're', 're', 'le', 'raai', 'ri', 'rii', 'ro', 'roo', 'lo', 'ra', 'raa', 'la', 'rwaa', 'rwaa', 'r', 'r', 'r', 'fe', 'faai', 'fi', 'fii', 'fo', 'foo', 'fa', 'faa', 'fwaa', 'fwaa', 'f', 'the', 'the', 'thi', 'thi', 'thii', 'thii', 'tho', 'thoo', 'tha', 'thaa', 'thwaa', 'thwaa', 'th', 'tthe', 'tthi', 'ttho', 'ttha', 'tth', 'tye', 'tyi', 'tyo', 'tya', 'he', 'hi', 'hii', 'ho', 'hoo', 'ha', 'haa', 'h', 'h', 'hk', 'qaai', 'qi', 'qii', 'qo', 'qoo', 'qa', 'qaa', 'q', 'tlhe', 'tlhi', 'tlho', 'tlha', 're', 'ri', 'ro', 'ra', 'ngaai', 'ngi', 'ngii', 'ngo', 'ngoo', 'nga', 'ngaa', 'ng', 'nng', 'she', 'shi', 'sho', 'sha', 'the', 'thi', 'tho', 'tha', 'th', 'lhi', 'lhii', 'lho', 'lhoo', 'lha', 'lhaa', 'lh', 'the', 'thi', 'thii', 'tho', 'thoo', 'tha', 'thaa', 'th', 'b', 'e', 'i', 'o', 'a', 'we', 'wi', 'wo', 'wa', 'ne', 'ni', 'no', 'na', 'ke', 'ki', 'ko', 'ka', 'he', 'hi', 'ho', 'ha', 'ghu', 'gho', 'ghe', 'ghee', 'ghi', 'gha', 'ru', 'ro', 're', 'ree', 'ri', 'ra', 'wu', 'wo', 'we', 'wee', 'wi', 'wa', 'hwu', 'hwo', 'hwe', 'hwee', 'hwi', 'hwa', 'thu', 'tho', 'the', 'thee', 'thi', 'tha', 'ttu', 'tto', 'tte', 'ttee', 'tti', 'tta', 'pu', 'po', 'pe', 'pee', 'pi', 'pa', 'p', 'gu', 'go', 'ge', 'gee', 'gi', 'ga', 'khu', 'kho', 'khe', 'khee', 'khi', 'kha', 'kku', 'kko', 'kke', 'kkee', 'kki'];
<?php return ['sswals', 'sswalt', 'sswalp', 'sswalh', 'sswam', 'sswab', 'sswabs', 'sswas', 'sswass', 'sswang', 'sswaj', 'sswac', 'sswak', 'sswat', 'sswap', 'sswah', 'sswae', 'sswaeg', 'sswaegg', 'sswaegs', 'sswaen', 'sswaenj', 'sswaenh', 'sswaed', 'sswael', 'sswaelg', 'sswaelm', 'sswaelb', 'sswaels', 'sswaelt', 'sswaelp', 'sswaelh', 'sswaem', 'sswaeb', 'sswaebs', 'sswaes', 'sswaess', 'sswaeng', 'sswaej', 'sswaec', 'sswaek', 'sswaet', 'sswaep', 'sswaeh', 'ssoe', 'ssoeg', 'ssoegg', 'ssoegs', 'ssoen', 'ssoenj', 'ssoenh', 'ssoed', 'ssoel', 'ssoelg', 'ssoelm', 'ssoelb', 'ssoels', 'ssoelt', 'ssoelp', 'ssoelh', 'ssoem', 'ssoeb', 'ssoebs', 'ssoes', 'ssoess', 'ssoeng', 'ssoej', 'ssoec', 'ssoek', 'ssoet', 'ssoep', 'ssoeh', 'ssyo', 'ssyog', 'ssyogg', 'ssyogs', 'ssyon', 'ssyonj', 'ssyonh', 'ssyod', 'ssyol', 'ssyolg', 'ssyolm', 'ssyolb', 'ssyols', 'ssyolt', 'ssyolp', 'ssyolh', 'ssyom', 'ssyob', 'ssyobs', 'ssyos', 'ssyoss', 'ssyong', 'ssyoj', 'ssyoc', 'ssyok', 'ssyot', 'ssyop', 'ssyoh', 'ssu', 'ssug', 'ssugg', 'ssugs', 'ssun', 'ssunj', 'ssunh', 'ssud', 'ssul', 'ssulg', 'ssulm', 'ssulb', 'ssuls', 'ssult', 'ssulp', 'ssulh', 'ssum', 'ssub', 'ssubs', 'ssus', 'ssuss', 'ssung', 'ssuj', 'ssuc', 'ssuk', 'ssut', 'ssup', 'ssuh', 'ssweo', 'ssweog', 'ssweogg', 'ssweogs', 'ssweon', 'ssweonj', 'ssweonh', 'ssweod', 'ssweol', 'ssweolg', 'ssweolm', 'ssweolb', 'ssweols', 'ssweolt', 'ssweolp', 'ssweolh', 'ssweom', 'ssweob', 'ssweobs', 'ssweos', 'ssweoss', 'ssweong', 'ssweoj', 'ssweoc', 'ssweok', 'ssweot', 'ssweop', 'ssweoh', 'sswe', 'ssweg', 'sswegg', 'sswegs', 'sswen', 'sswenj', 'sswenh', 'sswed', 'sswel', 'sswelg', 'sswelm', 'sswelb', 'sswels', 'sswelt', 'sswelp', 'sswelh', 'sswem', 'ssweb', 'sswebs', 'sswes', 'sswess', 'ssweng', 'sswej', 'sswec', 'sswek', 'sswet', 'sswep', 'ssweh', 'sswi', 'sswig', 'sswigg', 'sswigs', 'sswin', 'sswinj', 'sswinh', 'sswid', 'sswil', 'sswilg', 'sswilm', 'sswilb', 'sswils', 'sswilt', 'sswilp', 'sswilh', 'sswim', 'sswib', 'sswibs', 'sswis', 'sswiss', 'sswing', 'sswij', 'sswic', 'sswik', 'sswit', 'sswip', 'sswih', 'ssyu', 'ssyug', 'ssyugg', 'ssyugs', 'ssyun', 'ssyunj', 'ssyunh', 'ssyud', 'ssyul', 'ssyulg', 'ssyulm', 'ssyulb', 'ssyuls', 'ssyult', 'ssyulp', 'ssyulh', 'ssyum', 'ssyub', 'ssyubs', 'ssyus', 'ssyuss', 'ssyung', 'ssyuj', 'ssyuc', 'ssyuk', 'ssyut', 'ssyup', 'ssyuh', 'sseu', 'sseug', 'sseugg', 'sseugs', 'sseun', 'sseunj', 'sseunh', 'sseud', 'sseul', 'sseulg', 'sseulm', 'sseulb', 'sseuls', 'sseult', 'sseulp', 'sseulh'];
<?php return ['ggyeols', 'ggyeolt', 'ggyeolp', 'ggyeolh', 'ggyeom', 'ggyeob', 'ggyeobs', 'ggyeos', 'ggyeoss', 'ggyeong', 'ggyeoj', 'ggyeoc', 'ggyeok', 'ggyeot', 'ggyeop', 'ggyeoh', 'ggye', 'ggyeg', 'ggyegg', 'ggyegs', 'ggyen', 'ggyenj', 'ggyenh', 'ggyed', 'ggyel', 'ggyelg', 'ggyelm', 'ggyelb', 'ggyels', 'ggyelt', 'ggyelp', 'ggyelh', 'ggyem', 'ggyeb', 'ggyebs', 'ggyes', 'ggyess', 'ggyeng', 'ggyej', 'ggyec', 'ggyek', 'ggyet', 'ggyep', 'ggyeh', 'ggo', 'ggog', 'ggogg', 'ggogs', 'ggon', 'ggonj', 'ggonh', 'ggod', 'ggol', 'ggolg', 'ggolm', 'ggolb', 'ggols', 'ggolt', 'ggolp', 'ggolh', 'ggom', 'ggob', 'ggobs', 'ggos', 'ggoss', 'ggong', 'ggoj', 'ggoc', 'ggok', 'ggot', 'ggop', 'ggoh', 'ggwa', 'ggwag', 'ggwagg', 'ggwags', 'ggwan', 'ggwanj', 'ggwanh', 'ggwad', 'ggwal', 'ggwalg', 'ggwalm', 'ggwalb', 'ggwals', 'ggwalt', 'ggwalp', 'ggwalh', 'ggwam', 'ggwab', 'ggwabs', 'ggwas', 'ggwass', 'ggwang', 'ggwaj', 'ggwac', 'ggwak', 'ggwat', 'ggwap', 'ggwah', 'ggwae', 'ggwaeg', 'ggwaegg', 'ggwaegs', 'ggwaen', 'ggwaenj', 'ggwaenh', 'ggwaed', 'ggwael', 'ggwaelg', 'ggwaelm', 'ggwaelb', 'ggwaels', 'ggwaelt', 'ggwaelp', 'ggwaelh', 'ggwaem', 'ggwaeb', 'ggwaebs', 'ggwaes', 'ggwaess', 'ggwaeng', 'ggwaej', 'ggwaec', 'ggwaek', 'ggwaet', 'ggwaep', 'ggwaeh', 'ggoe', 'ggoeg', 'ggoegg', 'ggoegs', 'ggoen', 'ggoenj', 'ggoenh', 'ggoed', 'ggoel', 'ggoelg', 'ggoelm', 'ggoelb', 'ggoels', 'ggoelt', 'ggoelp', 'ggoelh', 'ggoem', 'ggoeb', 'ggoebs', 'ggoes', 'ggoess', 'ggoeng', 'ggoej', 'ggoec', 'ggoek', 'ggoet', 'ggoep', 'ggoeh', 'ggyo', 'ggyog', 'ggyogg', 'ggyogs', 'ggyon', 'ggyonj', 'ggyonh', 'ggyod', 'ggyol', 'ggyolg', 'ggyolm', 'ggyolb', 'ggyols', 'ggyolt', 'ggyolp', 'ggyolh', 'ggyom', 'ggyob', 'ggyobs', 'ggyos', 'ggyoss', 'ggyong', 'ggyoj', 'ggyoc', 'ggyok', 'ggyot', 'ggyop', 'ggyoh', 'ggu', 'ggug', 'ggugg', 'ggugs', 'ggun', 'ggunj', 'ggunh', 'ggud', 'ggul', 'ggulg', 'ggulm', 'ggulb', 'gguls', 'ggult', 'ggulp', 'ggulh', 'ggum', 'ggub', 'ggubs', 'ggus', 'gguss', 'ggung', 'gguj', 'gguc', 'gguk', 'ggut', 'ggup', 'gguh', 'ggweo', 'ggweog', 'ggweogg', 'ggweogs', 'ggweon', 'ggweonj', 'ggweonh', 'ggweod', 'ggweol', 'ggweolg', 'ggweolm', 'ggweolb', 'ggweols', 'ggweolt', 'ggweolp', 'ggweolh', 'ggweom', 'ggweob', 'ggweobs', 'ggweos', 'ggweoss', 'ggweong', 'ggweoj', 'ggweoc', 'ggweok', 'ggweot', 'ggweop', 'ggweoh', 'ggwe', 'ggweg', 'ggwegg', 'ggwegs', 'ggwen', 'ggwenj', 'ggwenh', 'ggwed', 'ggwel', 'ggwelg', 'ggwelm', 'ggwelb', 'ggwels', 'ggwelt', 'ggwelp', 'ggwelh'];
<?php return ['Ie', 'Io', 'Dj', 'Gj', 'Ie', 'Dz', 'I', 'Yi', 'J', 'Lj', 'Nj', 'Tsh', 'Kj', 'I', 'U', 'Dzh', 'A', 'B', 'V', 'G', 'D', 'E', 'Zh', 'Z', 'I', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'Kh', 'Ts', 'Ch', 'Sh', 'Shch', '\'', 'Y', '\'', 'E', 'Iu', 'Ia', 'a', 'b', 'v', 'g', 'd', 'e', 'zh', 'z', 'i', 'i', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'kh', 'ts', 'ch', 'sh', 'shch', '\'', 'y', '\'', 'e', 'iu', 'ia', 'ie', 'io', 'dj', 'gj', 'ie', 'dz', 'i', 'yi', 'j', 'lj', 'nj', 'tsh', 'kj', 'i', 'u', 'dzh', 'O', 'o', 'E', 'e', 'Ie', 'ie', 'E', 'e', 'Ie', 'ie', 'O', 'o', 'Io', 'io', 'Ks', 'ks', 'Ps', 'ps', 'F', 'f', 'Y', 'y', 'Y', 'y', 'u', 'u', 'O', 'o', 'O', 'o', 'Ot', 'ot', 'Q', 'q', '*1000*', '', '', '', '', '[?]', '*100.000*', '*1.000.000*', '[?]', '[?]', '"', '"', 'R\'', 'r\'', 'G\'', 'g\'', 'G\'', 'g\'', 'G\'', 'g\'', 'Zh\'', 'zh\'', 'Z\'', 'z\'', 'K\'', 'k\'', 'K\'', 'k\'', 'K\'', 'k\'', 'K\'', 'k\'', 'N\'', 'n\'', 'Ng', 'ng', 'P\'', 'p\'', 'Kh', 'kh', 'S\'', 's\'', 'T\'', 't\'', 'U', 'u', 'U\'', 'u\'', 'Kh\'', 'kh\'', 'Tts', 'tts', 'Ch\'', 'ch\'', 'Ch\'', 'ch\'', 'H', 'h', 'Ch', 'ch', 'Ch\'', 'ch\'', '`', 'Zh', 'zh', 'K\'', 'k\'', '[?]', '[?]', 'N\'', 'n\'', '[?]', '[?]', 'Ch', 'ch', '[?]', '[?]', '[?]', 'a', 'a', 'A', 'a', 'Ae', 'ae', 'Ie', 'ie', '@', '@', '@', '@', 'Zh', 'zh', 'Z', 'z', 'Dz', 'dz', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', 'O', 'o', 'E', 'e', 'U', 'u', 'U', 'u', 'U', 'u', 'Ch', 'ch', '[?]', '[?]', 'Y', 'y', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', '(ju)', '[?]', '[?]', '[?]', '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Dai) ', '(Hu) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', '(Ji) ', '(Xiu) ', '<<', '>>', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '(g)', '(n)', '(d)', '(r)', '(m)', '(b)', '(s)', '()', '(j)', '(c)', '(k)', '(t)', '(p)', '(h)', '(ga)', '(na)', '(da)', '(ra)', '(ma)', '(ba)', '(sa)', '(a)', '(ja)', '(ca)', '(ka)', '(ta)', '(pa)', '(ha)', '[?]', '[?]', '[?]', 'KIS ', '(1) ', '(2) ', '(3) ', '(4) ', '(5) ', '(6) ', '(7) ', '(8) ', '(9) ', '(10) ', '(Yue) ', '(Huo) ', '(Shui) ', '(Mu) ', '(Jin) ', '(Tu) ', '(Ri) ', '(Zhu) ', '(You) ', '(She) ', '(Ming) ', '(Te) ', '(Cai) ', '(Zhu) ', '(Lao) ', '(Mi) ', '(Nan) ', '(Nu) ', '(Shi) ', '(You) ', '(Yin) ', '(Zhu) ', '(Xiang) ', '(Xiu) ', '(Xie) ', '(Zheng) ', '(Shang) ', '(Zhong) ', '(Xia) ', '(Zuo) ', '(You) ', '(Yi) ', '(Zong) ', '(Xue) ', '(Jian) ', '(Qi) ', '(Zi) ', '(Xie) ', '(Ye) ', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '1M', '2M', '3M', '4M', '5M', '6M', '7M', '8M', '9M', '10M', '11M', '12M', 'Hg', 'erg', 'eV', 'LTD', 'a', 'i', 'u', 'u', 'o', 'ka', 'ki', 'ku', 'ke', 'ko', 'sa', 'si', 'su', 'se', 'so', 'ta', 'ti', 'tu', 'te', 'to', 'na', 'ni', 'nu', 'ne', 'no', 'ha', 'hi', 'hu', 'he', 'ho', 'ma', 'mi', 'mu', 'me', 'mo', 'ya', 'yu', 'yo', 'ra', 'ri', 'ru', 're', 'ro', 'wa', 'wi', 'we', 'wo'];
<?php return ['dae', 'daeg', 'daegg', 'daegs', 'daen', 'daenj', 'daenh', 'daed', 'dael', 'daelg', 'daelm', 'daelb', 'daels', 'daelt', 'daelp', 'daelh', 'daem', 'daeb', 'daebs', 'daes', 'daess', 'daeng', 'daej', 'daec', 'daek', 'daet', 'daep', 'daeh', 'dya', 'dyag', 'dyagg', 'dyags', 'dyan', 'dyanj', 'dyanh', 'dyad', 'dyal', 'dyalg', 'dyalm', 'dyalb', 'dyals', 'dyalt', 'dyalp', 'dyalh', 'dyam', 'dyab', 'dyabs', 'dyas', 'dyass', 'dyang', 'dyaj', 'dyac', 'dyak', 'dyat', 'dyap', 'dyah', 'dyae', 'dyaeg', 'dyaegg', 'dyaegs', 'dyaen', 'dyaenj', 'dyaenh', 'dyaed', 'dyael', 'dyaelg', 'dyaelm', 'dyaelb', 'dyaels', 'dyaelt', 'dyaelp', 'dyaelh', 'dyaem', 'dyaeb', 'dyaebs', 'dyaes', 'dyaess', 'dyaeng', 'dyaej', 'dyaec', 'dyaek', 'dyaet', 'dyaep', 'dyaeh', 'deo', 'deog', 'deogg', 'deogs', 'deon', 'deonj', 'deonh', 'deod', 'deol', 'deolg', 'deolm', 'deolb', 'deols', 'deolt', 'deolp', 'deolh', 'deom', 'deob', 'deobs', 'deos', 'deoss', 'deong', 'deoj', 'deoc', 'deok', 'deot', 'deop', 'deoh', 'de', 'deg', 'degg', 'degs', 'den', 'denj', 'denh', 'ded', 'del', 'delg', 'delm', 'delb', 'dels', 'delt', 'delp', 'delh', 'dem', 'deb', 'debs', 'des', 'dess', 'deng', 'dej', 'dec', 'dek', 'det', 'dep', 'deh', 'dyeo', 'dyeog', 'dyeogg', 'dyeogs', 'dyeon', 'dyeonj', 'dyeonh', 'dyeod', 'dyeol', 'dyeolg', 'dyeolm', 'dyeolb', 'dyeols', 'dyeolt', 'dyeolp', 'dyeolh', 'dyeom', 'dyeob', 'dyeobs', 'dyeos', 'dyeoss', 'dyeong', 'dyeoj', 'dyeoc', 'dyeok', 'dyeot', 'dyeop', 'dyeoh', 'dye', 'dyeg', 'dyegg', 'dyegs', 'dyen', 'dyenj', 'dyenh', 'dyed', 'dyel', 'dyelg', 'dyelm', 'dyelb', 'dyels', 'dyelt', 'dyelp', 'dyelh', 'dyem', 'dyeb', 'dyebs', 'dyes', 'dyess', 'dyeng', 'dyej', 'dyec', 'dyek', 'dyet', 'dyep', 'dyeh', 'do', 'dog', 'dogg', 'dogs', 'don', 'donj', 'donh', 'dod', 'dol', 'dolg', 'dolm', 'dolb', 'dols', 'dolt', 'dolp', 'dolh', 'dom', 'dob', 'dobs', 'dos', 'doss', 'dong', 'doj', 'doc', 'dok', 'dot', 'dop', 'doh', 'dwa', 'dwag', 'dwagg', 'dwags', 'dwan', 'dwanj', 'dwanh', 'dwad', 'dwal', 'dwalg', 'dwalm', 'dwalb', 'dwals', 'dwalt', 'dwalp', 'dwalh', 'dwam', 'dwab', 'dwabs', 'dwas', 'dwass', 'dwang', 'dwaj', 'dwac', 'dwak', 'dwat', 'dwap', 'dwah', 'dwae', 'dwaeg', 'dwaegg', 'dwaegs'];
<?php return ['Shu ', 'Luo ', 'Qi ', 'Yi ', 'Ji ', 'Zhe ', 'Yu ', 'Zhan ', 'Ye ', 'Yang ', 'Pi ', 'Ning ', 'Huo ', 'Mi ', 'Ying ', 'Meng ', 'Di ', 'Yue ', 'Yu ', 'Lei ', 'Bao ', 'Lu ', 'He ', 'Long ', 'Shuang ', 'Yue ', 'Ying ', 'Guan ', 'Qu ', 'Li ', 'Luan ', 'Niao ', 'Jiu ', 'Ji ', 'Yuan ', 'Ming ', 'Shi ', 'Ou ', 'Ya ', 'Cang ', 'Bao ', 'Zhen ', 'Gu ', 'Dong ', 'Lu ', 'Ya ', 'Xiao ', 'Yang ', 'Ling ', 'Zhi ', 'Qu ', 'Yuan ', 'Xue ', 'Tuo ', 'Si ', 'Zhi ', 'Er ', 'Gua ', 'Xiu ', 'Heng ', 'Zhou ', 'Ge ', 'Luan ', 'Hong ', 'Wu ', 'Bo ', 'Li ', 'Juan ', 'Hu ', 'E ', 'Yu ', 'Xian ', 'Ti ', 'Wu ', 'Que ', 'Miao ', 'An ', 'Kun ', 'Bei ', 'Peng ', 'Qian ', 'Chun ', 'Geng ', 'Yuan ', 'Su ', 'Hu ', 'He ', 'E ', 'Gu ', 'Qiu ', 'Zi ', 'Mei ', 'Mu ', 'Ni ', 'Yao ', 'Weng ', 'Liu ', 'Ji ', 'Ni ', 'Jian ', 'He ', 'Yi ', 'Ying ', 'Zhe ', 'Liao ', 'Liao ', 'Jiao ', 'Jiu ', 'Yu ', 'Lu ', 'Xuan ', 'Zhan ', 'Ying ', 'Huo ', 'Meng ', 'Guan ', 'Shuang ', 'Lu ', 'Jin ', 'Ling ', 'Jian ', 'Xian ', 'Cuo ', 'Jian ', 'Jian ', 'Yan ', 'Cuo ', 'Lu ', 'You ', 'Cu ', 'Ji ', 'Biao ', 'Cu ', 'Biao ', 'Zhu ', 'Jun ', 'Zhu ', 'Jian ', 'Mi ', 'Mi ', 'Wu ', 'Liu ', 'Chen ', 'Jun ', 'Lin ', 'Ni ', 'Qi ', 'Lu ', 'Jiu ', 'Jun ', 'Jing ', 'Li ', 'Xiang ', 'Yan ', 'Jia ', 'Mi ', 'Li ', 'She ', 'Zhang ', 'Lin ', 'Jing ', 'Ji ', 'Ling ', 'Yan ', 'Cu ', 'Mai ', 'Mai ', 'Ge ', 'Chao ', 'Fu ', 'Mian ', 'Mian ', 'Fu ', 'Pao ', 'Qu ', 'Qu ', 'Mou ', 'Fu ', 'Xian ', 'Lai ', 'Qu ', 'Mian ', '[?] ', 'Feng ', 'Fu ', 'Qu ', 'Mian ', 'Ma ', 'Mo ', 'Mo ', 'Hui ', 'Ma ', 'Zou ', 'Nen ', 'Fen ', 'Huang ', 'Huang ', 'Jin ', 'Guang ', 'Tian ', 'Tou ', 'Heng ', 'Xi ', 'Kuang ', 'Heng ', 'Shu ', 'Li ', 'Nian ', 'Chi ', 'Hei ', 'Hei ', 'Yi ', 'Qian ', 'Dan ', 'Xi ', 'Tuan ', 'Mo ', 'Mo ', 'Qian ', 'Dai ', 'Chu ', 'You ', 'Dian ', 'Yi ', 'Xia ', 'Yan ', 'Qu ', 'Mei ', 'Yan ', 'Jing ', 'Yu ', 'Li ', 'Dang ', 'Du ', 'Can ', 'Yin ', 'An ', 'Yan ', 'Tan ', 'An ', 'Zhen ', 'Dai ', 'Can ', 'Yi ', 'Mei ', 'Dan ', 'Yan ', 'Du ', 'Lu ', 'Zhi ', 'Fen ', 'Fu ', 'Fu ', 'Min ', 'Min ', 'Yuan '];
<?php return ['moen', 'moenj', 'moenh', 'moed', 'moel', 'moelg', 'moelm', 'moelb', 'moels', 'moelt', 'moelp', 'moelh', 'moem', 'moeb', 'moebs', 'moes', 'moess', 'moeng', 'moej', 'moec', 'moek', 'moet', 'moep', 'moeh', 'myo', 'myog', 'myogg', 'myogs', 'myon', 'myonj', 'myonh', 'myod', 'myol', 'myolg', 'myolm', 'myolb', 'myols', 'myolt', 'myolp', 'myolh', 'myom', 'myob', 'myobs', 'myos', 'myoss', 'myong', 'myoj', 'myoc', 'myok', 'myot', 'myop', 'myoh', 'mu', 'mug', 'mugg', 'mugs', 'mun', 'munj', 'munh', 'mud', 'mul', 'mulg', 'mulm', 'mulb', 'muls', 'mult', 'mulp', 'mulh', 'mum', 'mub', 'mubs', 'mus', 'muss', 'mung', 'muj', 'muc', 'muk', 'mut', 'mup', 'muh', 'mweo', 'mweog', 'mweogg', 'mweogs', 'mweon', 'mweonj', 'mweonh', 'mweod', 'mweol', 'mweolg', 'mweolm', 'mweolb', 'mweols', 'mweolt', 'mweolp', 'mweolh', 'mweom', 'mweob', 'mweobs', 'mweos', 'mweoss', 'mweong', 'mweoj', 'mweoc', 'mweok', 'mweot', 'mweop', 'mweoh', 'mwe', 'mweg', 'mwegg', 'mwegs', 'mwen', 'mwenj', 'mwenh', 'mwed', 'mwel', 'mwelg', 'mwelm', 'mwelb', 'mwels', 'mwelt', 'mwelp', 'mwelh', 'mwem', 'mweb', 'mwebs', 'mwes', 'mwess', 'mweng', 'mwej', 'mwec', 'mwek', 'mwet', 'mwep', 'mweh', 'mwi', 'mwig', 'mwigg', 'mwigs', 'mwin', 'mwinj', 'mwinh', 'mwid', 'mwil', 'mwilg', 'mwilm', 'mwilb', 'mwils', 'mwilt', 'mwilp', 'mwilh', 'mwim', 'mwib', 'mwibs', 'mwis', 'mwiss', 'mwing', 'mwij', 'mwic', 'mwik', 'mwit', 'mwip', 'mwih', 'myu', 'myug', 'myugg', 'myugs', 'myun', 'myunj', 'myunh', 'myud', 'myul', 'myulg', 'myulm', 'myulb', 'myuls', 'myult', 'myulp', 'myulh', 'myum', 'myub', 'myubs', 'myus', 'myuss', 'myung', 'myuj', 'myuc', 'myuk', 'myut', 'myup', 'myuh', 'meu', 'meug', 'meugg', 'meugs', 'meun', 'meunj', 'meunh', 'meud', 'meul', 'meulg', 'meulm', 'meulb', 'meuls', 'meult', 'meulp', 'meulh', 'meum', 'meub', 'meubs', 'meus', 'meuss', 'meung', 'meuj', 'meuc', 'meuk', 'meut', 'meup', 'meuh', 'myi', 'myig', 'myigg', 'myigs', 'myin', 'myinj', 'myinh', 'myid', 'myil', 'myilg', 'myilm', 'myilb', 'myils', 'myilt', 'myilp', 'myilh', 'myim', 'myib', 'myibs', 'myis', 'myiss', 'mying', 'myij', 'myic', 'myik', 'myit', 'myip', 'myih', 'mi', 'mig', 'migg', 'migs', 'min', 'minj', 'minh', 'mid'];
<?php return ['Ba ', 'Fang ', 'Chen ', 'Xing ', 'Tou ', 'Yue ', 'Yan ', 'Fu ', 'Pi ', 'Na ', 'Xin ', 'E ', 'Jue ', 'Dun ', 'Gou ', 'Yin ', 'Qian ', 'Ban ', 'Ji ', 'Ren ', 'Chao ', 'Niu ', 'Fen ', 'Yun ', 'Ji ', 'Qin ', 'Pi ', 'Guo ', 'Hong ', 'Yin ', 'Jun ', 'Shi ', 'Yi ', 'Zhong ', 'Nie ', 'Gai ', 'Ri ', 'Huo ', 'Tai ', 'Kang ', 'Habaki ', 'Irori ', 'Ngaak ', '[?] ', 'Duo ', 'Zi ', 'Ni ', 'Tu ', 'Shi ', 'Min ', 'Gu ', 'E ', 'Ling ', 'Bing ', 'Yi ', 'Gu ', 'Ba ', 'Pi ', 'Yu ', 'Si ', 'Zuo ', 'Bu ', 'You ', 'Dian ', 'Jia ', 'Zhen ', 'Shi ', 'Shi ', 'Tie ', 'Ju ', 'Zhan ', 'Shi ', 'She ', 'Xuan ', 'Zhao ', 'Bao ', 'He ', 'Bi ', 'Sheng ', 'Chu ', 'Shi ', 'Bo ', 'Zhu ', 'Chi ', 'Za ', 'Po ', 'Tong ', 'Qian ', 'Fu ', 'Zhai ', 'Liu ', 'Qian ', 'Fu ', 'Li ', 'Yue ', 'Pi ', 'Yang ', 'Ban ', 'Bo ', 'Jie ', 'Gou ', 'Shu ', 'Zheng ', 'Mu ', 'Ni ', 'Nie ', 'Di ', 'Jia ', 'Mu ', 'Dan ', 'Shen ', 'Yi ', 'Si ', 'Kuang ', 'Ka ', 'Bei ', 'Jian ', 'Tong ', 'Xing ', 'Hong ', 'Jiao ', 'Chi ', 'Er ', 'Ge ', 'Bing ', 'Shi ', 'Mou ', 'Jia ', 'Yin ', 'Jun ', 'Zhou ', 'Chong ', 'Shang ', 'Tong ', 'Mo ', 'Lei ', 'Ji ', 'Yu ', 'Xu ', 'Ren ', 'Zun ', 'Zhi ', 'Qiong ', 'Shan ', 'Chi ', 'Xian ', 'Xing ', 'Quan ', 'Pi ', 'Tie ', 'Zhu ', 'Hou ', 'Ming ', 'Kua ', 'Yao ', 'Xian ', 'Xian ', 'Xiu ', 'Jun ', 'Cha ', 'Lao ', 'Ji ', 'Pi ', 'Ru ', 'Mi ', 'Yi ', 'Yin ', 'Guang ', 'An ', 'Diou ', 'You ', 'Se ', 'Kao ', 'Qian ', 'Luan ', 'Kasugai ', 'Ai ', 'Diao ', 'Han ', 'Rui ', 'Shi ', 'Keng ', 'Qiu ', 'Xiao ', 'Zhe ', 'Xiu ', 'Zang ', 'Ti ', 'Cuo ', 'Gua ', 'Gong ', 'Zhong ', 'Dou ', 'Lu ', 'Mei ', 'Lang ', 'Wan ', 'Xin ', 'Yun ', 'Bei ', 'Wu ', 'Su ', 'Yu ', 'Chan ', 'Ting ', 'Bo ', 'Han ', 'Jia ', 'Hong ', 'Cuan ', 'Feng ', 'Chan ', 'Wan ', 'Zhi ', 'Si ', 'Xuan ', 'Wu ', 'Wu ', 'Tiao ', 'Gong ', 'Zhuo ', 'Lue ', 'Xing ', 'Qian ', 'Shen ', 'Han ', 'Lue ', 'Xie ', 'Chu ', 'Zheng ', 'Ju ', 'Xian ', 'Tie ', 'Mang ', 'Pu ', 'Li ', 'Pan ', 'Rui ', 'Cheng ', 'Gao ', 'Li ', 'Te ', 'Pyeng ', 'Zhu ', '[?] ', 'Tu ', 'Liu ', 'Zui ', 'Ju ', 'Chang ', 'Yuan ', 'Jian ', 'Gang ', 'Diao ', 'Tao ', 'Chang '];
<?php return ['Zui ', 'Can ', 'Xu ', 'Hui ', 'Yin ', 'Qie ', 'Fen ', 'Pi ', 'Yue ', 'You ', 'Ruan ', 'Peng ', 'Ban ', 'Fu ', 'Ling ', 'Fei ', 'Qu ', '[?] ', 'Nu ', 'Tiao ', 'Shuo ', 'Zhen ', 'Lang ', 'Lang ', 'Juan ', 'Ming ', 'Huang ', 'Wang ', 'Tun ', 'Zhao ', 'Ji ', 'Qi ', 'Ying ', 'Zong ', 'Wang ', 'Tong ', 'Lang ', '[?] ', 'Meng ', 'Long ', 'Mu ', 'Deng ', 'Wei ', 'Mo ', 'Ben ', 'Zha ', 'Zhu ', 'Zhu ', '[?] ', 'Zhu ', 'Ren ', 'Ba ', 'Po ', 'Duo ', 'Duo ', 'Dao ', 'Li ', 'Qiu ', 'Ji ', 'Jiu ', 'Bi ', 'Xiu ', 'Ting ', 'Ci ', 'Sha ', 'Eburi ', 'Za ', 'Quan ', 'Qian ', 'Yu ', 'Gan ', 'Wu ', 'Cha ', 'Shan ', 'Xun ', 'Fan ', 'Wu ', 'Zi ', 'Li ', 'Xing ', 'Cai ', 'Cun ', 'Ren ', 'Shao ', 'Tuo ', 'Di ', 'Zhang ', 'Mang ', 'Chi ', 'Yi ', 'Gu ', 'Gong ', 'Du ', 'Yi ', 'Qi ', 'Shu ', 'Gang ', 'Tiao ', 'Moku ', 'Soma ', 'Tochi ', 'Lai ', 'Sugi ', 'Mang ', 'Yang ', 'Ma ', 'Miao ', 'Si ', 'Yuan ', 'Hang ', 'Fei ', 'Bei ', 'Jie ', 'Dong ', 'Gao ', 'Yao ', 'Xian ', 'Chu ', 'Qun ', 'Pa ', 'Shu ', 'Hua ', 'Xin ', 'Chou ', 'Zhu ', 'Chou ', 'Song ', 'Ban ', 'Song ', 'Ji ', 'Yue ', 'Jin ', 'Gou ', 'Ji ', 'Mao ', 'Pi ', 'Bi ', 'Wang ', 'Ang ', 'Fang ', 'Fen ', 'Yi ', 'Fu ', 'Nan ', 'Xi ', 'Hu ', 'Ya ', 'Dou ', 'Xun ', 'Zhen ', 'Yao ', 'Lin ', 'Rui ', 'E ', 'Mei ', 'Zhao ', 'Guo ', 'Zhi ', 'Cong ', 'Yun ', 'Waku ', 'Dou ', 'Shu ', 'Zao ', '[?] ', 'Li ', 'Haze ', 'Jian ', 'Cheng ', 'Matsu ', 'Qiang ', 'Feng ', 'Nan ', 'Xiao ', 'Xian ', 'Ku ', 'Ping ', 'Yi ', 'Xi ', 'Zhi ', 'Guai ', 'Xiao ', 'Jia ', 'Jia ', 'Gou ', 'Fu ', 'Mo ', 'Yi ', 'Ye ', 'Ye ', 'Shi ', 'Nie ', 'Bi ', 'Duo ', 'Yi ', 'Ling ', 'Bing ', 'Ni ', 'La ', 'He ', 'Pan ', 'Fan ', 'Zhong ', 'Dai ', 'Ci ', 'Yang ', 'Fu ', 'Bo ', 'Mou ', 'Gan ', 'Qi ', 'Ran ', 'Rou ', 'Mao ', 'Zhao ', 'Song ', 'Zhe ', 'Xia ', 'You ', 'Shen ', 'Ju ', 'Tuo ', 'Zuo ', 'Nan ', 'Ning ', 'Yong ', 'Di ', 'Zhi ', 'Zha ', 'Cha ', 'Dan ', 'Gu ', 'Pu ', 'Jiu ', 'Ao ', 'Fu ', 'Jian ', 'Bo ', 'Duo ', 'Ke ', 'Nai ', 'Zhu ', 'Bi ', 'Liu ', 'Chai ', 'Zha ', 'Si ', 'Zhu ', 'Pei ', 'Shi ', 'Guai ', 'Cha ', 'Yao ', 'Jue ', 'Jiu ', 'Shi '];
<?php return ['gwan', 'gwanj', 'gwanh', 'gwad', 'gwal', 'gwalg', 'gwalm', 'gwalb', 'gwals', 'gwalt', 'gwalp', 'gwalh', 'gwam', 'gwab', 'gwabs', 'gwas', 'gwass', 'gwang', 'gwaj', 'gwac', 'gwak', 'gwat', 'gwap', 'gwah', 'gwae', 'gwaeg', 'gwaegg', 'gwaegs', 'gwaen', 'gwaenj', 'gwaenh', 'gwaed', 'gwael', 'gwaelg', 'gwaelm', 'gwaelb', 'gwaels', 'gwaelt', 'gwaelp', 'gwaelh', 'gwaem', 'gwaeb', 'gwaebs', 'gwaes', 'gwaess', 'gwaeng', 'gwaej', 'gwaec', 'gwaek', 'gwaet', 'gwaep', 'gwaeh', 'goe', 'goeg', 'goegg', 'goegs', 'goen', 'goenj', 'goenh', 'goed', 'goel', 'goelg', 'goelm', 'goelb', 'goels', 'goelt', 'goelp', 'goelh', 'goem', 'goeb', 'goebs', 'goes', 'goess', 'goeng', 'goej', 'goec', 'goek', 'goet', 'goep', 'goeh', 'gyo', 'gyog', 'gyogg', 'gyogs', 'gyon', 'gyonj', 'gyonh', 'gyod', 'gyol', 'gyolg', 'gyolm', 'gyolb', 'gyols', 'gyolt', 'gyolp', 'gyolh', 'gyom', 'gyob', 'gyobs', 'gyos', 'gyoss', 'gyong', 'gyoj', 'gyoc', 'gyok', 'gyot', 'gyop', 'gyoh', 'gu', 'gug', 'gugg', 'gugs', 'gun', 'gunj', 'gunh', 'gud', 'gul', 'gulg', 'gulm', 'gulb', 'guls', 'gult', 'gulp', 'gulh', 'gum', 'gub', 'gubs', 'gus', 'guss', 'gung', 'guj', 'guc', 'guk', 'gut', 'gup', 'guh', 'gweo', 'gweog', 'gweogg', 'gweogs', 'gweon', 'gweonj', 'gweonh', 'gweod', 'gweol', 'gweolg', 'gweolm', 'gweolb', 'gweols', 'gweolt', 'gweolp', 'gweolh', 'gweom', 'gweob', 'gweobs', 'gweos', 'gweoss', 'gweong', 'gweoj', 'gweoc', 'gweok', 'gweot', 'gweop', 'gweoh', 'gwe', 'gweg', 'gwegg', 'gwegs', 'gwen', 'gwenj', 'gwenh', 'gwed', 'gwel', 'gwelg', 'gwelm', 'gwelb', 'gwels', 'gwelt', 'gwelp', 'gwelh', 'gwem', 'gweb', 'gwebs', 'gwes', 'gwess', 'gweng', 'gwej', 'gwec', 'gwek', 'gwet', 'gwep', 'gweh', 'gwi', 'gwig', 'gwigg', 'gwigs', 'gwin', 'gwinj', 'gwinh', 'gwid', 'gwil', 'gwilg', 'gwilm', 'gwilb', 'gwils', 'gwilt', 'gwilp', 'gwilh', 'gwim', 'gwib', 'gwibs', 'gwis', 'gwiss', 'gwing', 'gwij', 'gwic', 'gwik', 'gwit', 'gwip', 'gwih', 'gyu', 'gyug', 'gyugg', 'gyugs', 'gyun', 'gyunj', 'gyunh', 'gyud', 'gyul', 'gyulg', 'gyulm', 'gyulb', 'gyuls', 'gyult', 'gyulp', 'gyulh', 'gyum', 'gyub', 'gyubs', 'gyus', 'gyuss', 'gyung', 'gyuj', 'gyuc', 'gyuk', 'gyut', 'gyup', 'gyuh', 'geu', 'geug', 'geugg', 'geugs', 'geun', 'geunj', 'geunh', 'geud'];
<?php return ['Zhui ', 'Zi ', 'Ke ', 'Xiang ', 'Jian ', 'Mian ', 'Lan ', 'Ti ', 'Miao ', 'Qi ', 'Yun ', 'Hui ', 'Si ', 'Duo ', 'Duan ', 'Bian ', 'Xian ', 'Gou ', 'Zhui ', 'Huan ', 'Di ', 'Lu ', 'Bian ', 'Min ', 'Yuan ', 'Jin ', 'Fu ', 'Ru ', 'Zhen ', 'Feng ', 'Shuai ', 'Gao ', 'Chan ', 'Li ', 'Yi ', 'Jian ', 'Bin ', 'Piao ', 'Man ', 'Lei ', 'Ying ', 'Suo ', 'Mou ', 'Sao ', 'Xie ', 'Liao ', 'Shan ', 'Zeng ', 'Jiang ', 'Qian ', 'Zao ', 'Huan ', 'Jiao ', 'Zuan ', 'Fou ', 'Xie ', 'Gang ', 'Fou ', 'Que ', 'Fou ', 'Kaakeru ', 'Bo ', 'Ping ', 'Hou ', '[?] ', 'Gang ', 'Ying ', 'Ying ', 'Qing ', 'Xia ', 'Guan ', 'Zun ', 'Tan ', 'Chang ', 'Qi ', 'Weng ', 'Ying ', 'Lei ', 'Tan ', 'Lu ', 'Guan ', 'Wang ', 'Wang ', 'Gang ', 'Wang ', 'Han ', '[?] ', 'Luo ', 'Fu ', 'Mi ', 'Fa ', 'Gu ', 'Zhu ', 'Ju ', 'Mao ', 'Gu ', 'Min ', 'Gang ', 'Ba ', 'Gua ', 'Ti ', 'Juan ', 'Fu ', 'Lin ', 'Yan ', 'Zhao ', 'Zui ', 'Gua ', 'Zhuo ', 'Yu ', 'Zhi ', 'An ', 'Fa ', 'Nan ', 'Shu ', 'Si ', 'Pi ', 'Ma ', 'Liu ', 'Ba ', 'Fa ', 'Li ', 'Chao ', 'Wei ', 'Bi ', 'Ji ', 'Zeng ', 'Tong ', 'Liu ', 'Ji ', 'Juan ', 'Mi ', 'Zhao ', 'Luo ', 'Pi ', 'Ji ', 'Ji ', 'Luan ', 'Yang ', 'Mie ', 'Qiang ', 'Ta ', 'Mei ', 'Yang ', 'You ', 'You ', 'Fen ', 'Ba ', 'Gao ', 'Yang ', 'Gu ', 'Qiang ', 'Zang ', 'Gao ', 'Ling ', 'Yi ', 'Zhu ', 'Di ', 'Xiu ', 'Qian ', 'Yi ', 'Xian ', 'Rong ', 'Qun ', 'Qun ', 'Qian ', 'Huan ', 'Zui ', 'Xian ', 'Yi ', 'Yashinau ', 'Qiang ', 'Xian ', 'Yu ', 'Geng ', 'Jie ', 'Tang ', 'Yuan ', 'Xi ', 'Fan ', 'Shan ', 'Fen ', 'Shan ', 'Lian ', 'Lei ', 'Geng ', 'Nou ', 'Qiang ', 'Chan ', 'Yu ', 'Gong ', 'Yi ', 'Chong ', 'Weng ', 'Fen ', 'Hong ', 'Chi ', 'Chi ', 'Cui ', 'Fu ', 'Xia ', 'Pen ', 'Yi ', 'La ', 'Yi ', 'Pi ', 'Ling ', 'Liu ', 'Zhi ', 'Qu ', 'Xi ', 'Xie ', 'Xiang ', 'Xi ', 'Xi ', 'Qi ', 'Qiao ', 'Hui ', 'Hui ', 'Xiao ', 'Se ', 'Hong ', 'Jiang ', 'Di ', 'Cui ', 'Fei ', 'Tao ', 'Sha ', 'Chi ', 'Zhu ', 'Jian ', 'Xuan ', 'Shi ', 'Pian ', 'Zong ', 'Wan ', 'Hui ', 'Hou ', 'He ', 'He ', 'Han ', 'Ao ', 'Piao ', 'Yi ', 'Lian ', 'Qu ', '[?] ', 'Lin ', 'Pen ', 'Qiao ', 'Ao ', 'Fan ', 'Yi ', 'Hui ', 'Xuan ', 'Dao '];
<?php return ['Ze ', 'Xi ', 'Guo ', 'Yi ', 'Hu ', 'Chan ', 'Kou ', 'Cu ', 'Ping ', 'Chou ', 'Ji ', 'Gui ', 'Su ', 'Lou ', 'Zha ', 'Lu ', 'Nian ', 'Suo ', 'Cuan ', 'Sasara ', 'Suo ', 'Le ', 'Duan ', 'Yana ', 'Xiao ', 'Bo ', 'Mi ', 'Si ', 'Dang ', 'Liao ', 'Dan ', 'Dian ', 'Fu ', 'Jian ', 'Min ', 'Kui ', 'Dai ', 'Qiao ', 'Deng ', 'Huang ', 'Sun ', 'Lao ', 'Zan ', 'Xiao ', 'Du ', 'Shi ', 'Zan ', '[?] ', 'Pai ', 'Hata ', 'Pai ', 'Gan ', 'Ju ', 'Du ', 'Lu ', 'Yan ', 'Bo ', 'Dang ', 'Sai ', 'Ke ', 'Long ', 'Qian ', 'Lian ', 'Bo ', 'Zhou ', 'Lai ', '[?] ', 'Lan ', 'Kui ', 'Yu ', 'Yue ', 'Hao ', 'Zhen ', 'Tai ', 'Ti ', 'Mi ', 'Chou ', 'Ji ', '[?] ', 'Hata ', 'Teng ', 'Zhuan ', 'Zhou ', 'Fan ', 'Sou ', 'Zhou ', 'Kuji ', 'Zhuo ', 'Teng ', 'Lu ', 'Lu ', 'Jian ', 'Tuo ', 'Ying ', 'Yu ', 'Lai ', 'Long ', 'Shinshi ', 'Lian ', 'Lan ', 'Qian ', 'Yue ', 'Zhong ', 'Qu ', 'Lian ', 'Bian ', 'Duan ', 'Zuan ', 'Li ', 'Si ', 'Luo ', 'Ying ', 'Yue ', 'Zhuo ', 'Xu ', 'Mi ', 'Di ', 'Fan ', 'Shen ', 'Zhe ', 'Shen ', 'Nu ', 'Xie ', 'Lei ', 'Xian ', 'Zi ', 'Ni ', 'Cun ', '[?] ', 'Qian ', 'Kume ', 'Bi ', 'Ban ', 'Wu ', 'Sha ', 'Kang ', 'Rou ', 'Fen ', 'Bi ', 'Cui ', '[?] ', 'Li ', 'Chi ', 'Nukamiso ', 'Ro ', 'Ba ', 'Li ', 'Gan ', 'Ju ', 'Po ', 'Mo ', 'Cu ', 'Nian ', 'Zhou ', 'Li ', 'Su ', 'Tiao ', 'Li ', 'Qi ', 'Su ', 'Hong ', 'Tong ', 'Zi ', 'Ce ', 'Yue ', 'Zhou ', 'Lin ', 'Zhuang ', 'Bai ', '[?] ', 'Fen ', 'Ji ', '[?] ', 'Sukumo ', 'Liang ', 'Xian ', 'Fu ', 'Liang ', 'Can ', 'Geng ', 'Li ', 'Yue ', 'Lu ', 'Ju ', 'Qi ', 'Cui ', 'Bai ', 'Zhang ', 'Lin ', 'Zong ', 'Jing ', 'Guo ', 'Kouji ', 'San ', 'San ', 'Tang ', 'Bian ', 'Rou ', 'Mian ', 'Hou ', 'Xu ', 'Zong ', 'Hu ', 'Jian ', 'Zan ', 'Ci ', 'Li ', 'Xie ', 'Fu ', 'Ni ', 'Bei ', 'Gu ', 'Xiu ', 'Gao ', 'Tang ', 'Qiu ', 'Sukumo ', 'Cao ', 'Zhuang ', 'Tang ', 'Mi ', 'San ', 'Fen ', 'Zao ', 'Kang ', 'Jiang ', 'Mo ', 'San ', 'San ', 'Nuo ', 'Xi ', 'Liang ', 'Jiang ', 'Kuai ', 'Bo ', 'Huan ', '[?] ', 'Zong ', 'Xian ', 'Nuo ', 'Tuan ', 'Nie ', 'Li ', 'Zuo ', 'Di ', 'Nie ', 'Tiao ', 'Lan ', 'Mi ', 'Jiao ', 'Jiu ', 'Xi ', 'Gong ', 'Zheng ', 'Jiu ', 'You '];
<?php return ['Yan ', 'Yan ', 'Ding ', 'Fu ', 'Qiu ', 'Qiu ', 'Jiao ', 'Hong ', 'Ji ', 'Fan ', 'Xun ', 'Diao ', 'Hong ', 'Cha ', 'Tao ', 'Xu ', 'Jie ', 'Yi ', 'Ren ', 'Xun ', 'Yin ', 'Shan ', 'Qi ', 'Tuo ', 'Ji ', 'Xun ', 'Yin ', 'E ', 'Fen ', 'Ya ', 'Yao ', 'Song ', 'Shen ', 'Yin ', 'Xin ', 'Jue ', 'Xiao ', 'Ne ', 'Chen ', 'You ', 'Zhi ', 'Xiong ', 'Fang ', 'Xin ', 'Chao ', 'She ', 'Xian ', 'Sha ', 'Tun ', 'Xu ', 'Yi ', 'Yi ', 'Su ', 'Chi ', 'He ', 'Shen ', 'He ', 'Xu ', 'Zhen ', 'Zhu ', 'Zheng ', 'Gou ', 'Zi ', 'Zi ', 'Zhan ', 'Gu ', 'Fu ', 'Quan ', 'Die ', 'Ling ', 'Di ', 'Yang ', 'Li ', 'Nao ', 'Pan ', 'Zhou ', 'Gan ', 'Yi ', 'Ju ', 'Ao ', 'Zha ', 'Tuo ', 'Yi ', 'Qu ', 'Zhao ', 'Ping ', 'Bi ', 'Xiong ', 'Qu ', 'Ba ', 'Da ', 'Zu ', 'Tao ', 'Zhu ', 'Ci ', 'Zhe ', 'Yong ', 'Xu ', 'Xun ', 'Yi ', 'Huang ', 'He ', 'Shi ', 'Cha ', 'Jiao ', 'Shi ', 'Hen ', 'Cha ', 'Gou ', 'Gui ', 'Quan ', 'Hui ', 'Jie ', 'Hua ', 'Gai ', 'Xiang ', 'Wei ', 'Shen ', 'Chou ', 'Tong ', 'Mi ', 'Zhan ', 'Ming ', 'E ', 'Hui ', 'Yan ', 'Xiong ', 'Gua ', 'Er ', 'Beng ', 'Tiao ', 'Chi ', 'Lei ', 'Zhu ', 'Kuang ', 'Kua ', 'Wu ', 'Yu ', 'Teng ', 'Ji ', 'Zhi ', 'Ren ', 'Su ', 'Lang ', 'E ', 'Kuang ', 'E ', 'Shi ', 'Ting ', 'Dan ', 'Bo ', 'Chan ', 'You ', 'Heng ', 'Qiao ', 'Qin ', 'Shua ', 'An ', 'Yu ', 'Xiao ', 'Cheng ', 'Jie ', 'Xian ', 'Wu ', 'Wu ', 'Gao ', 'Song ', 'Pu ', 'Hui ', 'Jing ', 'Shuo ', 'Zhen ', 'Shuo ', 'Du ', 'Yasashi ', 'Chang ', 'Shui ', 'Jie ', 'Ke ', 'Qu ', 'Cong ', 'Xiao ', 'Sui ', 'Wang ', 'Xuan ', 'Fei ', 'Chi ', 'Ta ', 'Yi ', 'Na ', 'Yin ', 'Diao ', 'Pi ', 'Chuo ', 'Chan ', 'Chen ', 'Zhun ', 'Ji ', 'Qi ', 'Tan ', 'Zhui ', 'Wei ', 'Ju ', 'Qing ', 'Jian ', 'Zheng ', 'Ze ', 'Zou ', 'Qian ', 'Zhuo ', 'Liang ', 'Jian ', 'Zhu ', 'Hao ', 'Lun ', 'Shen ', 'Biao ', 'Huai ', 'Pian ', 'Yu ', 'Die ', 'Xu ', 'Pian ', 'Shi ', 'Xuan ', 'Shi ', 'Hun ', 'Hua ', 'E ', 'Zhong ', 'Di ', 'Xie ', 'Fu ', 'Pu ', 'Ting ', 'Jian ', 'Qi ', 'Yu ', 'Zi ', 'Chuan ', 'Xi ', 'Hui ', 'Yin ', 'An ', 'Xian ', 'Nan ', 'Chen ', 'Feng ', 'Zhu ', 'Yang ', 'Yan ', 'Heng ', 'Xuan ', 'Ge ', 'Nuo ', 'Qi '];
<?php return ['[?]', 'e', 'aai', 'i', 'ii', 'o', 'oo', 'oo', 'ee', 'i', 'a', 'aa', 'we', 'we', 'wi', 'wi', 'wii', 'wii', 'wo', 'wo', 'woo', 'woo', 'woo', 'wa', 'wa', 'waa', 'waa', 'waa', 'ai', 'w', '\'', 't', 'k', 'sh', 's', 'n', 'w', 'n', '[?]', 'w', 'c', '?', 'l', 'en', 'in', 'on', 'an', 'pe', 'paai', 'pi', 'pii', 'po', 'poo', 'poo', 'hee', 'hi', 'pa', 'paa', 'pwe', 'pwe', 'pwi', 'pwi', 'pwii', 'pwii', 'pwo', 'pwo', 'pwoo', 'pwoo', 'pwa', 'pwa', 'pwaa', 'pwaa', 'pwaa', 'p', 'p', 'h', 'te', 'taai', 'ti', 'tii', 'to', 'too', 'too', 'dee', 'di', 'ta', 'taa', 'twe', 'twe', 'twi', 'twi', 'twii', 'twii', 'two', 'two', 'twoo', 'twoo', 'twa', 'twa', 'twaa', 'twaa', 'twaa', 't', 'tte', 'tti', 'tto', 'tta', 'ke', 'kaai', 'ki', 'kii', 'ko', 'koo', 'koo', 'ka', 'kaa', 'kwe', 'kwe', 'kwi', 'kwi', 'kwii', 'kwii', 'kwo', 'kwo', 'kwoo', 'kwoo', 'kwa', 'kwa', 'kwaa', 'kwaa', 'kwaa', 'k', 'kw', 'keh', 'kih', 'koh', 'kah', 'ce', 'caai', 'ci', 'cii', 'co', 'coo', 'coo', 'ca', 'caa', 'cwe', 'cwe', 'cwi', 'cwi', 'cwii', 'cwii', 'cwo', 'cwo', 'cwoo', 'cwoo', 'cwa', 'cwa', 'cwaa', 'cwaa', 'cwaa', 'c', 'th', 'me', 'maai', 'mi', 'mii', 'mo', 'moo', 'moo', 'ma', 'maa', 'mwe', 'mwe', 'mwi', 'mwi', 'mwii', 'mwii', 'mwo', 'mwo', 'mwoo', 'mwoo', 'mwa', 'mwa', 'mwaa', 'mwaa', 'mwaa', 'm', 'm', 'mh', 'm', 'm', 'ne', 'naai', 'ni', 'nii', 'no', 'noo', 'noo', 'na', 'naa', 'nwe', 'nwe', 'nwa', 'nwa', 'nwaa', 'nwaa', 'nwaa', 'n', 'ng', 'nh', 'le', 'laai', 'li', 'lii', 'lo', 'loo', 'loo', 'la', 'laa', 'lwe', 'lwe', 'lwi', 'lwi', 'lwii', 'lwii', 'lwo', 'lwo', 'lwoo', 'lwoo', 'lwa', 'lwa', 'lwaa', 'lwaa', 'l', 'l', 'l', 'se', 'saai', 'si', 'sii', 'so', 'soo', 'soo', 'sa', 'saa', 'swe', 'swe', 'swi', 'swi', 'swii', 'swii', 'swo', 'swo', 'swoo', 'swoo'];
<?php return ['Gui ', 'Deng ', 'Zhi ', 'Xu ', 'Yi ', 'Hua ', 'Xi ', 'Hui ', 'Rao ', 'Xi ', 'Yan ', 'Chan ', 'Jiao ', 'Mei ', 'Fan ', 'Fan ', 'Xian ', 'Yi ', 'Wei ', 'Jiao ', 'Fu ', 'Shi ', 'Bi ', 'Shan ', 'Sui ', 'Qiang ', 'Lian ', 'Huan ', 'Xin ', 'Niao ', 'Dong ', 'Yi ', 'Can ', 'Ai ', 'Niang ', 'Neng ', 'Ma ', 'Tiao ', 'Chou ', 'Jin ', 'Ci ', 'Yu ', 'Pin ', 'Yong ', 'Xu ', 'Nai ', 'Yan ', 'Tai ', 'Ying ', 'Can ', 'Niao ', 'Wo ', 'Ying ', 'Mian ', 'Kaka ', 'Ma ', 'Shen ', 'Xing ', 'Ni ', 'Du ', 'Liu ', 'Yuan ', 'Lan ', 'Yan ', 'Shuang ', 'Ling ', 'Jiao ', 'Niang ', 'Lan ', 'Xian ', 'Ying ', 'Shuang ', 'Shuai ', 'Quan ', 'Mi ', 'Li ', 'Luan ', 'Yan ', 'Zhu ', 'Lan ', 'Zi ', 'Jie ', 'Jue ', 'Jue ', 'Kong ', 'Yun ', 'Zi ', 'Zi ', 'Cun ', 'Sun ', 'Fu ', 'Bei ', 'Zi ', 'Xiao ', 'Xin ', 'Meng ', 'Si ', 'Tai ', 'Bao ', 'Ji ', 'Gu ', 'Nu ', 'Xue ', '[?] ', 'Zhuan ', 'Hai ', 'Luan ', 'Sun ', 'Huai ', 'Mie ', 'Cong ', 'Qian ', 'Shu ', 'Chan ', 'Ya ', 'Zi ', 'Ni ', 'Fu ', 'Zi ', 'Li ', 'Xue ', 'Bo ', 'Ru ', 'Lai ', 'Nie ', 'Nie ', 'Ying ', 'Luan ', 'Mian ', 'Zhu ', 'Rong ', 'Ta ', 'Gui ', 'Zhai ', 'Qiong ', 'Yu ', 'Shou ', 'An ', 'Tu ', 'Song ', 'Wan ', 'Rou ', 'Yao ', 'Hong ', 'Yi ', 'Jing ', 'Zhun ', 'Mi ', 'Zhu ', 'Dang ', 'Hong ', 'Zong ', 'Guan ', 'Zhou ', 'Ding ', 'Wan ', 'Yi ', 'Bao ', 'Shi ', 'Shi ', 'Chong ', 'Shen ', 'Ke ', 'Xuan ', 'Shi ', 'You ', 'Huan ', 'Yi ', 'Tiao ', 'Shi ', 'Xian ', 'Gong ', 'Cheng ', 'Qun ', 'Gong ', 'Xiao ', 'Zai ', 'Zha ', 'Bao ', 'Hai ', 'Yan ', 'Xiao ', 'Jia ', 'Shen ', 'Chen ', 'Rong ', 'Huang ', 'Mi ', 'Kou ', 'Kuan ', 'Bin ', 'Su ', 'Cai ', 'Zan ', 'Ji ', 'Yuan ', 'Ji ', 'Yin ', 'Mi ', 'Kou ', 'Qing ', 'Que ', 'Zhen ', 'Jian ', 'Fu ', 'Ning ', 'Bing ', 'Huan ', 'Mei ', 'Qin ', 'Han ', 'Yu ', 'Shi ', 'Ning ', 'Qin ', 'Ning ', 'Zhi ', 'Yu ', 'Bao ', 'Kuan ', 'Ning ', 'Qin ', 'Mo ', 'Cha ', 'Ju ', 'Gua ', 'Qin ', 'Hu ', 'Wu ', 'Liao ', 'Shi ', 'Zhu ', 'Zhai ', 'Shen ', 'Wei ', 'Xie ', 'Kuan ', 'Hui ', 'Liao ', 'Jun ', 'Huan ', 'Yi ', 'Yi ', 'Bao ', 'Qin ', 'Chong ', 'Bao ', 'Feng ', 'Cun ', 'Dui ', 'Si ', 'Xun ', 'Dao ', 'Lu ', 'Dui ', 'Shou '];
<?php return ['0.', '0,', '1,', '2,', '3,', '4,', '5,', '6,', '7,', '8,', '9,', '', '', '', '', '', '(A)', '(B)', '(C)', '(D)', '(E)', '(F)', '(G)', '(H)', '(I)', '(J)', '(K)',   // 0x1a
    '(L)', '(M)', '(N)', '(O)', '(P)', '(Q)', '(R)', '(S)', '(T)', '(U)', '(V)', '(W)', '(X)', '(Y)', '(Z)', 48 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 80 => 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 112 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 230 => 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ];
<?php return ['Ku ', 'Ke ', 'Tang ', 'Kun ', 'Ni ', 'Jian ', 'Dui ', 'Jin ', 'Gang ', 'Yu ', 'E ', 'Peng ', 'Gu ', 'Tu ', 'Leng ', '[?] ', 'Ya ', 'Qian ', '[?] ', 'An ', '[?] ', 'Duo ', 'Nao ', 'Tu ', 'Cheng ', 'Yin ', 'Hun ', 'Bi ', 'Lian ', 'Guo ', 'Die ', 'Zhuan ', 'Hou ', 'Bao ', 'Bao ', 'Yu ', 'Di ', 'Mao ', 'Jie ', 'Ruan ', 'E ', 'Geng ', 'Kan ', 'Zong ', 'Yu ', 'Huang ', 'E ', 'Yao ', 'Yan ', 'Bao ', 'Ji ', 'Mei ', 'Chang ', 'Du ', 'Tuo ', 'Yin ', 'Feng ', 'Zhong ', 'Jie ', 'Zhen ', 'Feng ', 'Gang ', 'Chuan ', 'Jian ', 'Pyeng ', 'Toride ', 'Xiang ', 'Huang ', 'Leng ', 'Duan ', '[?] ', 'Xuan ', 'Ji ', 'Ji ', 'Kuai ', 'Ying ', 'Ta ', 'Cheng ', 'Yong ', 'Kai ', 'Su ', 'Su ', 'Shi ', 'Mi ', 'Ta ', 'Weng ', 'Cheng ', 'Tu ', 'Tang ', 'Que ', 'Zhong ', 'Li ', 'Peng ', 'Bang ', 'Sai ', 'Zang ', 'Dui ', 'Tian ', 'Wu ', 'Cheng ', 'Xun ', 'Ge ', 'Zhen ', 'Ai ', 'Gong ', 'Yan ', 'Kan ', 'Tian ', 'Yuan ', 'Wen ', 'Xie ', 'Liu ', 'Ama ', 'Lang ', 'Chang ', 'Peng ', 'Beng ', 'Chen ', 'Cu ', 'Lu ', 'Ou ', 'Qian ', 'Mei ', 'Mo ', 'Zhuan ', 'Shuang ', 'Shu ', 'Lou ', 'Chi ', 'Man ', 'Biao ', 'Jing ', 'Qi ', 'Shu ', 'Di ', 'Zhang ', 'Kan ', 'Yong ', 'Dian ', 'Chen ', 'Zhi ', 'Xi ', 'Guo ', 'Qiang ', 'Jin ', 'Di ', 'Shang ', 'Mu ', 'Cui ', 'Yan ', 'Ta ', 'Zeng ', 'Qi ', 'Qiang ', 'Liang ', '[?] ', 'Zhui ', 'Qiao ', 'Zeng ', 'Xu ', 'Shan ', 'Shan ', 'Ba ', 'Pu ', 'Kuai ', 'Dong ', 'Fan ', 'Que ', 'Mo ', 'Dun ', 'Dun ', 'Dun ', 'Di ', 'Sheng ', 'Duo ', 'Duo ', 'Tan ', 'Deng ', 'Wu ', 'Fen ', 'Huang ', 'Tan ', 'Da ', 'Ye ', 'Sho ', 'Mama ', 'Yu ', 'Qiang ', 'Ji ', 'Qiao ', 'Ken ', 'Yi ', 'Pi ', 'Bi ', 'Dian ', 'Jiang ', 'Ye ', 'Yong ', 'Bo ', 'Tan ', 'Lan ', 'Ju ', 'Huai ', 'Dang ', 'Rang ', 'Qian ', 'Xun ', 'Lan ', 'Xi ', 'He ', 'Ai ', 'Ya ', 'Dao ', 'Hao ', 'Ruan ', 'Mama ', 'Lei ', 'Kuang ', 'Lu ', 'Yan ', 'Tan ', 'Wei ', 'Huai ', 'Long ', 'Long ', 'Rui ', 'Li ', 'Lin ', 'Rang ', 'Ten ', 'Xun ', 'Yan ', 'Lei ', 'Ba ', '[?] ', 'Shi ', 'Ren ', '[?] ', 'Zhuang ', 'Zhuang ', 'Sheng ', 'Yi ', 'Mai ', 'Ke ', 'Zhu ', 'Zhuang ', 'Hu ', 'Hu ', 'Kun ', 'Yi ', 'Hu ', 'Xu ', 'Kun ', 'Shou ', 'Mang ', 'Zun '];
<?php return ['You ', 'Yang ', 'Lu ', 'Si ', 'Jie ', 'Ying ', 'Du ', 'Wang ', 'Hui ', 'Xie ', 'Pan ', 'Shen ', 'Biao ', 'Chan ', 'Mo ', 'Liu ', 'Jian ', 'Pu ', 'Se ', 'Cheng ', 'Gu ', 'Bin ', 'Huo ', 'Xian ', 'Lu ', 'Qin ', 'Han ', 'Ying ', 'Yong ', 'Li ', 'Jing ', 'Xiao ', 'Ying ', 'Sui ', 'Wei ', 'Xie ', 'Huai ', 'Hao ', 'Zhu ', 'Long ', 'Lai ', 'Dui ', 'Fan ', 'Hu ', 'Lai ', '[?] ', '[?] ', 'Ying ', 'Mi ', 'Ji ', 'Lian ', 'Jian ', 'Ying ', 'Fen ', 'Lin ', 'Yi ', 'Jian ', 'Yue ', 'Chan ', 'Dai ', 'Rang ', 'Jian ', 'Lan ', 'Fan ', 'Shuang ', 'Yuan ', 'Zhuo ', 'Feng ', 'She ', 'Lei ', 'Lan ', 'Cong ', 'Qu ', 'Yong ', 'Qian ', 'Fa ', 'Guan ', 'Que ', 'Yan ', 'Hao ', 'Hyeng ', 'Sa ', 'Zan ', 'Luan ', 'Yan ', 'Li ', 'Mi ', 'Shan ', 'Tan ', 'Dang ', 'Jiao ', 'Chan ', '[?] ', 'Hao ', 'Ba ', 'Zhu ', 'Lan ', 'Lan ', 'Nang ', 'Wan ', 'Luan ', 'Xun ', 'Xian ', 'Yan ', 'Gan ', 'Yan ', 'Yu ', 'Huo ', 'Si ', 'Mie ', 'Guang ', 'Deng ', 'Hui ', 'Xiao ', 'Xiao ', 'Hu ', 'Hong ', 'Ling ', 'Zao ', 'Zhuan ', 'Jiu ', 'Zha ', 'Xie ', 'Chi ', 'Zhuo ', 'Zai ', 'Zai ', 'Can ', 'Yang ', 'Qi ', 'Zhong ', 'Fen ', 'Niu ', 'Jiong ', 'Wen ', 'Po ', 'Yi ', 'Lu ', 'Chui ', 'Pi ', 'Kai ', 'Pan ', 'Yan ', 'Kai ', 'Pang ', 'Mu ', 'Chao ', 'Liao ', 'Gui ', 'Kang ', 'Tun ', 'Guang ', 'Xin ', 'Zhi ', 'Guang ', 'Guang ', 'Wei ', 'Qiang ', '[?] ', 'Da ', 'Xia ', 'Zheng ', 'Zhu ', 'Ke ', 'Zhao ', 'Fu ', 'Ba ', 'Duo ', 'Duo ', 'Ling ', 'Zhuo ', 'Xuan ', 'Ju ', 'Tan ', 'Pao ', 'Jiong ', 'Pao ', 'Tai ', 'Tai ', 'Bing ', 'Yang ', 'Tong ', 'Han ', 'Zhu ', 'Zha ', 'Dian ', 'Wei ', 'Shi ', 'Lian ', 'Chi ', 'Huang ', '[?] ', 'Hu ', 'Shuo ', 'Lan ', 'Jing ', 'Jiao ', 'Xu ', 'Xing ', 'Quan ', 'Lie ', 'Huan ', 'Yang ', 'Xiao ', 'Xiu ', 'Xian ', 'Yin ', 'Wu ', 'Zhou ', 'Yao ', 'Shi ', 'Wei ', 'Tong ', 'Xue ', 'Zai ', 'Kai ', 'Hong ', 'Luo ', 'Xia ', 'Zhu ', 'Xuan ', 'Zheng ', 'Po ', 'Yan ', 'Hui ', 'Guang ', 'Zhe ', 'Hui ', 'Kao ', '[?] ', 'Fan ', 'Shao ', 'Ye ', 'Hui ', '[?] ', 'Tang ', 'Jin ', 'Re ', '[?] ', 'Xi ', 'Fu ', 'Jiong ', 'Che ', 'Pu ', 'Jing ', 'Zhuo ', 'Ting ', 'Wan ', 'Hai ', 'Peng ', 'Lang ', 'Shan ', 'Hu ', 'Feng ', 'Chi ', 'Rong '];
<?php return ['g', 'gg', 'n', 'd', 'dd', 'r', 'm', 'b', 'bb', 's', 'ss', '', 'j', 'jj', 'c', 'k', 't', 'p', 'h', 'ng', 'nn', 'nd', 'nb', 'dg', 'rn', 'rr', 'rh', 'rN', 'mb', 'mN', 'bg', 'bn', '', 'bs', 'bsg', 'bst', 'bsb', 'bss', 'bsj', 'bj', 'bc', 'bt', 'bp', 'bN', 'bbN', 'sg', 'sn', 'sd', 'sr', 'sm', 'sb', 'sbg', 'sss', 's', 'sj', 'sc', 'sk', 'st', 'sp', 'sh', '', '', '', '', 'Z', 'g', 'd', 'm', 'b', 's', 'Z', '', 'j', 'c', 't', 'p', 'N', 'j', '', '', '', '', 'ck', 'ch', '', '', 'pb', 'pN', 'hh', 'Q', '[?]', '[?]', '[?]', '[?]', '[?]', '', '', 'a', 'ae', 'ya', 'yae', 'eo', 'e', 'yeo', 'ye', 'o', 'wa', 'wae', 'oe', 'yo', 'u', 'weo', 'we', 'wi', 'yu', 'eu', 'yi', 'i', 'a-o', 'a-u', 'ya-o', 'ya-yo', 'eo-o', 'eo-u', 'eo-eu', 'yeo-o', 'yeo-u', 'o-eo', 'o-e', 'o-ye', 'o-o', 'o-u', 'yo-ya', 'yo-yae', 'yo-yeo', 'yo-o', 'yo-i', 'u-a', 'u-ae', 'u-eo-eu', 'u-ye', 'u-u', 'yu-a', 'yu-eo', 'yu-e', 'yu-yeo', 'yu-ye', 'yu-u', 'yu-i', 'eu-u', 'eu-eu', 'yi-u', 'i-a', 'i-ya', 'i-o', 'i-u', 'i-eu', 'i-U', 'U', 'U-eo', 'U-u', 'U-i', 'UU', '[?]', '[?]', '[?]', '[?]', '[?]', 'g', 'gg', 'gs', 'n', 'nj', 'nh', 'd', 'l', 'lg', 'lm', 'lb', 'ls', 'lt', 'lp', 'lh', 'm', 'b', 'bs', 's', 'ss', 'ng', 'j', 'c', 'k', 't', 'p', 'h', 'gl', 'gsg', 'ng', 'nd', 'ns', 'nZ', 'nt', 'dg', 'tl', 'lgs', 'ln', 'ld', 'lth', 'll', 'lmg', 'lms', 'lbs', 'lbh', 'rNp', 'lss', 'lZ', 'lk', 'lQ', 'mg', 'ml', 'mb', 'ms', 'mss', 'mZ', 'mc', 'mh', 'mN', 'bl', 'bp', 'ph', 'pN', 'sg', 'sd', 'sl', 'sb', 'Z', 'g', 'ss', '', 'kh', 'N', 'Ns', 'NZ', 'pb', 'pN', 'hn', 'hl', 'hm', 'hb', 'Q', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['E ', 'Cheng ', 'Xin ', 'Ai ', 'Lu ', 'Zhui ', 'Zhou ', 'She ', 'Pian ', 'Kun ', 'Tao ', 'Lai ', 'Zong ', 'Ke ', 'Qi ', 'Qi ', 'Yan ', 'Fei ', 'Sao ', 'Yan ', 'Jie ', 'Yao ', 'Wu ', 'Pian ', 'Cong ', 'Pian ', 'Qian ', 'Fei ', 'Huang ', 'Jian ', 'Huo ', 'Yu ', 'Ti ', 'Quan ', 'Xia ', 'Zong ', 'Kui ', 'Rou ', 'Si ', 'Gua ', 'Tuo ', 'Kui ', 'Sou ', 'Qian ', 'Cheng ', 'Zhi ', 'Liu ', 'Pang ', 'Teng ', 'Xi ', 'Cao ', 'Du ', 'Yan ', 'Yuan ', 'Zou ', 'Sao ', 'Shan ', 'Li ', 'Zhi ', 'Shuang ', 'Lu ', 'Xi ', 'Luo ', 'Zhang ', 'Mo ', 'Ao ', 'Can ', 'Piao ', 'Cong ', 'Qu ', 'Bi ', 'Zhi ', 'Yu ', 'Xu ', 'Hua ', 'Bo ', 'Su ', 'Xiao ', 'Lin ', 'Chan ', 'Dun ', 'Liu ', 'Tuo ', 'Zeng ', 'Tan ', 'Jiao ', 'Tie ', 'Yan ', 'Luo ', 'Zhan ', 'Jing ', 'Yi ', 'Ye ', 'Tuo ', 'Bin ', 'Zou ', 'Yan ', 'Peng ', 'Lu ', 'Teng ', 'Xiang ', 'Ji ', 'Shuang ', 'Ju ', 'Xi ', 'Huan ', 'Li ', 'Biao ', 'Ma ', 'Yu ', 'Tuo ', 'Xun ', 'Chi ', 'Qu ', 'Ri ', 'Bo ', 'Lu ', 'Zang ', 'Shi ', 'Si ', 'Fu ', 'Ju ', 'Zou ', 'Zhu ', 'Tuo ', 'Nu ', 'Jia ', 'Yi ', 'Tai ', 'Xiao ', 'Ma ', 'Yin ', 'Jiao ', 'Hua ', 'Luo ', 'Hai ', 'Pian ', 'Biao ', 'Li ', 'Cheng ', 'Yan ', 'Xin ', 'Qin ', 'Jun ', 'Qi ', 'Qi ', 'Ke ', 'Zhui ', 'Zong ', 'Su ', 'Can ', 'Pian ', 'Zhi ', 'Kui ', 'Sao ', 'Wu ', 'Ao ', 'Liu ', 'Qian ', 'Shan ', 'Piao ', 'Luo ', 'Cong ', 'Chan ', 'Zou ', 'Ji ', 'Shuang ', 'Xiang ', 'Gu ', 'Wei ', 'Wei ', 'Wei ', 'Yu ', 'Gan ', 'Yi ', 'Ang ', 'Tou ', 'Xie ', 'Bao ', 'Bi ', 'Chi ', 'Ti ', 'Di ', 'Ku ', 'Hai ', 'Qiao ', 'Gou ', 'Kua ', 'Ge ', 'Tui ', 'Geng ', 'Pian ', 'Bi ', 'Ke ', 'Ka ', 'Yu ', 'Sui ', 'Lou ', 'Bo ', 'Xiao ', 'Pang ', 'Bo ', 'Ci ', 'Kuan ', 'Bin ', 'Mo ', 'Liao ', 'Lou ', 'Nao ', 'Du ', 'Zang ', 'Sui ', 'Ti ', 'Bin ', 'Kuan ', 'Lu ', 'Gao ', 'Gao ', 'Qiao ', 'Kao ', 'Qiao ', 'Lao ', 'Zao ', 'Biao ', 'Kun ', 'Kun ', 'Ti ', 'Fang ', 'Xiu ', 'Ran ', 'Mao ', 'Dan ', 'Kun ', 'Bin ', 'Fa ', 'Tiao ', 'Peng ', 'Zi ', 'Fa ', 'Ran ', 'Ti ', 'Pao ', 'Pi ', 'Mao ', 'Fu ', 'Er ', 'Rong ', 'Qu ', 'Gong ', 'Xiu ', 'Gua ', 'Ji ', 'Peng ', 'Zhua ', 'Shao ', 'Sha '];
<?php return ['it', 'ix', 'i', 'ip', 'iet', 'iex', 'ie', 'iep', 'at', 'ax', 'a', 'ap', 'uox', 'uo', 'uop', 'ot', 'ox', 'o', 'op', 'ex', 'e', 'wu', 'bit', 'bix', 'bi', 'bip', 'biet', 'biex', 'bie', 'biep', 'bat', 'bax', 'ba', 'bap', 'buox', 'buo', 'buop', 'bot', 'box', 'bo', 'bop', 'bex', 'be', 'bep', 'but', 'bux', 'bu', 'bup', 'burx', 'bur', 'byt', 'byx', 'by', 'byp', 'byrx', 'byr', 'pit', 'pix', 'pi', 'pip', 'piex', 'pie', 'piep', 'pat', 'pax', 'pa', 'pap', 'puox', 'puo', 'puop', 'pot', 'pox', 'po', 'pop', 'put', 'pux', 'pu', 'pup', 'purx', 'pur', 'pyt', 'pyx', 'py', 'pyp', 'pyrx', 'pyr', 'bbit', 'bbix', 'bbi', 'bbip', 'bbiet', 'bbiex', 'bbie', 'bbiep', 'bbat', 'bbax', 'bba', 'bbap', 'bbuox', 'bbuo', 'bbuop', 'bbot', 'bbox', 'bbo', 'bbop', 'bbex', 'bbe', 'bbep', 'bbut', 'bbux', 'bbu', 'bbup', 'bburx', 'bbur', 'bbyt', 'bbyx', 'bby', 'bbyp', 'nbit', 'nbix', 'nbi', 'nbip', 'nbiex', 'nbie', 'nbiep', 'nbat', 'nbax', 'nba', 'nbap', 'nbot', 'nbox', 'nbo', 'nbop', 'nbut', 'nbux', 'nbu', 'nbup', 'nburx', 'nbur', 'nbyt', 'nbyx', 'nby', 'nbyp', 'nbyrx', 'nbyr', 'hmit', 'hmix', 'hmi', 'hmip', 'hmiex', 'hmie', 'hmiep', 'hmat', 'hmax', 'hma', 'hmap', 'hmuox', 'hmuo', 'hmuop', 'hmot', 'hmox', 'hmo', 'hmop', 'hmut', 'hmux', 'hmu', 'hmup', 'hmurx', 'hmur', 'hmyx', 'hmy', 'hmyp', 'hmyrx', 'hmyr', 'mit', 'mix', 'mi', 'mip', 'miex', 'mie', 'miep', 'mat', 'max', 'ma', 'map', 'muot', 'muox', 'muo', 'muop', 'mot', 'mox', 'mo', 'mop', 'mex', 'me', 'mut', 'mux', 'mu', 'mup', 'murx', 'mur', 'myt', 'myx', 'my', 'myp', 'fit', 'fix', 'fi', 'fip', 'fat', 'fax', 'fa', 'fap', 'fox', 'fo', 'fop', 'fut', 'fux', 'fu', 'fup', 'furx', 'fur', 'fyt', 'fyx', 'fy', 'fyp', 'vit', 'vix', 'vi', 'vip', 'viet', 'viex', 'vie', 'viep', 'vat', 'vax', 'va', 'vap', 'vot', 'vox', 'vo', 'vop', 'vex', 'vep', 'vut', 'vux', 'vu', 'vup', 'vurx', 'vur', 'vyt', 'vyx', 'vy', 'vyp', 'vyrx', 'vyr'];
<?php return ['Lian ', 'Nan ', 'Mi ', 'Tang ', 'Jue ', 'Gang ', 'Gang ', 'Gang ', 'Ge ', 'Yue ', 'Wu ', 'Jian ', 'Xu ', 'Shu ', 'Rong ', 'Xi ', 'Cheng ', 'Wo ', 'Jie ', 'Ge ', 'Jian ', 'Qiang ', 'Huo ', 'Qiang ', 'Zhan ', 'Dong ', 'Qi ', 'Jia ', 'Die ', 'Zei ', 'Jia ', 'Ji ', 'Shi ', 'Kan ', 'Ji ', 'Kui ', 'Gai ', 'Deng ', 'Zhan ', 'Chuang ', 'Ge ', 'Jian ', 'Jie ', 'Yu ', 'Jian ', 'Yan ', 'Lu ', 'Xi ', 'Zhan ', 'Xi ', 'Xi ', 'Chuo ', 'Dai ', 'Qu ', 'Hu ', 'Hu ', 'Hu ', 'E ', 'Shi ', 'Li ', 'Mao ', 'Hu ', 'Li ', 'Fang ', 'Suo ', 'Bian ', 'Dian ', 'Jiong ', 'Shang ', 'Yi ', 'Yi ', 'Shan ', 'Hu ', 'Fei ', 'Yan ', 'Shou ', 'T ', 'Cai ', 'Zha ', 'Qiu ', 'Le ', 'Bu ', 'Ba ', 'Da ', 'Reng ', 'Fu ', 'Hameru ', 'Zai ', 'Tuo ', 'Zhang ', 'Diao ', 'Kang ', 'Yu ', 'Ku ', 'Han ', 'Shen ', 'Cha ', 'Yi ', 'Gu ', 'Kou ', 'Wu ', 'Tuo ', 'Qian ', 'Zhi ', 'Ren ', 'Kuo ', 'Men ', 'Sao ', 'Yang ', 'Niu ', 'Ban ', 'Che ', 'Rao ', 'Xi ', 'Qian ', 'Ban ', 'Jia ', 'Yu ', 'Fu ', 'Ao ', 'Xi ', 'Pi ', 'Zhi ', 'Zi ', 'E ', 'Dun ', 'Zhao ', 'Cheng ', 'Ji ', 'Yan ', 'Kuang ', 'Bian ', 'Chao ', 'Ju ', 'Wen ', 'Hu ', 'Yue ', 'Jue ', 'Ba ', 'Qin ', 'Zhen ', 'Zheng ', 'Yun ', 'Wan ', 'Nu ', 'Yi ', 'Shu ', 'Zhua ', 'Pou ', 'Tou ', 'Dou ', 'Kang ', 'Zhe ', 'Pou ', 'Fu ', 'Pao ', 'Ba ', 'Ao ', 'Ze ', 'Tuan ', 'Kou ', 'Lun ', 'Qiang ', '[?] ', 'Hu ', 'Bao ', 'Bing ', 'Zhi ', 'Peng ', 'Tan ', 'Pu ', 'Pi ', 'Tai ', 'Yao ', 'Zhen ', 'Zha ', 'Yang ', 'Bao ', 'He ', 'Ni ', 'Yi ', 'Di ', 'Chi ', 'Pi ', 'Za ', 'Mo ', 'Mo ', 'Shen ', 'Ya ', 'Chou ', 'Qu ', 'Min ', 'Chu ', 'Jia ', 'Fu ', 'Zhan ', 'Zhu ', 'Dan ', 'Chai ', 'Mu ', 'Nian ', 'La ', 'Fu ', 'Pao ', 'Ban ', 'Pai ', 'Ling ', 'Na ', 'Guai ', 'Qian ', 'Ju ', 'Tuo ', 'Ba ', 'Tuo ', 'Tuo ', 'Ao ', 'Ju ', 'Zhuo ', 'Pan ', 'Zhao ', 'Bai ', 'Bai ', 'Di ', 'Ni ', 'Ju ', 'Kuo ', 'Long ', 'Jian ', '[?] ', 'Yong ', 'Lan ', 'Ning ', 'Bo ', 'Ze ', 'Qian ', 'Hen ', 'Gua ', 'Shi ', 'Jie ', 'Zheng ', 'Nin ', 'Gong ', 'Gong ', 'Quan ', 'Shuan ', 'Cun ', 'Zan ', 'Kao ', 'Chi ', 'Xie ', 'Ce ', 'Hui ', 'Pin ', 'Zhuai ', 'Shi ', 'Na '];
<?php return ['mya', 'myag', 'myagg', 'myags', 'myan', 'myanj', 'myanh', 'myad', 'myal', 'myalg', 'myalm', 'myalb', 'myals', 'myalt', 'myalp', 'myalh', 'myam', 'myab', 'myabs', 'myas', 'myass', 'myang', 'myaj', 'myac', 'myak', 'myat', 'myap', 'myah', 'myae', 'myaeg', 'myaegg', 'myaegs', 'myaen', 'myaenj', 'myaenh', 'myaed', 'myael', 'myaelg', 'myaelm', 'myaelb', 'myaels', 'myaelt', 'myaelp', 'myaelh', 'myaem', 'myaeb', 'myaebs', 'myaes', 'myaess', 'myaeng', 'myaej', 'myaec', 'myaek', 'myaet', 'myaep', 'myaeh', 'meo', 'meog', 'meogg', 'meogs', 'meon', 'meonj', 'meonh', 'meod', 'meol', 'meolg', 'meolm', 'meolb', 'meols', 'meolt', 'meolp', 'meolh', 'meom', 'meob', 'meobs', 'meos', 'meoss', 'meong', 'meoj', 'meoc', 'meok', 'meot', 'meop', 'meoh', 'me', 'meg', 'megg', 'megs', 'men', 'menj', 'menh', 'med', 'mel', 'melg', 'melm', 'melb', 'mels', 'melt', 'melp', 'melh', 'mem', 'meb', 'mebs', 'mes', 'mess', 'meng', 'mej', 'mec', 'mek', 'met', 'mep', 'meh', 'myeo', 'myeog', 'myeogg', 'myeogs', 'myeon', 'myeonj', 'myeonh', 'myeod', 'myeol', 'myeolg', 'myeolm', 'myeolb', 'myeols', 'myeolt', 'myeolp', 'myeolh', 'myeom', 'myeob', 'myeobs', 'myeos', 'myeoss', 'myeong', 'myeoj', 'myeoc', 'myeok', 'myeot', 'myeop', 'myeoh', 'mye', 'myeg', 'myegg', 'myegs', 'myen', 'myenj', 'myenh', 'myed', 'myel', 'myelg', 'myelm', 'myelb', 'myels', 'myelt', 'myelp', 'myelh', 'myem', 'myeb', 'myebs', 'myes', 'myess', 'myeng', 'myej', 'myec', 'myek', 'myet', 'myep', 'myeh', 'mo', 'mog', 'mogg', 'mogs', 'mon', 'monj', 'monh', 'mod', 'mol', 'molg', 'molm', 'molb', 'mols', 'molt', 'molp', 'molh', 'mom', 'mob', 'mobs', 'mos', 'moss', 'mong', 'moj', 'moc', 'mok', 'mot', 'mop', 'moh', 'mwa', 'mwag', 'mwagg', 'mwags', 'mwan', 'mwanj', 'mwanh', 'mwad', 'mwal', 'mwalg', 'mwalm', 'mwalb', 'mwals', 'mwalt', 'mwalp', 'mwalh', 'mwam', 'mwab', 'mwabs', 'mwas', 'mwass', 'mwang', 'mwaj', 'mwac', 'mwak', 'mwat', 'mwap', 'mwah', 'mwae', 'mwaeg', 'mwaegg', 'mwaegs', 'mwaen', 'mwaenj', 'mwaenh', 'mwaed', 'mwael', 'mwaelg', 'mwaelm', 'mwaelb', 'mwaels', 'mwaelt', 'mwaelp', 'mwaelh', 'mwaem', 'mwaeb', 'mwaebs', 'mwaes', 'mwaess', 'mwaeng', 'mwaej', 'mwaec', 'mwaek', 'mwaet', 'mwaep', 'mwaeh', 'moe', 'moeg', 'moegg', 'moegs'];
<?php return ['yeoss', 'yeong', 'yeoj', 'yeoc', 'yeok', 'yeot', 'yeop', 'yeoh', 'ye', 'yeg', 'yegg', 'yegs', 'yen', 'yenj', 'yenh', 'yed', 'yel', 'yelg', 'yelm', 'yelb', 'yels', 'yelt', 'yelp', 'yelh', 'yem', 'yeb', 'yebs', 'yes', 'yess', 'yeng', 'yej', 'yec', 'yek', 'yet', 'yep', 'yeh', 'o', 'og', 'ogg', 'ogs', 'on', 'onj', 'onh', 'od', 'ol', 'olg', 'olm', 'olb', 'ols', 'olt', 'olp', 'olh', 'om', 'ob', 'obs', 'os', 'oss', 'ong', 'oj', 'oc', 'ok', 'ot', 'op', 'oh', 'wa', 'wag', 'wagg', 'wags', 'wan', 'wanj', 'wanh', 'wad', 'wal', 'walg', 'walm', 'walb', 'wals', 'walt', 'walp', 'walh', 'wam', 'wab', 'wabs', 'was', 'wass', 'wang', 'waj', 'wac', 'wak', 'wat', 'wap', 'wah', 'wae', 'waeg', 'waegg', 'waegs', 'waen', 'waenj', 'waenh', 'waed', 'wael', 'waelg', 'waelm', 'waelb', 'waels', 'waelt', 'waelp', 'waelh', 'waem', 'waeb', 'waebs', 'waes', 'waess', 'waeng', 'waej', 'waec', 'waek', 'waet', 'waep', 'waeh', 'oe', 'oeg', 'oegg', 'oegs', 'oen', 'oenj', 'oenh', 'oed', 'oel', 'oelg', 'oelm', 'oelb', 'oels', 'oelt', 'oelp', 'oelh', 'oem', 'oeb', 'oebs', 'oes', 'oess', 'oeng', 'oej', 'oec', 'oek', 'oet', 'oep', 'oeh', 'yo', 'yog', 'yogg', 'yogs', 'yon', 'yonj', 'yonh', 'yod', 'yol', 'yolg', 'yolm', 'yolb', 'yols', 'yolt', 'yolp', 'yolh', 'yom', 'yob', 'yobs', 'yos', 'yoss', 'yong', 'yoj', 'yoc', 'yok', 'yot', 'yop', 'yoh', 'u', 'ug', 'ugg', 'ugs', 'un', 'unj', 'unh', 'ud', 'ul', 'ulg', 'ulm', 'ulb', 'uls', 'ult', 'ulp', 'ulh', 'um', 'ub', 'ubs', 'us', 'uss', 'ung', 'uj', 'uc', 'uk', 'ut', 'up', 'uh', 'weo', 'weog', 'weogg', 'weogs', 'weon', 'weonj', 'weonh', 'weod', 'weol', 'weolg', 'weolm', 'weolb', 'weols', 'weolt', 'weolp', 'weolh', 'weom', 'weob', 'weobs', 'weos', 'weoss', 'weong', 'weoj', 'weoc', 'weok', 'weot', 'weop', 'weoh', 'we', 'weg', 'wegg', 'wegs', 'wen', 'wenj', 'wenh', 'wed', 'wel', 'welg', 'welm', 'welb', 'wels', 'welt', 'welp', 'welh', 'wem', 'web', 'webs', 'wes', 'wess', 'weng', 'wej', 'wec'];
<?php return ['Qing ', 'Yu ', 'Piao ', 'Ji ', 'Ya ', 'Jiao ', 'Qi ', 'Xi ', 'Ji ', 'Lu ', 'Lu ', 'Long ', 'Jin ', 'Guo ', 'Cong ', 'Lou ', 'Zhi ', 'Gai ', 'Qiang ', 'Li ', 'Yan ', 'Cao ', 'Jiao ', 'Cong ', 'Qun ', 'Tuan ', 'Ou ', 'Teng ', 'Ye ', 'Xi ', 'Mi ', 'Tang ', 'Mo ', 'Shang ', 'Han ', 'Lian ', 'Lan ', 'Wa ', 'Li ', 'Qian ', 'Feng ', 'Xuan ', 'Yi ', 'Man ', 'Zi ', 'Mang ', 'Kang ', 'Lei ', 'Peng ', 'Shu ', 'Zhang ', 'Zhang ', 'Chong ', 'Xu ', 'Huan ', 'Kuo ', 'Jian ', 'Yan ', 'Chuang ', 'Liao ', 'Cui ', 'Ti ', 'Yang ', 'Jiang ', 'Cong ', 'Ying ', 'Hong ', 'Xun ', 'Shu ', 'Guan ', 'Ying ', 'Xiao ', '[?] ', '[?] ', 'Xu ', 'Lian ', 'Zhi ', 'Wei ', 'Pi ', 'Jue ', 'Jiao ', 'Po ', 'Dang ', 'Hui ', 'Jie ', 'Wu ', 'Pa ', 'Ji ', 'Pan ', 'Gui ', 'Xiao ', 'Qian ', 'Qian ', 'Xi ', 'Lu ', 'Xi ', 'Xuan ', 'Dun ', 'Huang ', 'Min ', 'Run ', 'Su ', 'Liao ', 'Zhen ', 'Zhong ', 'Yi ', 'Di ', 'Wan ', 'Dan ', 'Tan ', 'Chao ', 'Xun ', 'Kui ', 'Yie ', 'Shao ', 'Tu ', 'Zhu ', 'San ', 'Hei ', 'Bi ', 'Shan ', 'Chan ', 'Chan ', 'Shu ', 'Tong ', 'Pu ', 'Lin ', 'Wei ', 'Se ', 'Se ', 'Cheng ', 'Jiong ', 'Cheng ', 'Hua ', 'Jiao ', 'Lao ', 'Che ', 'Gan ', 'Cun ', 'Heng ', 'Si ', 'Shu ', 'Peng ', 'Han ', 'Yun ', 'Liu ', 'Hong ', 'Fu ', 'Hao ', 'He ', 'Xian ', 'Jian ', 'Shan ', 'Xi ', 'Oki ', '[?] ', 'Lan ', '[?] ', 'Yu ', 'Lin ', 'Min ', 'Zao ', 'Dang ', 'Wan ', 'Ze ', 'Xie ', 'Yu ', 'Li ', 'Shi ', 'Xue ', 'Ling ', 'Man ', 'Zi ', 'Yong ', 'Kuai ', 'Can ', 'Lian ', 'Dian ', 'Ye ', 'Ao ', 'Huan ', 'Zhen ', 'Chan ', 'Man ', 'Dan ', 'Dan ', 'Yi ', 'Sui ', 'Pi ', 'Ju ', 'Ta ', 'Qin ', 'Ji ', 'Zhuo ', 'Lian ', 'Nong ', 'Guo ', 'Jin ', 'Fen ', 'Se ', 'Ji ', 'Sui ', 'Hui ', 'Chu ', 'Ta ', 'Song ', 'Ding ', '[?] ', 'Zhu ', 'Lai ', 'Bin ', 'Lian ', 'Mi ', 'Shi ', 'Shu ', 'Mi ', 'Ning ', 'Ying ', 'Ying ', 'Meng ', 'Jin ', 'Qi ', 'Pi ', 'Ji ', 'Hao ', 'Ru ', 'Zui ', 'Wo ', 'Tao ', 'Yin ', 'Yin ', 'Dui ', 'Ci ', 'Huo ', 'Jing ', 'Lan ', 'Jun ', 'Ai ', 'Pu ', 'Zhuo ', 'Wei ', 'Bin ', 'Gu ', 'Qian ', 'Xing ', 'Hama ', 'Kuo ', 'Fei ', '[?] ', 'Boku ', 'Jian ', 'Wei ', 'Luo ', 'Zan ', 'Lu ', 'Li '];
<?php return ['r', 'r.', '[?]', '[?]', '[?]', '[?]', 'T', 'T.', '[?]', 's', '[?]', '[]', '\\', '/', '[?]', '__', '[?]', '[?]', '>', '%', '[?]', '[?]', '>', '=', '[?]', '/', '-', '~', '\\', '/', '~', '~', '|-', '-|', '[?]', '[?]', '[?]', '[?]', '<=', '=>', '((', '))', '[?]', '[?]', '::', '[?]', '?', '\'', 'o', '.', ',', '.', ',', ';', '[?]', '[?]', '[?]', '[?]', '----', '------', 'x', '|', '[?]', '[?]', '=', ',', '"', '`--', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?] ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['wek', 'wet', 'wep', 'weh', 'wi', 'wig', 'wigg', 'wigs', 'win', 'winj', 'winh', 'wid', 'wil', 'wilg', 'wilm', 'wilb', 'wils', 'wilt', 'wilp', 'wilh', 'wim', 'wib', 'wibs', 'wis', 'wiss', 'wing', 'wij', 'wic', 'wik', 'wit', 'wip', 'wih', 'yu', 'yug', 'yugg', 'yugs', 'yun', 'yunj', 'yunh', 'yud', 'yul', 'yulg', 'yulm', 'yulb', 'yuls', 'yult', 'yulp', 'yulh', 'yum', 'yub', 'yubs', 'yus', 'yuss', 'yung', 'yuj', 'yuc', 'yuk', 'yut', 'yup', 'yuh', 'eu', 'eug', 'eugg', 'eugs', 'eun', 'eunj', 'eunh', 'eud', 'eul', 'eulg', 'eulm', 'eulb', 'euls', 'eult', 'eulp', 'eulh', 'eum', 'eub', 'eubs', 'eus', 'euss', 'eung', 'euj', 'euc', 'euk', 'eut', 'eup', 'euh', 'yi', 'yig', 'yigg', 'yigs', 'yin', 'yinj', 'yinh', 'yid', 'yil', 'yilg', 'yilm', 'yilb', 'yils', 'yilt', 'yilp', 'yilh', 'yim', 'yib', 'yibs', 'yis', 'yiss', 'ying', 'yij', 'yic', 'yik', 'yit', 'yip', 'yih', 'i', 'ig', 'igg', 'igs', 'in', 'inj', 'inh', 'id', 'il', 'ilg', 'ilm', 'ilb', 'ils', 'ilt', 'ilp', 'ilh', 'im', 'ib', 'ibs', 'is', 'iss', 'ing', 'ij', 'ic', 'ik', 'it', 'ip', 'ih', 'ja', 'jag', 'jagg', 'jags', 'jan', 'janj', 'janh', 'jad', 'jal', 'jalg', 'jalm', 'jalb', 'jals', 'jalt', 'jalp', 'jalh', 'jam', 'jab', 'jabs', 'jas', 'jass', 'jang', 'jaj', 'jac', 'jak', 'jat', 'jap', 'jah', 'jae', 'jaeg', 'jaegg', 'jaegs', 'jaen', 'jaenj', 'jaenh', 'jaed', 'jael', 'jaelg', 'jaelm', 'jaelb', 'jaels', 'jaelt', 'jaelp', 'jaelh', 'jaem', 'jaeb', 'jaebs', 'jaes', 'jaess', 'jaeng', 'jaej', 'jaec', 'jaek', 'jaet', 'jaep', 'jaeh', 'jya', 'jyag', 'jyagg', 'jyags', 'jyan', 'jyanj', 'jyanh', 'jyad', 'jyal', 'jyalg', 'jyalm', 'jyalb', 'jyals', 'jyalt', 'jyalp', 'jyalh', 'jyam', 'jyab', 'jyabs', 'jyas', 'jyass', 'jyang', 'jyaj', 'jyac', 'jyak', 'jyat', 'jyap', 'jyah', 'jyae', 'jyaeg', 'jyaegg', 'jyaegs', 'jyaen', 'jyaenj', 'jyaenh', 'jyaed', 'jyael', 'jyaelg', 'jyaelm', 'jyaelb', 'jyaels', 'jyaelt', 'jyaelp', 'jyaelh', 'jyaem', 'jyaeb', 'jyaebs', 'jyaes', 'jyaess', 'jyaeng', 'jyaej', 'jyaec', 'jyaek', 'jyaet', 'jyaep', 'jyaeh'];
<?php return ['jjwaels', 'jjwaelt', 'jjwaelp', 'jjwaelh', 'jjwaem', 'jjwaeb', 'jjwaebs', 'jjwaes', 'jjwaess', 'jjwaeng', 'jjwaej', 'jjwaec', 'jjwaek', 'jjwaet', 'jjwaep', 'jjwaeh', 'jjoe', 'jjoeg', 'jjoegg', 'jjoegs', 'jjoen', 'jjoenj', 'jjoenh', 'jjoed', 'jjoel', 'jjoelg', 'jjoelm', 'jjoelb', 'jjoels', 'jjoelt', 'jjoelp', 'jjoelh', 'jjoem', 'jjoeb', 'jjoebs', 'jjoes', 'jjoess', 'jjoeng', 'jjoej', 'jjoec', 'jjoek', 'jjoet', 'jjoep', 'jjoeh', 'jjyo', 'jjyog', 'jjyogg', 'jjyogs', 'jjyon', 'jjyonj', 'jjyonh', 'jjyod', 'jjyol', 'jjyolg', 'jjyolm', 'jjyolb', 'jjyols', 'jjyolt', 'jjyolp', 'jjyolh', 'jjyom', 'jjyob', 'jjyobs', 'jjyos', 'jjyoss', 'jjyong', 'jjyoj', 'jjyoc', 'jjyok', 'jjyot', 'jjyop', 'jjyoh', 'jju', 'jjug', 'jjugg', 'jjugs', 'jjun', 'jjunj', 'jjunh', 'jjud', 'jjul', 'jjulg', 'jjulm', 'jjulb', 'jjuls', 'jjult', 'jjulp', 'jjulh', 'jjum', 'jjub', 'jjubs', 'jjus', 'jjuss', 'jjung', 'jjuj', 'jjuc', 'jjuk', 'jjut', 'jjup', 'jjuh', 'jjweo', 'jjweog', 'jjweogg', 'jjweogs', 'jjweon', 'jjweonj', 'jjweonh', 'jjweod', 'jjweol', 'jjweolg', 'jjweolm', 'jjweolb', 'jjweols', 'jjweolt', 'jjweolp', 'jjweolh', 'jjweom', 'jjweob', 'jjweobs', 'jjweos', 'jjweoss', 'jjweong', 'jjweoj', 'jjweoc', 'jjweok', 'jjweot', 'jjweop', 'jjweoh', 'jjwe', 'jjweg', 'jjwegg', 'jjwegs', 'jjwen', 'jjwenj', 'jjwenh', 'jjwed', 'jjwel', 'jjwelg', 'jjwelm', 'jjwelb', 'jjwels', 'jjwelt', 'jjwelp', 'jjwelh', 'jjwem', 'jjweb', 'jjwebs', 'jjwes', 'jjwess', 'jjweng', 'jjwej', 'jjwec', 'jjwek', 'jjwet', 'jjwep', 'jjweh', 'jjwi', 'jjwig', 'jjwigg', 'jjwigs', 'jjwin', 'jjwinj', 'jjwinh', 'jjwid', 'jjwil', 'jjwilg', 'jjwilm', 'jjwilb', 'jjwils', 'jjwilt', 'jjwilp', 'jjwilh', 'jjwim', 'jjwib', 'jjwibs', 'jjwis', 'jjwiss', 'jjwing', 'jjwij', 'jjwic', 'jjwik', 'jjwit', 'jjwip', 'jjwih', 'jjyu', 'jjyug', 'jjyugg', 'jjyugs', 'jjyun', 'jjyunj', 'jjyunh', 'jjyud', 'jjyul', 'jjyulg', 'jjyulm', 'jjyulb', 'jjyuls', 'jjyult', 'jjyulp', 'jjyulh', 'jjyum', 'jjyub', 'jjyubs', 'jjyus', 'jjyuss', 'jjyung', 'jjyuj', 'jjyuc', 'jjyuk', 'jjyut', 'jjyup', 'jjyuh', 'jjeu', 'jjeug', 'jjeugg', 'jjeugs', 'jjeun', 'jjeunj', 'jjeunh', 'jjeud', 'jjeul', 'jjeulg', 'jjeulm', 'jjeulb', 'jjeuls', 'jjeult', 'jjeulp', 'jjeulh', 'jjeum', 'jjeub', 'jjeubs', 'jjeus', 'jjeuss', 'jjeung', 'jjeuj', 'jjeuc', 'jjeuk', 'jjeut', 'jjeup', 'jjeuh', 'jjyi', 'jjyig', 'jjyigg', 'jjyigs', 'jjyin', 'jjyinj', 'jjyinh', 'jjyid', 'jjyil', 'jjyilg', 'jjyilm', 'jjyilb', 'jjyils', 'jjyilt', 'jjyilp', 'jjyilh'];
<?php return ['Kay ', 'Kayng ', 'Ke ', 'Ko ', 'Kol ', 'Koc ', 'Kwi ', 'Kwi ', 'Kyun ', 'Kul ', 'Kum ', 'Na ', 'Na ', 'Na ', 'La ', 'Na ', 'Na ', 'Na ', 'Na ', 'Na ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nak ', 'Nan ', 'Nan ', 'Nan ', 'Nan ', 'Nan ', 'Nan ', 'Nam ', 'Nam ', 'Nam ', 'Nam ', 'Nap ', 'Nap ', 'Nap ', 'Nang ', 'Nang ', 'Nang ', 'Nang ', 'Nang ', 'Nay ', 'Nayng ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'No ', 'Nok ', 'Nok ', 'Nok ', 'Nok ', 'Nok ', 'Nok ', 'Non ', 'Nong ', 'Nong ', 'Nong ', 'Nong ', 'Noy ', 'Noy ', 'Noy ', 'Noy ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nwu ', 'Nuk ', 'Nuk ', 'Num ', 'Nung ', 'Nung ', 'Nung ', 'Nung ', 'Nung ', 'Twu ', 'La ', 'Lak ', 'Lak ', 'Lan ', 'Lyeng ', 'Lo ', 'Lyul ', 'Li ', 'Pey ', 'Pen ', 'Pyen ', 'Pwu ', 'Pwul ', 'Pi ', 'Sak ', 'Sak ', 'Sam ', 'Sayk ', 'Sayng ', 'Sep ', 'Sey ', 'Sway ', 'Sin ', 'Sim ', 'Sip ', 'Ya ', 'Yak ', 'Yak ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Yang ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Ye ', 'Yek ', 'Yek ', 'Yek ', 'Yek ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yen ', 'Yel ', 'Yel ', 'Yel ', 'Yel ', 'Yel ', 'Yel ', 'Yem ', 'Yem ', 'Yem ', 'Yem ', 'Yem ', 'Yep ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yeng ', 'Yey ', 'Yey ', 'Yey ', 'Yey ', 'O ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yo ', 'Yong ', 'Wun ', 'Wen ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yu ', 'Yuk ', 'Yuk ', 'Yuk ', 'Yun ', 'Yun ', 'Yun ', 'Yun ', 'Yul ', 'Yul ', 'Yul ', 'Yul ', 'Yung ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'I ', 'Ik ', 'Ik ', 'In ', 'In ', 'In ', 'In ', 'In ', 'In ', 'In ', 'Im ', 'Im ', 'Im ', 'Ip ', 'Ip ', 'Ip ', 'Cang ', 'Cek ', 'Ci ', 'Cip ', 'Cha ', 'Chek '];
<?php return ['Mang ', 'Zhu ', 'Utsubo ', 'Du ', 'Ji ', 'Xiao ', 'Ba ', 'Suan ', 'Ji ', 'Zhen ', 'Zhao ', 'Sun ', 'Ya ', 'Zhui ', 'Yuan ', 'Hu ', 'Gang ', 'Xiao ', 'Cen ', 'Pi ', 'Bi ', 'Jian ', 'Yi ', 'Dong ', 'Shan ', 'Sheng ', 'Xia ', 'Di ', 'Zhu ', 'Na ', 'Chi ', 'Gu ', 'Li ', 'Qie ', 'Min ', 'Bao ', 'Tiao ', 'Si ', 'Fu ', 'Ce ', 'Ben ', 'Pei ', 'Da ', 'Zi ', 'Di ', 'Ling ', 'Ze ', 'Nu ', 'Fu ', 'Gou ', 'Fan ', 'Jia ', 'Ge ', 'Fan ', 'Shi ', 'Mao ', 'Po ', 'Sey ', 'Jian ', 'Qiong ', 'Long ', 'Souke ', 'Bian ', 'Luo ', 'Gui ', 'Qu ', 'Chi ', 'Yin ', 'Yao ', 'Xian ', 'Bi ', 'Qiong ', 'Gua ', 'Deng ', 'Jiao ', 'Jin ', 'Quan ', 'Sun ', 'Ru ', 'Fa ', 'Kuang ', 'Zhu ', 'Tong ', 'Ji ', 'Da ', 'Xing ', 'Ce ', 'Zhong ', 'Kou ', 'Lai ', 'Bi ', 'Shai ', 'Dang ', 'Zheng ', 'Ce ', 'Fu ', 'Yun ', 'Tu ', 'Pa ', 'Li ', 'Lang ', 'Ju ', 'Guan ', 'Jian ', 'Han ', 'Tong ', 'Xia ', 'Zhi ', 'Cheng ', 'Suan ', 'Shi ', 'Zhu ', 'Zuo ', 'Xiao ', 'Shao ', 'Ting ', 'Ce ', 'Yan ', 'Gao ', 'Kuai ', 'Gan ', 'Chou ', 'Kago ', 'Gang ', 'Yun ', 'O ', 'Qian ', 'Xiao ', 'Jian ', 'Pu ', 'Lai ', 'Zou ', 'Bi ', 'Bi ', 'Bi ', 'Ge ', 'Chi ', 'Guai ', 'Yu ', 'Jian ', 'Zhao ', 'Gu ', 'Chi ', 'Zheng ', 'Jing ', 'Sha ', 'Zhou ', 'Lu ', 'Bo ', 'Ji ', 'Lin ', 'Suan ', 'Jun ', 'Fu ', 'Zha ', 'Gu ', 'Kong ', 'Qian ', 'Quan ', 'Jun ', 'Chui ', 'Guan ', 'Yuan ', 'Ce ', 'Ju ', 'Bo ', 'Ze ', 'Qie ', 'Tuo ', 'Luo ', 'Dan ', 'Xiao ', 'Ruo ', 'Jian ', 'Xuan ', 'Bian ', 'Sun ', 'Xiang ', 'Xian ', 'Ping ', 'Zhen ', 'Sheng ', 'Hu ', 'Shi ', 'Zhu ', 'Yue ', 'Chun ', 'Lu ', 'Wu ', 'Dong ', 'Xiao ', 'Ji ', 'Jie ', 'Huang ', 'Xing ', 'Mei ', 'Fan ', 'Chui ', 'Zhuan ', 'Pian ', 'Feng ', 'Zhu ', 'Hong ', 'Qie ', 'Hou ', 'Qiu ', 'Miao ', 'Qian ', '[?] ', 'Kui ', 'Sik ', 'Lou ', 'Yun ', 'He ', 'Tang ', 'Yue ', 'Chou ', 'Gao ', 'Fei ', 'Ruo ', 'Zheng ', 'Gou ', 'Nie ', 'Qian ', 'Xiao ', 'Cuan ', 'Gong ', 'Pang ', 'Du ', 'Li ', 'Bi ', 'Zhuo ', 'Chu ', 'Shai ', 'Chi ', 'Zhu ', 'Qiang ', 'Long ', 'Lan ', 'Jian ', 'Bu ', 'Li ', 'Hui ', 'Bi ', 'Di ', 'Cong ', 'Yan ', 'Peng ', 'Sen ', 'Zhuan ', 'Pai ', 'Piao ', 'Dou ', 'Yu ', 'Mie ', 'Zhuan '];
<?php return ['Er ', 'Qiong ', 'Ju ', 'Jiao ', 'Guang ', 'Lu ', 'Kai ', 'Quan ', 'Zhou ', 'Zai ', 'Zhi ', 'She ', 'Liang ', 'Yu ', 'Shao ', 'You ', 'Huan ', 'Yun ', 'Zhe ', 'Wan ', 'Fu ', 'Qing ', 'Zhou ', 'Ni ', 'Ling ', 'Zhe ', 'Zhan ', 'Liang ', 'Zi ', 'Hui ', 'Wang ', 'Chuo ', 'Guo ', 'Kan ', 'Yi ', 'Peng ', 'Qian ', 'Gun ', 'Nian ', 'Pian ', 'Guan ', 'Bei ', 'Lun ', 'Pai ', 'Liang ', 'Ruan ', 'Rou ', 'Ji ', 'Yang ', 'Xian ', 'Chuan ', 'Cou ', 'Qun ', 'Ge ', 'You ', 'Hong ', 'Shu ', 'Fu ', 'Zi ', 'Fu ', 'Wen ', 'Ben ', 'Zhan ', 'Yu ', 'Wen ', 'Tao ', 'Gu ', 'Zhen ', 'Xia ', 'Yuan ', 'Lu ', 'Jiu ', 'Chao ', 'Zhuan ', 'Wei ', 'Hun ', 'Sori ', 'Che ', 'Jiao ', 'Zhan ', 'Pu ', 'Lao ', 'Fen ', 'Fan ', 'Lin ', 'Ge ', 'Se ', 'Kan ', 'Huan ', 'Yi ', 'Ji ', 'Dui ', 'Er ', 'Yu ', 'Xian ', 'Hong ', 'Lei ', 'Pei ', 'Li ', 'Li ', 'Lu ', 'Lin ', 'Che ', 'Ya ', 'Gui ', 'Xuan ', 'Di ', 'Ren ', 'Zhuan ', 'E ', 'Lun ', 'Ruan ', 'Hong ', 'Ku ', 'Ke ', 'Lu ', 'Zhou ', 'Zhi ', 'Yi ', 'Hu ', 'Zhen ', 'Li ', 'Yao ', 'Qing ', 'Shi ', 'Zai ', 'Zhi ', 'Jiao ', 'Zhou ', 'Quan ', 'Lu ', 'Jiao ', 'Zhe ', 'Fu ', 'Liang ', 'Nian ', 'Bei ', 'Hui ', 'Gun ', 'Wang ', 'Liang ', 'Chuo ', 'Zi ', 'Cou ', 'Fu ', 'Ji ', 'Wen ', 'Shu ', 'Pei ', 'Yuan ', 'Xia ', 'Zhan ', 'Lu ', 'Che ', 'Lin ', 'Xin ', 'Gu ', 'Ci ', 'Ci ', 'Pi ', 'Zui ', 'Bian ', 'La ', 'La ', 'Ci ', 'Xue ', 'Ban ', 'Bian ', 'Bian ', 'Bian ', '[?] ', 'Bian ', 'Ban ', 'Ci ', 'Bian ', 'Bian ', 'Chen ', 'Ru ', 'Nong ', 'Nong ', 'Zhen ', 'Chuo ', 'Chuo ', 'Suberu ', 'Reng ', 'Bian ', 'Bian ', 'Sip ', 'Ip ', 'Liao ', 'Da ', 'Chan ', 'Gan ', 'Qian ', 'Yu ', 'Yu ', 'Qi ', 'Xun ', 'Yi ', 'Guo ', 'Mai ', 'Qi ', 'Za ', 'Wang ', 'Jia ', 'Zhun ', 'Ying ', 'Ti ', 'Yun ', 'Jin ', 'Hang ', 'Ya ', 'Fan ', 'Wu ', 'Da ', 'E ', 'Huan ', 'Zhe ', 'Totemo ', 'Jin ', 'Yuan ', 'Wei ', 'Lian ', 'Chi ', 'Che ', 'Ni ', 'Tiao ', 'Zhi ', 'Yi ', 'Jiong ', 'Jia ', 'Chen ', 'Dai ', 'Er ', 'Di ', 'Po ', 'Wang ', 'Die ', 'Ze ', 'Tao ', 'Shu ', 'Tuo ', 'Kep ', 'Jing ', 'Hui ', 'Tong ', 'You ', 'Mi ', 'Beng ', 'Ji ', 'Nai ', 'Yi ', 'Jie ', 'Zhui ', 'Lie ', 'Xun '];
<?php return ['A', 'a', 'B', 'b', 'B', 'b', 'B', 'b', 'C', 'c', 'D', 'd', 'D', 'd', 'D', 'd', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'K', 'k', 'K', 'k', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'M', 'm', 'M', 'm', 'M', 'm', 'N', 'n', 'N', 'n', 'N', 'n', 'N', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'P', 'p', 'P', 'p', 'R', 'r', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'V', 'v', 'V', 'v', 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'X', 'x', 'X', 'x', 'Y', 'y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 'h', 't', 'w', 'y', 'a', 's', 's', 's', 'Ss', 'd', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'Y', 'y', 'Y', 'y', 'Y', 'y', 'Y', 'y', 'LL', 'll', 'V', 'v', 'Y', 'y'];
<?php return ['Han ', 'Xuan ', 'Yan ', 'Qiu ', 'Quan ', 'Lang ', 'Li ', 'Xiu ', 'Fu ', 'Liu ', 'Ye ', 'Xi ', 'Ling ', 'Li ', 'Jin ', 'Lian ', 'Suo ', 'Chiisai ', '[?] ', 'Wan ', 'Dian ', 'Pin ', 'Zhan ', 'Cui ', 'Min ', 'Yu ', 'Ju ', 'Chen ', 'Lai ', 'Wen ', 'Sheng ', 'Wei ', 'Dian ', 'Chu ', 'Zhuo ', 'Pei ', 'Cheng ', 'Hu ', 'Qi ', 'E ', 'Kun ', 'Chang ', 'Qi ', 'Beng ', 'Wan ', 'Lu ', 'Cong ', 'Guan ', 'Yan ', 'Diao ', 'Bei ', 'Lin ', 'Qin ', 'Pi ', 'Pa ', 'Que ', 'Zhuo ', 'Qin ', 'Fa ', '[?] ', 'Qiong ', 'Du ', 'Jie ', 'Hun ', 'Yu ', 'Mao ', 'Mei ', 'Chun ', 'Xuan ', 'Ti ', 'Xing ', 'Dai ', 'Rou ', 'Min ', 'Zhen ', 'Wei ', 'Ruan ', 'Huan ', 'Jie ', 'Chuan ', 'Jian ', 'Zhuan ', 'Yang ', 'Lian ', 'Quan ', 'Xia ', 'Duan ', 'Yuan ', 'Ye ', 'Nao ', 'Hu ', 'Ying ', 'Yu ', 'Huang ', 'Rui ', 'Se ', 'Liu ', 'Shi ', 'Rong ', 'Suo ', 'Yao ', 'Wen ', 'Wu ', 'Jin ', 'Jin ', 'Ying ', 'Ma ', 'Tao ', 'Liu ', 'Tang ', 'Li ', 'Lang ', 'Gui ', 'Zhen ', 'Qiang ', 'Cuo ', 'Jue ', 'Zhao ', 'Yao ', 'Ai ', 'Bin ', 'Tu ', 'Chang ', 'Kun ', 'Zhuan ', 'Cong ', 'Jin ', 'Yi ', 'Cui ', 'Cong ', 'Qi ', 'Li ', 'Ying ', 'Suo ', 'Qiu ', 'Xuan ', 'Ao ', 'Lian ', 'Man ', 'Zhang ', 'Yin ', '[?] ', 'Ying ', 'Zhi ', 'Lu ', 'Wu ', 'Deng ', 'Xiou ', 'Zeng ', 'Xun ', 'Qu ', 'Dang ', 'Lin ', 'Liao ', 'Qiong ', 'Su ', 'Huang ', 'Gui ', 'Pu ', 'Jing ', 'Fan ', 'Jin ', 'Liu ', 'Ji ', '[?] ', 'Jing ', 'Ai ', 'Bi ', 'Can ', 'Qu ', 'Zao ', 'Dang ', 'Jiao ', 'Gun ', 'Tan ', 'Hui ', 'Huan ', 'Se ', 'Sui ', 'Tian ', '[?] ', 'Yu ', 'Jin ', 'Lu ', 'Bin ', 'Shou ', 'Wen ', 'Zui ', 'Lan ', 'Xi ', 'Ji ', 'Xuan ', 'Ruan ', 'Huo ', 'Gai ', 'Lei ', 'Du ', 'Li ', 'Zhi ', 'Rou ', 'Li ', 'Zan ', 'Qiong ', 'Zhe ', 'Gui ', 'Sui ', 'La ', 'Long ', 'Lu ', 'Li ', 'Zan ', 'Lan ', 'Ying ', 'Mi ', 'Xiang ', 'Xi ', 'Guan ', 'Dao ', 'Zan ', 'Huan ', 'Gua ', 'Bo ', 'Die ', 'Bao ', 'Hu ', 'Zhi ', 'Piao ', 'Ban ', 'Rang ', 'Li ', 'Wa ', 'Dekaguramu ', 'Jiang ', 'Qian ', 'Fan ', 'Pen ', 'Fang ', 'Dan ', 'Weng ', 'Ou ', 'Deshiguramu ', 'Miriguramu ', 'Thon ', 'Hu ', 'Ling ', 'Yi ', 'Ping ', 'Ci ', 'Hekutogura ', 'Juan ', 'Chang ', 'Chi ', 'Sarake ', 'Dang ', 'Meng ', 'Pou '];
<?php return ['Yun ', 'Bei ', 'Ang ', 'Ze ', 'Ban ', 'Jie ', 'Kun ', 'Sheng ', 'Hu ', 'Fang ', 'Hao ', 'Gui ', 'Chang ', 'Xuan ', 'Ming ', 'Hun ', 'Fen ', 'Qin ', 'Hu ', 'Yi ', 'Xi ', 'Xin ', 'Yan ', 'Ze ', 'Fang ', 'Tan ', 'Shen ', 'Ju ', 'Yang ', 'Zan ', 'Bing ', 'Xing ', 'Ying ', 'Xuan ', 'Pei ', 'Zhen ', 'Ling ', 'Chun ', 'Hao ', 'Mei ', 'Zuo ', 'Mo ', 'Bian ', 'Xu ', 'Hun ', 'Zhao ', 'Zong ', 'Shi ', 'Shi ', 'Yu ', 'Fei ', 'Die ', 'Mao ', 'Ni ', 'Chang ', 'Wen ', 'Dong ', 'Ai ', 'Bing ', 'Ang ', 'Zhou ', 'Long ', 'Xian ', 'Kuang ', 'Tiao ', 'Chao ', 'Shi ', 'Huang ', 'Huang ', 'Xuan ', 'Kui ', 'Xu ', 'Jiao ', 'Jin ', 'Zhi ', 'Jin ', 'Shang ', 'Tong ', 'Hong ', 'Yan ', 'Gai ', 'Xiang ', 'Shai ', 'Xiao ', 'Ye ', 'Yun ', 'Hui ', 'Han ', 'Han ', 'Jun ', 'Wan ', 'Xian ', 'Kun ', 'Zhou ', 'Xi ', 'Cheng ', 'Sheng ', 'Bu ', 'Zhe ', 'Zhe ', 'Wu ', 'Han ', 'Hui ', 'Hao ', 'Chen ', 'Wan ', 'Tian ', 'Zhuo ', 'Zui ', 'Zhou ', 'Pu ', 'Jing ', 'Xi ', 'Shan ', 'Yi ', 'Xi ', 'Qing ', 'Qi ', 'Jing ', 'Gui ', 'Zhen ', 'Yi ', 'Zhi ', 'An ', 'Wan ', 'Lin ', 'Liang ', 'Chang ', 'Wang ', 'Xiao ', 'Zan ', 'Hi ', 'Xuan ', 'Xuan ', 'Yi ', 'Xia ', 'Yun ', 'Hui ', 'Fu ', 'Min ', 'Kui ', 'He ', 'Ying ', 'Du ', 'Wei ', 'Shu ', 'Qing ', 'Mao ', 'Nan ', 'Jian ', 'Nuan ', 'An ', 'Yang ', 'Chun ', 'Yao ', 'Suo ', 'Jin ', 'Ming ', 'Jiao ', 'Kai ', 'Gao ', 'Weng ', 'Chang ', 'Qi ', 'Hao ', 'Yan ', 'Li ', 'Ai ', 'Ji ', 'Gui ', 'Men ', 'Zan ', 'Xie ', 'Hao ', 'Mu ', 'Mo ', 'Cong ', 'Ni ', 'Zhang ', 'Hui ', 'Bao ', 'Han ', 'Xuan ', 'Chuan ', 'Liao ', 'Xian ', 'Dan ', 'Jing ', 'Pie ', 'Lin ', 'Tun ', 'Xi ', 'Yi ', 'Ji ', 'Huang ', 'Tai ', 'Ye ', 'Ye ', 'Li ', 'Tan ', 'Tong ', 'Xiao ', 'Fei ', 'Qin ', 'Zhao ', 'Hao ', 'Yi ', 'Xiang ', 'Xing ', 'Sen ', 'Jiao ', 'Bao ', 'Jing ', 'Yian ', 'Ai ', 'Ye ', 'Ru ', 'Shu ', 'Meng ', 'Xun ', 'Yao ', 'Pu ', 'Li ', 'Chen ', 'Kuang ', 'Die ', '[?] ', 'Yan ', 'Huo ', 'Lu ', 'Xi ', 'Rong ', 'Long ', 'Nang ', 'Luo ', 'Luan ', 'Shai ', 'Tang ', 'Yan ', 'Chu ', 'Yue ', 'Yue ', 'Qu ', 'Yi ', 'Geng ', 'Ye ', 'Hu ', 'He ', 'Shu ', 'Cao ', 'Cao ', 'Noboru ', 'Man ', 'Ceng ', 'Ceng ', 'Ti '];
<?php return ['Tui ', 'Song ', 'Gua ', 'Tao ', 'Pang ', 'Hou ', 'Ni ', 'Dun ', 'Jiong ', 'Xuan ', 'Xun ', 'Bu ', 'You ', 'Xiao ', 'Qiu ', 'Tou ', 'Zhu ', 'Qiu ', 'Di ', 'Di ', 'Tu ', 'Jing ', 'Ti ', 'Dou ', 'Yi ', 'Zhe ', 'Tong ', 'Guang ', 'Wu ', 'Shi ', 'Cheng ', 'Su ', 'Zao ', 'Qun ', 'Feng ', 'Lian ', 'Suo ', 'Hui ', 'Li ', 'Sako ', 'Lai ', 'Ben ', 'Cuo ', 'Jue ', 'Beng ', 'Huan ', 'Dai ', 'Lu ', 'You ', 'Zhou ', 'Jin ', 'Yu ', 'Chuo ', 'Kui ', 'Wei ', 'Ti ', 'Yi ', 'Da ', 'Yuan ', 'Luo ', 'Bi ', 'Nuo ', 'Yu ', 'Dang ', 'Sui ', 'Dun ', 'Sui ', 'Yan ', 'Chuan ', 'Chi ', 'Ti ', 'Yu ', 'Shi ', 'Zhen ', 'You ', 'Yun ', 'E ', 'Bian ', 'Guo ', 'E ', 'Xia ', 'Huang ', 'Qiu ', 'Dao ', 'Da ', 'Wei ', 'Appare ', 'Yi ', 'Gou ', 'Yao ', 'Chu ', 'Liu ', 'Xun ', 'Ta ', 'Di ', 'Chi ', 'Yuan ', 'Su ', 'Ta ', 'Qian ', '[?] ', 'Yao ', 'Guan ', 'Zhang ', 'Ao ', 'Shi ', 'Ce ', 'Chi ', 'Su ', 'Zao ', 'Zhe ', 'Dun ', 'Di ', 'Lou ', 'Chi ', 'Cuo ', 'Lin ', 'Zun ', 'Rao ', 'Qian ', 'Xuan ', 'Yu ', 'Yi ', 'Wu ', 'Liao ', 'Ju ', 'Shi ', 'Bi ', 'Yao ', 'Mai ', 'Xie ', 'Sui ', 'Huan ', 'Zhan ', 'Teng ', 'Er ', 'Miao ', 'Bian ', 'Bian ', 'La ', 'Li ', 'Yuan ', 'Yao ', 'Luo ', 'Li ', 'Yi ', 'Ting ', 'Deng ', 'Qi ', 'Yong ', 'Shan ', 'Han ', 'Yu ', 'Mang ', 'Ru ', 'Qiong ', '[?] ', 'Kuang ', 'Fu ', 'Kang ', 'Bin ', 'Fang ', 'Xing ', 'Na ', 'Xin ', 'Shen ', 'Bang ', 'Yuan ', 'Cun ', 'Huo ', 'Xie ', 'Bang ', 'Wu ', 'Ju ', 'You ', 'Han ', 'Tai ', 'Qiu ', 'Bi ', 'Pei ', 'Bing ', 'Shao ', 'Bei ', 'Wa ', 'Di ', 'Zou ', 'Ye ', 'Lin ', 'Kuang ', 'Gui ', 'Zhu ', 'Shi ', 'Ku ', 'Yu ', 'Gai ', 'Ge ', 'Xi ', 'Zhi ', 'Ji ', 'Xun ', 'Hou ', 'Xing ', 'Jiao ', 'Xi ', 'Gui ', 'Nuo ', 'Lang ', 'Jia ', 'Kuai ', 'Zheng ', 'Otoko ', 'Yun ', 'Yan ', 'Cheng ', 'Dou ', 'Chi ', 'Lu ', 'Fu ', 'Wu ', 'Fu ', 'Gao ', 'Hao ', 'Lang ', 'Jia ', 'Geng ', 'Jun ', 'Ying ', 'Bo ', 'Xi ', 'Bei ', 'Li ', 'Yun ', 'Bu ', 'Xiao ', 'Qi ', 'Pi ', 'Qing ', 'Guo ', 'Zhou ', 'Tan ', 'Zou ', 'Ping ', 'Lai ', 'Ni ', 'Chen ', 'You ', 'Bu ', 'Xiang ', 'Dan ', 'Ju ', 'Yong ', 'Qiao ', 'Yi ', 'Du ', 'Yan ', 'Mei '];
<?php return ['Cu ', 'Qu ', 'Chao ', 'Wa ', 'Zhu ', 'Zhi ', 'Mang ', 'Ao ', 'Bie ', 'Tuo ', 'Bi ', 'Yuan ', 'Chao ', 'Tuo ', 'Ding ', 'Mi ', 'Nai ', 'Ding ', 'Zi ', 'Gu ', 'Gu ', 'Dong ', 'Fen ', 'Tao ', 'Yuan ', 'Pi ', 'Chang ', 'Gao ', 'Qi ', 'Yuan ', 'Tang ', 'Teng ', 'Shu ', 'Shu ', 'Fen ', 'Fei ', 'Wen ', 'Ba ', 'Diao ', 'Tuo ', 'Tong ', 'Qu ', 'Sheng ', 'Shi ', 'You ', 'Shi ', 'Ting ', 'Wu ', 'Nian ', 'Jing ', 'Hun ', 'Ju ', 'Yan ', 'Tu ', 'Ti ', 'Xi ', 'Xian ', 'Yan ', 'Lei ', 'Bi ', 'Yao ', 'Qiu ', 'Han ', 'Wu ', 'Wu ', 'Hou ', 'Xi ', 'Ge ', 'Zha ', 'Xiu ', 'Weng ', 'Zha ', 'Nong ', 'Nang ', 'Qi ', 'Zhai ', 'Ji ', 'Zi ', 'Ji ', 'Ji ', 'Qi ', 'Ji ', 'Chi ', 'Chen ', 'Chen ', 'He ', 'Ya ', 'Ken ', 'Xie ', 'Pao ', 'Cuo ', 'Shi ', 'Zi ', 'Chi ', 'Nian ', 'Ju ', 'Tiao ', 'Ling ', 'Ling ', 'Chu ', 'Quan ', 'Xie ', 'Ken ', 'Nie ', 'Jiu ', 'Yao ', 'Chuo ', 'Kun ', 'Yu ', 'Chu ', 'Yi ', 'Ni ', 'Cuo ', 'Zou ', 'Qu ', 'Nen ', 'Xian ', 'Ou ', 'E ', 'Wo ', 'Yi ', 'Chuo ', 'Zou ', 'Dian ', 'Chu ', 'Jin ', 'Ya ', 'Chi ', 'Chen ', 'He ', 'Ken ', 'Ju ', 'Ling ', 'Pao ', 'Tiao ', 'Zi ', 'Ken ', 'Yu ', 'Chuo ', 'Qu ', 'Wo ', 'Long ', 'Pang ', 'Gong ', 'Pang ', 'Yan ', 'Long ', 'Long ', 'Gong ', 'Kan ', 'Ta ', 'Ling ', 'Ta ', 'Long ', 'Gong ', 'Kan ', 'Gui ', 'Qiu ', 'Bie ', 'Gui ', 'Yue ', 'Chui ', 'He ', 'Jue ', 'Xie ', 'Yu ', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['Hu ', 'Qi ', 'He ', 'Cui ', 'Tao ', 'Chun ', 'Bei ', 'Chang ', 'Huan ', 'Fei ', 'Lai ', 'Qi ', 'Meng ', 'Ping ', 'Wei ', 'Dan ', 'Sha ', 'Huan ', 'Yan ', 'Yi ', 'Tiao ', 'Qi ', 'Wan ', 'Ce ', 'Nai ', 'Kutabireru ', 'Tuo ', 'Jiu ', 'Tie ', 'Luo ', '[?] ', '[?] ', 'Meng ', '[?] ', 'Yaji ', '[?] ', 'Ying ', 'Ying ', 'Ying ', 'Xiao ', 'Sa ', 'Qiu ', 'Ke ', 'Xiang ', 'Wan ', 'Yu ', 'Yu ', 'Fu ', 'Lian ', 'Xuan ', 'Yuan ', 'Nan ', 'Ze ', 'Wo ', 'Chun ', 'Xiao ', 'Yu ', 'Pian ', 'Mao ', 'An ', 'E ', 'Luo ', 'Ying ', 'Huo ', 'Gua ', 'Jiang ', 'Mian ', 'Zuo ', 'Zuo ', 'Ju ', 'Bao ', 'Rou ', 'Xi ', 'Xie ', 'An ', 'Qu ', 'Jian ', 'Fu ', 'Lu ', 'Jing ', 'Pen ', 'Feng ', 'Hong ', 'Hong ', 'Hou ', 'Yan ', 'Tu ', 'Zhu ', 'Zi ', 'Xiang ', 'Shen ', 'Ge ', 'Jie ', 'Jing ', 'Mi ', 'Huang ', 'Shen ', 'Pu ', 'Gai ', 'Dong ', 'Zhou ', 'Qian ', 'Wei ', 'Bo ', 'Wei ', 'Pa ', 'Ji ', 'Hu ', 'Zang ', 'Jia ', 'Duan ', 'Yao ', 'Jun ', 'Cong ', 'Quan ', 'Wei ', 'Xian ', 'Kui ', 'Ting ', 'Hun ', 'Xi ', 'Shi ', 'Qi ', 'Lan ', 'Zong ', 'Yao ', 'Yuan ', 'Mei ', 'Yun ', 'Shu ', 'Di ', 'Zhuan ', 'Guan ', 'Sukumo ', 'Xue ', 'Chan ', 'Kai ', 'Kui ', '[?] ', 'Jiang ', 'Lou ', 'Wei ', 'Pai ', '[?] ', 'Sou ', 'Yin ', 'Shi ', 'Chun ', 'Shi ', 'Yun ', 'Zhen ', 'Lang ', 'Nu ', 'Meng ', 'He ', 'Que ', 'Suan ', 'Yuan ', 'Li ', 'Ju ', 'Xi ', 'Pang ', 'Chu ', 'Xu ', 'Tu ', 'Liu ', 'Wo ', 'Zhen ', 'Qian ', 'Zu ', 'Po ', 'Cuo ', 'Yuan ', 'Chu ', 'Yu ', 'Kuai ', 'Pan ', 'Pu ', 'Pu ', 'Na ', 'Shuo ', 'Xi ', 'Fen ', 'Yun ', 'Zheng ', 'Jian ', 'Ji ', 'Ruo ', 'Cang ', 'En ', 'Mi ', 'Hao ', 'Sun ', 'Zhen ', 'Ming ', 'Sou ', 'Xu ', 'Liu ', 'Xi ', 'Gu ', 'Lang ', 'Rong ', 'Weng ', 'Gai ', 'Cuo ', 'Shi ', 'Tang ', 'Luo ', 'Ru ', 'Suo ', 'Xian ', 'Bei ', 'Yao ', 'Gui ', 'Bi ', 'Zong ', 'Gun ', 'Za ', 'Xiu ', 'Ce ', 'Hai ', 'Lan ', '[?] ', 'Ji ', 'Li ', 'Can ', 'Lang ', 'Yu ', '[?] ', 'Ying ', 'Mo ', 'Diao ', 'Tiao ', 'Mao ', 'Tong ', 'Zhu ', 'Peng ', 'An ', 'Lian ', 'Cong ', 'Xi ', 'Ping ', 'Qiu ', 'Jin ', 'Chun ', 'Jie ', 'Wei ', 'Tui ', 'Cao ', 'Yu ', 'Yi ', 'Ji ', 'Liao ', 'Bi ', 'Lu ', 'Su '];
<?php return ['Wei ', 'Bai ', 'Chen ', 'Zhuan ', 'Zhi ', 'Zhui ', 'Biao ', 'Yun ', 'Zeng ', 'Tan ', 'Zan ', 'Yan ', '[?] ', 'Shan ', 'Wan ', 'Ying ', 'Jin ', 'Gan ', 'Xian ', 'Zang ', 'Bi ', 'Du ', 'Shu ', 'Yan ', '[?] ', 'Xuan ', 'Long ', 'Gan ', 'Zang ', 'Bei ', 'Zhen ', 'Fu ', 'Yuan ', 'Gong ', 'Cai ', 'Ze ', 'Xian ', 'Bai ', 'Zhang ', 'Huo ', 'Zhi ', 'Fan ', 'Tan ', 'Pin ', 'Bian ', 'Gou ', 'Zhu ', 'Guan ', 'Er ', 'Jian ', 'Bi ', 'Shi ', 'Tie ', 'Gui ', 'Kuang ', 'Dai ', 'Mao ', 'Fei ', 'He ', 'Yi ', 'Zei ', 'Zhi ', 'Jia ', 'Hui ', 'Zi ', 'Ren ', 'Lu ', 'Zang ', 'Zi ', 'Gai ', 'Jin ', 'Qiu ', 'Zhen ', 'Lai ', 'She ', 'Fu ', 'Du ', 'Ji ', 'Shu ', 'Shang ', 'Si ', 'Bi ', 'Zhou ', 'Geng ', 'Pei ', 'Tan ', 'Lai ', 'Feng ', 'Zhui ', 'Fu ', 'Zhuan ', 'Sai ', 'Ze ', 'Yan ', 'Zan ', 'Yun ', 'Zeng ', 'Shan ', 'Ying ', 'Gan ', 'Chi ', 'Xi ', 'She ', 'Nan ', 'Xiong ', 'Xi ', 'Cheng ', 'He ', 'Cheng ', 'Zhe ', 'Xia ', 'Tang ', 'Zou ', 'Zou ', 'Li ', 'Jiu ', 'Fu ', 'Zhao ', 'Gan ', 'Qi ', 'Shan ', 'Qiong ', 'Qin ', 'Xian ', 'Ci ', 'Jue ', 'Qin ', 'Chi ', 'Ci ', 'Chen ', 'Chen ', 'Die ', 'Ju ', 'Chao ', 'Di ', 'Se ', 'Zhan ', 'Zhu ', 'Yue ', 'Qu ', 'Jie ', 'Chi ', 'Chu ', 'Gua ', 'Xue ', 'Ci ', 'Tiao ', 'Duo ', 'Lie ', 'Gan ', 'Suo ', 'Cu ', 'Xi ', 'Zhao ', 'Su ', 'Yin ', 'Ju ', 'Jian ', 'Que ', 'Tang ', 'Chuo ', 'Cui ', 'Lu ', 'Qu ', 'Dang ', 'Qiu ', 'Zi ', 'Ti ', 'Qu ', 'Chi ', 'Huang ', 'Qiao ', 'Qiao ', 'Yao ', 'Zao ', 'Ti ', '[?] ', 'Zan ', 'Zan ', 'Zu ', 'Pa ', 'Bao ', 'Ku ', 'Ke ', 'Dun ', 'Jue ', 'Fu ', 'Chen ', 'Jian ', 'Fang ', 'Zhi ', 'Sa ', 'Yue ', 'Pa ', 'Qi ', 'Yue ', 'Qiang ', 'Tuo ', 'Tai ', 'Yi ', 'Nian ', 'Ling ', 'Mei ', 'Ba ', 'Die ', 'Ku ', 'Tuo ', 'Jia ', 'Ci ', 'Pao ', 'Qia ', 'Zhu ', 'Ju ', 'Die ', 'Zhi ', 'Fu ', 'Pan ', 'Ju ', 'Shan ', 'Bo ', 'Ni ', 'Ju ', 'Li ', 'Gen ', 'Yi ', 'Ji ', 'Dai ', 'Xian ', 'Jiao ', 'Duo ', 'Zhu ', 'Zhuan ', 'Kua ', 'Zhuai ', 'Gui ', 'Qiong ', 'Kui ', 'Xiang ', 'Chi ', 'Lu ', 'Beng ', 'Zhi ', 'Jia ', 'Tiao ', 'Cai ', 'Jian ', 'Ta ', 'Qiao ', 'Bi ', 'Xian ', 'Duo ', 'Ji ', 'Ju ', 'Ji ', 'Shu ', 'Tu '];
<?php return ['' => 0, "\x00" => 0, "\x01" => 1, "\x02" => 2, "\x03" => 3, "\x04" => 4, "\x05" => 5, "\x06" => 6, "\x07" => 7, "\x08" => 8, "\x09" => 9, "\x0A" => 10, "\x0B" => 11, "\x0C" => 12, "\x0D" => 13, "\x0E" => 14, "\x0F" => 15, "\x10" => 16, "\x11" => 17, "\x12" => 18, "\x13" => 19, "\x14" => 20, "\x15" => 21, "\x16" => 22, "\x17" => 23, "\x18" => 24, "\x19" => 25, "\x1A" => 26, "\x1B" => 27, "\x1C" => 28, "\x1D" => 29, "\x1E" => 30, "\x1F" => 31, "\x20" => 32, "\x21" => 33, "\x22" => 34, "\x23" => 35, "\x24" => 36, "\x25" => 37, "\x26" => 38, "\x27" => 39, "\x28" => 40, "\x29" => 41, "\x2A" => 42, "\x2B" => 43, "\x2C" => 44, "\x2D" => 45, "\x2E" => 46, "\x2F" => 47, "\x30" => 48, "\x31" => 49, "\x32" => 50, "\x33" => 51, "\x34" => 52, "\x35" => 53, "\x36" => 54, "\x37" => 55, "\x38" => 56, "\x39" => 57, "\x3A" => 58, "\x3B" => 59, "\x3C" => 60, "\x3D" => 61, "\x3E" => 62, "\x3F" => 63, "\x40" => 64, "\x41" => 65, "\x42" => 66, "\x43" => 67, "\x44" => 68, "\x45" => 69, "\x46" => 70, "\x47" => 71, "\x48" => 72, "\x49" => 73, "\x4A" => 74, "\x4B" => 75, "\x4C" => 76, "\x4D" => 77, "\x4E" => 78, "\x4F" => 79, "\x50" => 80, "\x51" => 81, "\x52" => 82, "\x53" => 83, "\x54" => 84, "\x55" => 85, "\x56" => 86, "\x57" => 87, "\x58" => 88, "\x59" => 89, "\x5A" => 90, "\x5B" => 91, "\x5C" => 92, "\x5D" => 93, "\x5E" => 94, "\x5F" => 95, "\x60" => 96, "\x61" => 97, "\x62" => 98, "\x63" => 99, "\x64" => 100, "\x65" => 101, "\x66" => 102, "\x67" => 103, "\x68" => 104, "\x69" => 105, "\x6A" => 106, "\x6B" => 107, "\x6C" => 108, "\x6D" => 109, "\x6E" => 110, "\x6F" => 111, "\x70" => 112, "\x71" => 113, "\x72" => 114, "\x73" => 115, "\x74" => 116, "\x75" => 117, "\x76" => 118, "\x77" => 119, "\x78" => 120, "\x79" => 121, "\x7A" => 122, "\x7B" => 123, "\x7C" => 124, "\x7D" => 125, "\x7E" => 126, "\x7F" => 127, "\x80" => 128, "\x81" => 129, "\x82" => 130, "\x83" => 131, "\x84" => 132, "\x85" => 133, "\x86" => 134, "\x87" => 135, "\x88" => 136, "\x89" => 137, "\x8A" => 138, "\x8B" => 139, "\x8C" => 140, "\x8D" => 141, "\x8E" => 142, "\x8F" => 143, "\x90" => 144, "\x91" => 145, "\x92" => 146, "\x93" => 147, "\x94" => 148, "\x95" => 149, "\x96" => 150, "\x97" => 151, "\x98" => 152, "\x99" => 153, "\x9A" => 154, "\x9B" => 155, "\x9C" => 156, "\x9D" => 157, "\x9E" => 158, "\x9F" => 159, "\xA0" => 160, "\xA1" => 161, "\xA2" => 162, "\xA3" => 163, "\xA4" => 164, "\xA5" => 165, "\xA6" => 166, "\xA7" => 167, "\xA8" => 168, "\xA9" => 169, "\xAA" => 170, "\xAB" => 171, "\xAC" => 172, "\xAD" => 173, "\xAE" => 174, "\xAF" => 175, "\xB0" => 176, "\xB1" => 177, "\xB2" => 178, "\xB3" => 179, "\xB4" => 180, "\xB5" => 181, "\xB6" => 182, "\xB7" => 183, "\xB8" => 184, "\xB9" => 185, "\xBA" => 186, "\xBB" => 187, "\xBC" => 188, "\xBD" => 189, "\xBE" => 190, "\xBF" => 191, "\xC0" => 192, "\xC1" => 193, "\xC2" => 194, "\xC3" => 195, "\xC4" => 196, "\xC5" => 197, "\xC6" => 198, "\xC7" => 199, "\xC8" => 200, "\xC9" => 201, "\xCA" => 202, "\xCB" => 203, "\xCC" => 204, "\xCD" => 205, "\xCE" => 206, "\xCF" => 207, "\xD0" => 208, "\xD1" => 209, "\xD2" => 210, "\xD3" => 211, "\xD4" => 212, "\xD5" => 213, "\xD6" => 214, "\xD7" => 215, "\xD8" => 216, "\xD9" => 217, "\xDA" => 218, "\xDB" => 219, "\xDC" => 220, "\xDD" => 221, "\xDE" => 222, "\xDF" => 223, "\xE0" => 224, "\xE1" => 225, "\xE2" => 226, "\xE3" => 227, "\xE4" => 228, "\xE5" => 229, "\xE6" => 230, "\xE7" => 231, "\xE8" => 232, "\xE9" => 233, "\xEA" => 234, "\xEB" => 235, "\xEC" => 236, "\xED" => 237, "\xEE" => 238, "\xEF" => 239, "\xF0" => 240, "\xF1" => 241, "\xF2" => 242, "\xF3" => 243, "\xF4" => 244, "\xF5" => 245, "\xF6" => 246, "\xF7" => 247, "\xF8" => 248, "\xF9" => 249, "\xFA" => 250, "\xFB" => 251, "\xFC" => 252, "\xFD" => 253, "\xFE" => 254, "\xFF" => 255];
<?php return ['ha', 'hu', 'hi', 'haa', 'hee', 'he', 'ho', '[?]', 'la', 'lu', 'li', 'laa', 'lee', 'le', 'lo', 'lwa', 'hha', 'hhu', 'hhi', 'hhaa', 'hhee', 'hhe', 'hho', 'hhwa', 'ma', 'mu', 'mi', 'maa', 'mee', 'me', 'mo', 'mwa', 'sza', 'szu', 'szi', 'szaa', 'szee', 'sze', 'szo', 'szwa', 'ra', 'ru', 'ri', 'raa', 'ree', 're', 'ro', 'rwa', 'sa', 'su', 'si', 'saa', 'see', 'se', 'so', 'swa', 'sha', 'shu', 'shi', 'shaa', 'shee', 'she', 'sho', 'shwa', 'qa', 'qu', 'qi', 'qaa', 'qee', 'qe', 'qo', '[?]', 'qwa', '[?]', 'qwi', 'qwaa', 'qwee', 'qwe', '[?]', '[?]', 'qha', 'qhu', 'qhi', 'qhaa', 'qhee', 'qhe', 'qho', '[?]', 'qhwa', '[?]', 'qhwi', 'qhwaa', 'qhwee', 'qhwe', '[?]', '[?]', 'ba', 'bu', 'bi', 'baa', 'bee', 'be', 'bo', 'bwa', 'va', 'vu', 'vi', 'vaa', 'vee', 've', 'vo', 'vwa', 'ta', 'tu', 'ti', 'taa', 'tee', 'te', 'to', 'twa', 'ca', 'cu', 'ci', 'caa', 'cee', 'ce', 'co', 'cwa', 'xa', 'xu', 'xi', 'xaa', 'xee', 'xe', 'xo', '[?]', 'xwa', '[?]', 'xwi', 'xwaa', 'xwee', 'xwe', '[?]', '[?]', 'na', 'nu', 'ni', 'naa', 'nee', 'ne', 'no', 'nwa', 'nya', 'nyu', 'nyi', 'nyaa', 'nyee', 'nye', 'nyo', 'nywa', '\'a', '\'u', '[?]', '\'aa', '\'ee', '\'e', '\'o', '\'wa', 'ka', 'ku', 'ki', 'kaa', 'kee', 'ke', 'ko', '[?]', 'kwa', '[?]', 'kwi', 'kwaa', 'kwee', 'kwe', '[?]', '[?]', 'kxa', 'kxu', 'kxi', 'kxaa', 'kxee', 'kxe', 'kxo', '[?]', 'kxwa', '[?]', 'kxwi', 'kxwaa', 'kxwee', 'kxwe', '[?]', '[?]', 'wa', 'wu', 'wi', 'waa', 'wee', 'we', 'wo', '[?]', '`a', '`u', '`i', '`aa', '`ee', '`e', '`o', '[?]', 'za', 'zu', 'zi', 'zaa', 'zee', 'ze', 'zo', 'zwa', 'zha', 'zhu', 'zhi', 'zhaa', 'zhee', 'zhe', 'zho', 'zhwa', 'ya', 'yu', 'yi', 'yaa', 'yee', 'ye', 'yo', '[?]', 'da', 'du', 'di', 'daa', 'dee', 'de', 'do', 'dwa', 'dda', 'ddu', 'ddi', 'ddaa', 'ddee', 'dde', 'ddo', 'ddwa'];
<?php return ['hwen', 'hwenj', 'hwenh', 'hwed', 'hwel', 'hwelg', 'hwelm', 'hwelb', 'hwels', 'hwelt', 'hwelp', 'hwelh', 'hwem', 'hweb', 'hwebs', 'hwes', 'hwess', 'hweng', 'hwej', 'hwec', 'hwek', 'hwet', 'hwep', 'hweh', 'hwi', 'hwig', 'hwigg', 'hwigs', 'hwin', 'hwinj', 'hwinh', 'hwid', 'hwil', 'hwilg', 'hwilm', 'hwilb', 'hwils', 'hwilt', 'hwilp', 'hwilh', 'hwim', 'hwib', 'hwibs', 'hwis', 'hwiss', 'hwing', 'hwij', 'hwic', 'hwik', 'hwit', 'hwip', 'hwih', 'hyu', 'hyug', 'hyugg', 'hyugs', 'hyun', 'hyunj', 'hyunh', 'hyud', 'hyul', 'hyulg', 'hyulm', 'hyulb', 'hyuls', 'hyult', 'hyulp', 'hyulh', 'hyum', 'hyub', 'hyubs', 'hyus', 'hyuss', 'hyung', 'hyuj', 'hyuc', 'hyuk', 'hyut', 'hyup', 'hyuh', 'heu', 'heug', 'heugg', 'heugs', 'heun', 'heunj', 'heunh', 'heud', 'heul', 'heulg', 'heulm', 'heulb', 'heuls', 'heult', 'heulp', 'heulh', 'heum', 'heub', 'heubs', 'heus', 'heuss', 'heung', 'heuj', 'heuc', 'heuk', 'heut', 'heup', 'heuh', 'hyi', 'hyig', 'hyigg', 'hyigs', 'hyin', 'hyinj', 'hyinh', 'hyid', 'hyil', 'hyilg', 'hyilm', 'hyilb', 'hyils', 'hyilt', 'hyilp', 'hyilh', 'hyim', 'hyib', 'hyibs', 'hyis', 'hyiss', 'hying', 'hyij', 'hyic', 'hyik', 'hyit', 'hyip', 'hyih', 'hi', 'hig', 'higg', 'higs', 'hin', 'hinj', 'hinh', 'hid', 'hil', 'hilg', 'hilm', 'hilb', 'hils', 'hilt', 'hilp', 'hilh', 'him', 'hib', 'hibs', 'his', 'hiss', 'hing', 'hij', 'hic', 'hik', 'hit', 'hip', 'hih', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]'];
<?php return ['A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'N', 'n', 'N', 'n', 'N', 'n', '\'n', 'ng', 'NG', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'b', 'B', 'B', 'b', '6', '6', 'O', 'C', 'c', 'D', 'D', 'D', 'd', 'd', '3', '@', 'E', 'F', 'f', 'G', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'l', 'W', 'N', 'n', 'O', 'O', 'o', 'OI', 'oi', 'P', 'p', 'YR', '2', '2', 'SH', 'sh', 't', 'T', 't', 'T', 'U', 'u', 'Y', 'V', 'Y', 'y', 'Z', 'z', 'ZH', 'ZH', 'zh', 'zh', '2', '5', '5', 'ts', 'w', '|', '||', '|=', '!', 'DZ', 'Dz', 'dz', 'LJ', 'Lj', 'lj', 'NJ', 'Nj', 'nj', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', '@', 'A', 'a', 'A', 'a', 'AE', 'ae', 'G', 'g', 'G', 'g', 'K', 'k', 'O', 'o', 'O', 'o', 'ZH', 'zh', 'j', 'DZ', 'Dz', 'dz', 'G', 'g', 'HV', 'W', 'N', 'n', 'A', 'a', 'AE', 'ae', 'O', 'o'];
<?php return ['dit', 'dix', 'di', 'dip', 'diex', 'die', 'diep', 'dat', 'dax', 'da', 'dap', 'duox', 'duo', 'dot', 'dox', 'do', 'dop', 'dex', 'de', 'dep', 'dut', 'dux', 'du', 'dup', 'durx', 'dur', 'tit', 'tix', 'ti', 'tip', 'tiex', 'tie', 'tiep', 'tat', 'tax', 'ta', 'tap', 'tuot', 'tuox', 'tuo', 'tuop', 'tot', 'tox', 'to', 'top', 'tex', 'te', 'tep', 'tut', 'tux', 'tu', 'tup', 'turx', 'tur', 'ddit', 'ddix', 'ddi', 'ddip', 'ddiex', 'ddie', 'ddiep', 'ddat', 'ddax', 'dda', 'ddap', 'dduox', 'dduo', 'dduop', 'ddot', 'ddox', 'ddo', 'ddop', 'ddex', 'dde', 'ddep', 'ddut', 'ddux', 'ddu', 'ddup', 'ddurx', 'ddur', 'ndit', 'ndix', 'ndi', 'ndip', 'ndiex', 'ndie', 'ndat', 'ndax', 'nda', 'ndap', 'ndot', 'ndox', 'ndo', 'ndop', 'ndex', 'nde', 'ndep', 'ndut', 'ndux', 'ndu', 'ndup', 'ndurx', 'ndur', 'hnit', 'hnix', 'hni', 'hnip', 'hniet', 'hniex', 'hnie', 'hniep', 'hnat', 'hnax', 'hna', 'hnap', 'hnuox', 'hnuo', 'hnot', 'hnox', 'hnop', 'hnex', 'hne', 'hnep', 'hnut', 'nit', 'nix', 'ni', 'nip', 'niex', 'nie', 'niep', 'nax', 'na', 'nap', 'nuox', 'nuo', 'nuop', 'not', 'nox', 'no', 'nop', 'nex', 'ne', 'nep', 'nut', 'nux', 'nu', 'nup', 'nurx', 'nur', 'hlit', 'hlix', 'hli', 'hlip', 'hliex', 'hlie', 'hliep', 'hlat', 'hlax', 'hla', 'hlap', 'hluox', 'hluo', 'hluop', 'hlox', 'hlo', 'hlop', 'hlex', 'hle', 'hlep', 'hlut', 'hlux', 'hlu', 'hlup', 'hlurx', 'hlur', 'hlyt', 'hlyx', 'hly', 'hlyp', 'hlyrx', 'hlyr', 'lit', 'lix', 'li', 'lip', 'liet', 'liex', 'lie', 'liep', 'lat', 'lax', 'la', 'lap', 'luot', 'luox', 'luo', 'luop', 'lot', 'lox', 'lo', 'lop', 'lex', 'le', 'lep', 'lut', 'lux', 'lu', 'lup', 'lurx', 'lur', 'lyt', 'lyx', 'ly', 'lyp', 'lyrx', 'lyr', 'git', 'gix', 'gi', 'gip', 'giet', 'giex', 'gie', 'giep', 'gat', 'gax', 'ga', 'gap', 'guot', 'guox', 'guo', 'guop', 'got', 'gox', 'go', 'gop', 'get', 'gex', 'ge', 'gep', 'gut', 'gux', 'gu', 'gup', 'gurx', 'gur', 'kit', 'kix', 'ki', 'kip', 'kiex', 'kie', 'kiep', 'kat'];
<?php return ['jjyim', 'jjyib', 'jjyibs', 'jjyis', 'jjyiss', 'jjying', 'jjyij', 'jjyic', 'jjyik', 'jjyit', 'jjyip', 'jjyih', 'jji', 'jjig', 'jjigg', 'jjigs', 'jjin', 'jjinj', 'jjinh', 'jjid', 'jjil', 'jjilg', 'jjilm', 'jjilb', 'jjils', 'jjilt', 'jjilp', 'jjilh', 'jjim', 'jjib', 'jjibs', 'jjis', 'jjiss', 'jjing', 'jjij', 'jjic', 'jjik', 'jjit', 'jjip', 'jjih', 'ca', 'cag', 'cagg', 'cags', 'can', 'canj', 'canh', 'cad', 'cal', 'calg', 'calm', 'calb', 'cals', 'calt', 'calp', 'calh', 'cam', 'cab', 'cabs', 'cas', 'cass', 'cang', 'caj', 'cac', 'cak', 'cat', 'cap', 'cah', 'cae', 'caeg', 'caegg', 'caegs', 'caen', 'caenj', 'caenh', 'caed', 'cael', 'caelg', 'caelm', 'caelb', 'caels', 'caelt', 'caelp', 'caelh', 'caem', 'caeb', 'caebs', 'caes', 'caess', 'caeng', 'caej', 'caec', 'caek', 'caet', 'caep', 'caeh', 'cya', 'cyag', 'cyagg', 'cyags', 'cyan', 'cyanj', 'cyanh', 'cyad', 'cyal', 'cyalg', 'cyalm', 'cyalb', 'cyals', 'cyalt', 'cyalp', 'cyalh', 'cyam', 'cyab', 'cyabs', 'cyas', 'cyass', 'cyang', 'cyaj', 'cyac', 'cyak', 'cyat', 'cyap', 'cyah', 'cyae', 'cyaeg', 'cyaegg', 'cyaegs', 'cyaen', 'cyaenj', 'cyaenh', 'cyaed', 'cyael', 'cyaelg', 'cyaelm', 'cyaelb', 'cyaels', 'cyaelt', 'cyaelp', 'cyaelh', 'cyaem', 'cyaeb', 'cyaebs', 'cyaes', 'cyaess', 'cyaeng', 'cyaej', 'cyaec', 'cyaek', 'cyaet', 'cyaep', 'cyaeh', 'ceo', 'ceog', 'ceogg', 'ceogs', 'ceon', 'ceonj', 'ceonh', 'ceod', 'ceol', 'ceolg', 'ceolm', 'ceolb', 'ceols', 'ceolt', 'ceolp', 'ceolh', 'ceom', 'ceob', 'ceobs', 'ceos', 'ceoss', 'ceong', 'ceoj', 'ceoc', 'ceok', 'ceot', 'ceop', 'ceoh', 'ce', 'ceg', 'cegg', 'cegs', 'cen', 'cenj', 'cenh', 'ced', 'cel', 'celg', 'celm', 'celb', 'cels', 'celt', 'celp', 'celh', 'cem', 'ceb', 'cebs', 'ces', 'cess', 'ceng', 'cej', 'cec', 'cek', 'cet', 'cep', 'ceh', 'cyeo', 'cyeog', 'cyeogg', 'cyeogs', 'cyeon', 'cyeonj', 'cyeonh', 'cyeod', 'cyeol', 'cyeolg', 'cyeolm', 'cyeolb', 'cyeols', 'cyeolt', 'cyeolp', 'cyeolh', 'cyeom', 'cyeob', 'cyeobs', 'cyeos', 'cyeoss', 'cyeong', 'cyeoj', 'cyeoc', 'cyeok', 'cyeot', 'cyeop', 'cyeoh', 'cye', 'cyeg', 'cyegg', 'cyegs', 'cyen', 'cyenj', 'cyenh', 'cyed', 'cyel', 'cyelg', 'cyelm', 'cyelb', 'cyels', 'cyelt', 'cyelp', 'cyelh', 'cyem', 'cyeb', 'cyebs', 'cyes'];
<?php return ['Xu ', 'Ji ', 'Mu ', 'Chen ', 'Xiao ', 'Zha ', 'Ting ', 'Zhen ', 'Pei ', 'Mei ', 'Ling ', 'Qi ', 'Chou ', 'Huo ', 'Sha ', 'Fei ', 'Weng ', 'Zhan ', 'Yin ', 'Ni ', 'Chou ', 'Tun ', 'Lin ', '[?] ', 'Dong ', 'Ying ', 'Wu ', 'Ling ', 'Shuang ', 'Ling ', 'Xia ', 'Hong ', 'Yin ', 'Mo ', 'Mai ', 'Yun ', 'Liu ', 'Meng ', 'Bin ', 'Wu ', 'Wei ', 'Huo ', 'Yin ', 'Xi ', 'Yi ', 'Ai ', 'Dan ', 'Deng ', 'Xian ', 'Yu ', 'Lu ', 'Long ', 'Dai ', 'Ji ', 'Pang ', 'Yang ', 'Ba ', 'Pi ', 'Wei ', '[?] ', 'Xi ', 'Ji ', 'Mai ', 'Meng ', 'Meng ', 'Lei ', 'Li ', 'Huo ', 'Ai ', 'Fei ', 'Dai ', 'Long ', 'Ling ', 'Ai ', 'Feng ', 'Li ', 'Bao ', '[?] ', 'He ', 'He ', 'Bing ', 'Qing ', 'Qing ', 'Jing ', 'Tian ', 'Zhen ', 'Jing ', 'Cheng ', 'Qing ', 'Jing ', 'Jing ', 'Dian ', 'Jing ', 'Tian ', 'Fei ', 'Fei ', 'Kao ', 'Mi ', 'Mian ', 'Mian ', 'Pao ', 'Ye ', 'Tian ', 'Hui ', 'Ye ', 'Ge ', 'Ding ', 'Cha ', 'Jian ', 'Ren ', 'Di ', 'Du ', 'Wu ', 'Ren ', 'Qin ', 'Jin ', 'Xue ', 'Niu ', 'Ba ', 'Yin ', 'Sa ', 'Na ', 'Mo ', 'Zu ', 'Da ', 'Ban ', 'Yi ', 'Yao ', 'Tao ', 'Tuo ', 'Jia ', 'Hong ', 'Pao ', 'Yang ', 'Tomo ', 'Yin ', 'Jia ', 'Tao ', 'Ji ', 'Xie ', 'An ', 'An ', 'Hen ', 'Gong ', 'Kohaze ', 'Da ', 'Qiao ', 'Ting ', 'Wan ', 'Ying ', 'Sui ', 'Tiao ', 'Qiao ', 'Xuan ', 'Kong ', 'Beng ', 'Ta ', 'Zhang ', 'Bing ', 'Kuo ', 'Ju ', 'La ', 'Xie ', 'Rou ', 'Bang ', 'Yi ', 'Qiu ', 'Qiu ', 'He ', 'Xiao ', 'Mu ', 'Ju ', 'Jian ', 'Bian ', 'Di ', 'Jian ', 'On ', 'Tao ', 'Gou ', 'Ta ', 'Bei ', 'Xie ', 'Pan ', 'Ge ', 'Bi ', 'Kuo ', 'Tang ', 'Lou ', 'Gui ', 'Qiao ', 'Xue ', 'Ji ', 'Jian ', 'Jiang ', 'Chan ', 'Da ', 'Huo ', 'Xian ', 'Qian ', 'Du ', 'Wa ', 'Jian ', 'Lan ', 'Wei ', 'Ren ', 'Fu ', 'Mei ', 'Juan ', 'Ge ', 'Wei ', 'Qiao ', 'Han ', 'Chang ', '[?] ', 'Rou ', 'Xun ', 'She ', 'Wei ', 'Ge ', 'Bei ', 'Tao ', 'Gou ', 'Yun ', '[?] ', 'Bi ', 'Wei ', 'Hui ', 'Du ', 'Wa ', 'Du ', 'Wei ', 'Ren ', 'Fu ', 'Han ', 'Wei ', 'Yun ', 'Tao ', 'Jiu ', 'Jiu ', 'Xian ', 'Xie ', 'Xian ', 'Ji ', 'Yin ', 'Za ', 'Yun ', 'Shao ', 'Le ', 'Peng ', 'Heng ', 'Ying ', 'Yun ', 'Peng ', 'Yin ', 'Yin ', 'Xiang '];
<?php return ['Xi ', 'Kao ', 'Lang ', 'Fu ', 'Ze ', 'Shui ', 'Lu ', 'Kun ', 'Gan ', 'Geng ', 'Ti ', 'Cheng ', 'Tu ', 'Shao ', 'Shui ', 'Ya ', 'Lun ', 'Lu ', 'Gu ', 'Zuo ', 'Ren ', 'Zhun ', 'Bang ', 'Bai ', 'Ji ', 'Zhi ', 'Zhi ', 'Kun ', 'Leng ', 'Peng ', 'Ke ', 'Bing ', 'Chou ', 'Zu ', 'Yu ', 'Su ', 'Lue ', '[?] ', 'Yi ', 'Xi ', 'Bian ', 'Ji ', 'Fu ', 'Bi ', 'Nuo ', 'Jie ', 'Zhong ', 'Zong ', 'Xu ', 'Cheng ', 'Dao ', 'Wen ', 'Lian ', 'Zi ', 'Yu ', 'Ji ', 'Xu ', 'Zhen ', 'Zhi ', 'Dao ', 'Jia ', 'Ji ', 'Gao ', 'Gao ', 'Gu ', 'Rong ', 'Sui ', 'You ', 'Ji ', 'Kang ', 'Mu ', 'Shan ', 'Men ', 'Zhi ', 'Ji ', 'Lu ', 'Su ', 'Ji ', 'Ying ', 'Wen ', 'Qiu ', 'Se ', '[?] ', 'Yi ', 'Huang ', 'Qie ', 'Ji ', 'Sui ', 'Xiao ', 'Pu ', 'Jiao ', 'Zhuo ', 'Tong ', 'Sai ', 'Lu ', 'Sui ', 'Nong ', 'Se ', 'Hui ', 'Rang ', 'Nuo ', 'Yu ', 'Bin ', 'Ji ', 'Tui ', 'Wen ', 'Cheng ', 'Huo ', 'Gong ', 'Lu ', 'Biao ', '[?] ', 'Rang ', 'Zhuo ', 'Li ', 'Zan ', 'Xue ', 'Wa ', 'Jiu ', 'Qiong ', 'Xi ', 'Qiong ', 'Kong ', 'Yu ', 'Sen ', 'Jing ', 'Yao ', 'Chuan ', 'Zhun ', 'Tu ', 'Lao ', 'Qie ', 'Zhai ', 'Yao ', 'Bian ', 'Bao ', 'Yao ', 'Bing ', 'Wa ', 'Zhu ', 'Jiao ', 'Qiao ', 'Diao ', 'Wu ', 'Gui ', 'Yao ', 'Zhi ', 'Chuang ', 'Yao ', 'Tiao ', 'Jiao ', 'Chuang ', 'Jiong ', 'Xiao ', 'Cheng ', 'Kou ', 'Cuan ', 'Wo ', 'Dan ', 'Ku ', 'Ke ', 'Zhui ', 'Xu ', 'Su ', 'Guan ', 'Kui ', 'Dou ', '[?] ', 'Yin ', 'Wo ', 'Wa ', 'Ya ', 'Yu ', 'Ju ', 'Qiong ', 'Yao ', 'Yao ', 'Tiao ', 'Chao ', 'Yu ', 'Tian ', 'Diao ', 'Ju ', 'Liao ', 'Xi ', 'Wu ', 'Kui ', 'Chuang ', 'Zhao ', '[?] ', 'Kuan ', 'Long ', 'Cheng ', 'Cui ', 'Piao ', 'Zao ', 'Cuan ', 'Qiao ', 'Qiong ', 'Dou ', 'Zao ', 'Long ', 'Qie ', 'Li ', 'Chu ', 'Shi ', 'Fou ', 'Qian ', 'Chu ', 'Hong ', 'Qi ', 'Qian ', 'Gong ', 'Shi ', 'Shu ', 'Miao ', 'Ju ', 'Zhan ', 'Zhu ', 'Ling ', 'Long ', 'Bing ', 'Jing ', 'Jing ', 'Zhang ', 'Yi ', 'Si ', 'Jun ', 'Hong ', 'Tong ', 'Song ', 'Jing ', 'Diao ', 'Yi ', 'Shu ', 'Jing ', 'Qu ', 'Jie ', 'Ping ', 'Duan ', 'Shao ', 'Zhuan ', 'Ceng ', 'Deng ', 'Cui ', 'Huai ', 'Jing ', 'Kan ', 'Jing ', 'Zhu ', 'Zhu ', 'Le ', 'Peng ', 'Yu ', 'Chi ', 'Gan '];
<?php

return [
    // Dutch (Flemish)
    'nl' => [
        '=' => ' gelijk ',
        '%' => ' procent ',
        '∑' => ' som ',
        '∆' => ' delta ',
        '∞' => ' oneindig ',
        '♥' => ' love ',
        '&' => ' en ',
        '+' => ' plus ',
    ],
    // Italian
    'it' => [
        '=' => ' uguale ',
        '%' => ' percent ',
        '∑' => ' somma ',
        '∆' => ' delta ',
        '∞' => ' infinito ',
        '♥' => ' amore ',
        '&' => ' e ',
        '+' => ' piu ',
    ],
    // Macedonian
    'mk' => [
        '=' => ' ednakva ',
        '%' => ' procenti ',
        '∑' => ' zbir ',
        '∆' => ' delta ',
        '∞' => ' beskonecnost ',
        '♥' => ' loveubov ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Portuguese (Brazil)
    'pt' => [
        '=' => ' igual ',
        '%' => ' por cento ',
        '∑' => ' soma ',
        '∆' => ' delta ',
        '∞' => ' infinito ',
        '♥' => ' amor ',
        '&' => ' e ',
        '+' => ' mais ',
    ],
    // Greek(lish) (Elláda)
    'el__greeklish' => [
        '=' => ' isos ',
        '%' => ' tois ekato ',
        '∑' => ' athroisma ',
        '∆' => ' delta ',
        '∞' => ' apeiro ',
        '♥' => ' agape ',
        '&' => ' kai ',
        '+' => ' syn ',
    ],
    // Greek (Elláda)
    'el' => [
        '=' => ' isos ',
        '%' => ' tois ekato ',
        '∑' => ' athroisma ',
        '∆' => ' delta ',
        '∞' => ' apeiro ',
        '♥' => ' agape ',
        '&' => ' kai ',
        '+' => ' syn ',
    ],
    // Hindi
    'hi' => [
        '=' => ' samana ',
        '%' => ' paratisata ',
        '∑' => ' yoga ',
        '∆' => ' dalata ',
        '∞' => ' anata ',
        '♥' => ' payara ',
        '&' => ' aura ',
        '+' => ' palasa ',
    ],
    // Armenian
    'hy' => [
        '=' => ' havasar ',
        '%' => ' tvokvos ',
        '∑' => ' gvoumar ',
        '∆' => ' delta ',
        '∞' => ' ansahmanvouthyvoun ',
        '♥' => ' ser ',
        '&' => ' ev ',
        '+' => ' gvoumarats ',
    ],
    // Swedish
    'sv' => [
        '=' => ' lika ',
        '%' => ' procent ',
        '∑' => ' summa ',
        '∆' => ' delta ',
        '∞' => ' oandlighet ',
        '♥' => ' alskar ',
        '&' => ' och ',
        '+' => ' plus ',
    ],
    // Turkmen
    'tk' => [
        '=' => ' den ',
        '%' => ' yuzde ',
        '∑' => ' jem ',
        '∆' => ' delta ',
        '∞' => ' mudimilik ',
        '♥' => ' soygi ',
        '&' => ' we ',
        '+' => ' yzy ',
    ],
    // Turkish
    'tr' => [
        '=' => ' esit ',
        '%' => ' yuzde ',
        '∑' => ' Toplam ',
        '∆' => ' delta ',
        '∞' => ' sonsuzluk ',
        '♥' => ' ask ',
        '&' => ' ve ',
        '+' => ' arti ',
    ],
    // Bulgarian
    'bg' => [
        '=' => ' raven ',
        '%' => ' na sto ',
        '∑' => ' suma ',
        '∆' => ' delta ',
        '∞' => ' bezkrajnost ',
        '♥' => ' obicam ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Hungarian
    'hu' => [
        '=' => ' Egyenlo ',
        '%' => ' Szazalek ',
        '∑' => ' osszeg ',
        '∆' => ' delta ',
        '∞' => ' vegtelenitett ',
        '♥' => ' love ',
        '&' => ' Es ',
        '+' => ' Plusz ',
    ],
    // Myanmar (Burmese)
    'my' => [
        '=' => ' ttn:ttnnym? ',
        '%' => ' raakhngnn:k ',
        '∑' => ' ld ',
        '∆' => ' m?cwk?n:pe? ',
        '∞' => ' ach:m ',
        '♥' => ' mettttaa ',
        '&' => ' n ',
        '+' => ' ape?ng: ',
    ],
    // Croatian (Hrvatska)
    'hr' => [
        '=' => ' Jednaki ',
        '%' => ' Posto ',
        '∑' => ' zbroj ',
        '∆' => ' Delta ',
        '∞' => ' beskonacno ',
        '♥' => ' ljubav ',
        '&' => ' I ',
        '+' => ' Plus ',
    ],
    // Finnish
    'fi' => [
        '=' => ' Sama ',
        '%' => ' Prosenttia ',
        '∑' => ' sum ',
        '∆' => ' delta ',
        '∞' => ' aareton ',
        '♥' => ' rakkautta ',
        '&' => ' Ja ',
        '+' => ' Plus ',
    ],
    // Georgian (Kartvelian)
    'ka' => [
        '=' => ' tanasts\'ori ',
        '%' => ' p\'rotsent\'i ',
        '∑' => ' tankha ',
        '∆' => ' delt\'a ',
        '∞' => ' usasrulo ',
        '♥' => ' siq\'varuli ',
        '&' => ' da ',
        '+' => ' p\'lus ',
    ],
    // Russian
    'ru' => [
        '=' => ' ravnyj ',
        '%' => ' procent ',
        '∑' => ' summa ',
        '∆' => ' del\'ta ',
        '∞' => ' beskonecnost\' ',
        '♥' => ' lublu ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Russian - GOST 7.79-2000(B)
    'ru__gost_2000_b' => [
        '=' => ' ravnyj ',
        '%' => ' procent ',
        '∑' => ' summa ',
        '∆' => ' del\'ta ',
        '∞' => ' beskonecnost\' ',
        '♥' => ' lublu ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Russian - Passport (2013), ICAO
    'ru__passport_2013' => [
        '=' => ' ravnyj ',
        '%' => ' procent ',
        '∑' => ' summa ',
        '∆' => ' del\'ta ',
        '∞' => ' beskonecnost\' ',
        '♥' => ' lublu ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Ukrainian
    'uk' => [
        '=' => ' rivnij ',
        '%' => ' vidsotkiv ',
        '∑' => ' suma ',
        '∆' => ' del\'ta ',
        '∞' => ' neskincennist\' ',
        '♥' => ' lubov ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Kazakh
    'kk' => [
        '=' => ' ten\' ',
        '%' => ' Pajyzdar ',
        '∑' => ' zalpy ',
        '∆' => ' ajyrmasylyk, ',
        '∞' => ' seksiz ',
        '♥' => ' mahabbat ',
        '&' => ' z@ne ',
        '+' => ' plus ',
    ],
    // Czech
    'cs' => [
        '=' => ' rovnat se ',
        '%' => ' procento ',
        '∑' => ' soucet ',
        '∆' => ' delta ',
        '∞' => ' nekonecno ',
        '♥' => ' laska ',
        '&' => ' a ',
        '+' => ' plus ',
    ],
    // Danish
    'da' => [
        '=' => ' Lige ',
        '%' => ' Prozent ',
        '∑' => ' sum ',
        '∆' => ' delta ',
        '∞' => ' uendelig ',
        '♥' => ' kaerlighed ',
        '&' => ' Og ',
        '+' => ' Plus ',
    ],
    // Polish
    'pl' => [
        '=' => ' rowny ',
        '%' => ' procent ',
        '∑' => ' suma ',
        '∆' => ' delta ',
        '∞' => ' nieskonczonosc ',
        '♥' => ' milosc ',
        '&' => ' i ',
        '+' => ' plus ',
    ],
    // Romanian
    'ro' => [
        '=' => ' egal ',
        '%' => ' la suta ',
        '∑' => ' suma ',
        '∆' => ' delta ',
        '∞' => ' infinit ',
        '♥' => ' dragoste ',
        '&' => ' si ',
        '+' => ' la care se adauga ',
    ],
    // Esperanto
    'eo' => [
        '=' => ' Egalaj ',
        '%' => ' Procento ',
        '∑' => ' sumo ',
        '∆' => ' delto ',
        '∞' => ' senfina ',
        '♥' => ' amo ',
        '&' => ' Kaj ',
        '+' => ' Pli ',
    ],
    // Estonian
    'et' => [
        '=' => ' Vordsed ',
        '%' => ' Protsenti ',
        '∑' => ' summa ',
        '∆' => ' o ',
        '∞' => ' loputut ',
        '♥' => ' armastus ',
        '&' => ' Ja ',
        '+' => ' Pluss ',
    ],
    // Latvian
    'lv' => [
        '=' => ' vienads ',
        '%' => ' procents ',
        '∑' => ' summa ',
        '∆' => ' delta ',
        '∞' => ' bezgaliba ',
        '♥' => ' milestiba ',
        '&' => ' un ',
        '+' => ' pluss ',
    ],
    // Lithuanian
    'lt' => [
        '=' => ' lygus ',
        '%' => ' procentu ',
        '∑' => ' suma ',
        '∆' => ' delta ',
        '∞' => ' begalybe ',
        '♥' => ' meile ',
        '&' => ' ir ',
        '+' => ' plius ',
    ],
    // Norwegian
    'no' => [
        '=' => ' Lik ',
        '%' => ' Prosent ',
        '∑' => ' sum ',
        '∆' => ' delta ',
        '∞' => ' uendelig ',
        '♥' => ' kjaerlighet ',
        '&' => ' Og ',
        '+' => ' Pluss ',
    ],
    // Vietnamese
    'vi' => [
        '=' => ' cong bang ',
        '%' => ' phan tram ',
        '∑' => ' tong so ',
        '∆' => ' dong bang ',
        '∞' => ' vo cuc ',
        '♥' => ' Yeu ',
        '&' => ' va ',
        '+' => ' them ',
    ],
    // Arabic
    'ar' => [
        '=' => ' mtsawy ',
        '%' => ' nsbh mywyh ',
        '∑' => ' mjmw\' ',
        '∆' => ' dlta ',
        '∞' => ' ma la nhayt ',
        '♥' => ' hb ',
        '&' => ' w ',
        '+' => ' zayd ',
    ],
    // Persian (Farsi)
    'fa' => [
        '=' => ' brabr ',
        '%' => ' dr sd ',
        '∑' => ' mjmw\' ',
        '∆' => ' dlta ',
        '∞' => ' by nhayt ',
        '♥' => ' \'shq ',
        '&' => ' w ',
        '+' => ' bh \'lawh ',
    ],
    // Serbian
    'sr' => [
        '=' => ' jednak ',
        '%' => ' procenat ',
        '∑' => ' zbir ',
        '∆' => ' delta ',
        '∞' => ' beskraj ',
        '♥' => ' lubav ',
        '&' => ' i ',
        '+' => ' vise ',
    ],
    // Serbian - Cyrillic
    'sr__cyr' => [
        '=' => ' jednak ',
        '%' => ' procenat ',
        '∑' => ' zbir ',
        '∆' => ' delta ',
        '∞' => ' beskraj ',
        '♥' => ' lubav ',
        '&' => ' i ',
        '+' => ' vise ',
    ],
    // Serbian - Latin
    'sr__lat' => [
        '=' => ' jednak ',
        '%' => ' procenat ',
        '∑' => ' zbir ',
        '∆' => ' delta ',
        '∞' => ' beskraj ',
        '♥' => ' lubav ',
        '&' => ' i ',
        '+' => ' vise ',
    ],
    // Azerbaijani
    'az' => [
        '=' => ' b@rab@r ',
        '%' => ' faiz ',
        '∑' => ' m@bl@g ',
        '∆' => ' delta ',
        '∞' => ' sonsuzluq ',
        '♥' => ' sevgi ',
        '&' => ' v@ ',
        '+' => ' plus ',
    ],
    // Slovak
    'sk' => [
        '=' => ' rovny ',
        '%' => ' percento ',
        '∑' => ' sucet ',
        '∆' => ' delta ',
        '∞' => ' infinity ',
        '♥' => ' milovat ',
        '&' => ' a ',
        '+' => ' viac ',
    ],
    // French
    'fr' => [
        '=' => ' Egal ',
        '%' => ' Pourcentage ',
        '∑' => ' somme ',
        '∆' => ' delta ',
        '∞' => ' infini ',
        '♥' => ' amour ',
        '&' => ' Et ',
        '+' => ' Plus ',
    ],
    // Austrian (French)
    'fr_at' => [
        '=' => ' Egal ',
        '%' => ' Pourcentage ',
        '∑' => ' somme ',
        '∆' => ' delta ',
        '∞' => ' infini ',
        '♥' => ' amour ',
        '&' => ' Et ',
        '+' => ' Plus ',
    ],
    // Switzerland (French)
    'fr_ch' => [
        '=' => ' Egal ',
        '%' => ' Pourcentage ',
        '∑' => ' somme ',
        '∆' => ' delta ',
        '∞' => ' infini ',
        '♥' => ' amour ',
        '&' => ' Et ',
        '+' => ' Plus ',
    ],
    // German
    'de' => [
        '=' => ' gleich ',
        '%' => ' Prozent ',
        '∑' => ' gesamt ',
        '∆' => ' Unterschied ',
        '∞' => ' undendlich ',
        '♥' => ' liebe ',
        '&' => ' und ',
        '+' => ' plus ',
    ],
    // Austrian (German)
    'de_at' => [
        '=' => ' gleich ',
        '%' => ' Prozent ',
        '∑' => ' gesamt ',
        '∆' => ' Unterschied ',
        '∞' => ' undendlich ',
        '♥' => ' liebe ',
        '&' => ' und ',
        '+' => ' plus ',
    ],
    // Switzerland (German)
    'de_ch' => [
        '=' => ' gleich ',
        '%' => ' Prozent ',
        '∑' => ' gesamt ',
        '∆' => ' Unterschied ',
        '∞' => ' undendlich ',
        '♥' => ' liebe ',
        '&' => ' und ',
        '+' => ' plus ',
    ],
    // Bengali (Bangla)
    'bn' => [
        '=' => ' Saman ',
        '%' => ' Satakora ',
        '∑' => ' Samasti ',
        '∆' => ' Badhip ',
        '∞' => ' Ananta ',
        '♥' => ' Valobasa ',
        '&' => ' Abong ',
        '+' => ' Songzojon ',
    ],
    // English
    'en' => [
        '=' => ' equal ',
        '%' => ' percent ',
        '∑' => ' sum ',
        '∆' => ' delta ',
        '∞' => ' infinity ',
        '♥' => ' love ',
        '&' => ' and ',
        '+' => ' plus ',
    ],
    // Currency
    //
    // url: https://en.wikipedia.org/wiki/Currency_symbol
    'currency' => [
        '€'  => ' Euro ',
        '$'  => ' Dollar ',
        '₢'  => ' cruzeiro ',
        '₣'  => ' French franc ',
        '£'  => ' pound ',
        '₤'  => ' lira ', // Italian
        '₶'  => ' livre tournois ',
        'ℳ'  => ' mark ',
        '₥'  => ' mill ',
        '₦'  => ' naira ',
        '₧'  => ' peseta ',
        '₨'  => ' rupee ',
        'රු' => ' rupee ', // Sri Lankan
        'ரூ' => ' rupee ', // Sri Lankan
        '௹'  => ' rupee ', // Tamil
        'रू' => ' rupee ', // Nepalese
        '₹'  => ' rupee ', // Indian
        '૱'  => ' rupee ', // Gujarat
        '₩'  => ' won ',
        '₪'  => ' new shequel ',
        '₸'  => ' tenge ',
        '₫'  => ' dong ',
        '֏'  => ' dram ',
        '₭'  => ' kip ',
        '₺'  => ' lira ', // Turkish
        '₼'  => ' manat ',
        '₮'  => ' tugrik ',
        '₯'  => ' drachma ',
        '₰'  => ' pfennig ',
        '₷'  => ' spesmilo ',
        '₱'  => ' peso ', // Philippine
        '﷼‎' => ' riyal ',
        '₲'  => ' guarani ',
        '₾'  => ' lari ',
        '₳'  => ' austral ',
        '₴'  => ' hryvnia ',
        '₽'  => ' ruble ',
        '₵'  => ' cedi ',
        '₡'  => ' colon ',
        '¢'  => ' cent ',
        '¥'  => ' yen ',
        '円'  => ' yen ',
        '৳'  => ' taka ',
        '元'  => ' yuan ',
        '﷼'  => ' riyal ',
        '៛'  => ' riel ',
        '₠'  => ' European Currency ',
        '¤'  => ' currency ',
        '฿'  => ' baht ',
        '؋'  => ' afghani ',
    ],
    // Temperature
    //
    // url: https://en.wikipedia.org/wiki/Conversion_of_units_of_temperature
    'temperature' => [
        '°De' => ' Delisle ',
        '°Re' => ' Reaumur ', // Réaumur
        '°Ro' => ' Romer ', // Rømer
        '°R'  => ' Rankine ',
        '°C'  => ' Celsius ',
        '°F'  => ' Fahrenheit ',
        '°N'  => ' Newton ',
    ],
    'latin_symbols' => [
        '=' => '=',
        '%' => '%',
        '∑' => '∑',
        '∆' => '∆',
        '∞' => '∞',
        '♥' => '♥',
        '&' => '&',
        '+' => '+',
        // ---
        '©' => ' (c) ',
        '®' => ' (r) ',
        '@' => ' (at) ',
        '№' => ' No. ',
        '℞' => ' Rx ',
        '［' => '[',
        '＼' => '\\',
        '］' => ']',
        '＾' => '^',
        '＿' => '_',
        '｀' => '`',
        '‐' => '-',
        '‑' => '-',
        '‒' => '-',
        '–' => '-',
        '−' => '-',
        '—' => '-',
        '―' => '-',
        '﹘' => '-',
        '│' => '|',
        '∖' => '\\',
        '∕' => '/',
        '⁄' => '/',
        '￩' => '<-',
        '￫' => '->',
        '￪' => '|',
        '￬' => '|',
        '⁅' => '[',
        '⁆' => ']',
        '⁎' => '*',
        '、' => ',',
        '。' => '.',
        '〈' => '<',
        '〉' => '>',
        '《' => '<<',
        '》' => '>>',
        '〔' => '[',
        '〕' => ']',
        '〘' => '[',
        '〙' => ']',
        '〚' => '[',
        '〛' => ']',
        '﹝' => '[',
        '﹞' => ']',
        '︹' => '[',
        '︺' => ']',
        '﹇' => '[',
        '﹈' => ']',
        '︐' => ',',
        '︑' => ',',
        '︒' => '.',
        '︓' => ':',
        '︔' => ';',
        '︕' => '!',
        '︖' => '?',
        '︙' => '...',
        '︰' => '..',
        '︵' => '(',
        '︶' => ')',
        '﹙' => '(',
        '﹚' => ')',
        '︷' => '{',
        '︸' => '}',
        '﹛' => '{',
        '﹜' => '}',
        '︽' => '<<',
        '︾' => '>>',
        '︿' => '<',
        '﹀' => '>',
        '×' => '*',
        '÷' => '/',
        '≪' => '<<',
        '≫' => '>>',
        '⦅' => '((',
        '⦆' => '))',
        '〇' => '0',
        '′' => '\'',
        '〝' => '"',
        '〞' => '"',
        '«' => '<<',
        '»' => '>>',
        '‘' => "'",
        '’' => "'",
        '‚' => ',',
        '‛' => "'",
        '“' => '"',
        '”' => '"',
        '„' => '"',
        '‟' => '"',
        '‹' => '<',
        '›' => '>',
        '․' => '.',
        '‥' => '..',
        '…' => '...',
        '″' => '"',
        '‴' => '\'\'\'',
        '‶' => '``',
        '‷' => '```',
        '‼' => '!!',
        '⁇' => '??',
        '⁈' => '?!',
        '⁉' => '!?',
        '⁗' => '````',
        '⩴' => '::=',
        '⩵' => '==',
        '⩶' => '===',
        '﹔' => ';',
        '﹕' => ':',
        '﹖' => '?',
        '﹗' => '!',
        '﹍' => '_',
        '﹎' => '_',
        '﹏' => '_',
        '﹐' => ',',
        '﹑' => ',',
        '﹒' => '.',
        '﹟' => '#',
        '﹠' => '&',
        '﹡' => '*',
        '﹢' => '+',
        '﹣' => '-',
        '﹤' => '<',
        '﹥' => '>',
        '﹦' => '=',
        '﹨' => '\\',
        '﹩' => '$',
        '﹪' => '%',
        '﹫' => '@',
        '！' => '!',
        '＂' => '"',
        '＃' => '#',
        '＄' => '$',
        '％' => '%',
        '＆' => '&',
        '＇' => '\'',
        '（' => '(',
        '）' => ')',
        '＊' => '*',
        '＋' => '+',
        '，' => ',',
        '－' => '-',
        '．' => '.',
        '／' => '/',
        '：' => ':',
        '；' => ';',
        '＜' => '<',
        '＝' => '=',
        '＞' => '>',
        '？' => '?',
        '＠' => '@',
        '｛' => '{',
        '｜' => '|',
        '｝' => '}',
        '～' => '~',
        '｟' => '((',
        '｠' => '))',
        '￢' => '!',
        '￣' => '-',
        '￤' => '|',
        '￭' => '#',
    ],
];
<?php return ['[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ',', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', ';', '[?]', '[?]', '[?]', '?', '[?]', '', 'a', 'a', 'w\'', '', 'y\'', '', 'b', '@', 't', 'th', 'j', 'H', 'kh', 'd', 'dh', 'r', 'z', 's', 'sh', 'S', 'D', 'T', 'Z', '`', 'G', '[?]', '[?]', '[?]', '[?]', '[?]', '', 'f', 'q', 'k', 'l', 'm', 'n', 'h', 'w', '~', 'y', 'an', 'un', 'in', 'a', 'u', 'i', 'W', '', '', '\'', '\'', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '%', '.', ',', '*', '[?]', '[?]', '', '\'', '\'', '\'', '', '\'', '\'w', '\'u', '\'y', 'tt', 'tth', 'b', 't', 'T', 'p', 'th', 'bh', '\'h', 'H', 'ny', 'dy', 'H', 'ch', 'cch', 'dd', 'D', 'D', 'Dt', 'dh', 'ddh', 'd', 'D', 'D', 'rr', 'R', 'R', 'R', 'R', 'R', 'R', 'j', 'R', 'S', 'S', 'S', 'S', 'S', 'T', 'GH', 'F', 'F', 'F', 'v', 'f', 'ph', 'Q', 'Q', 'kh', 'k', 'K', 'K', 'ng', 'K', 'g', 'G', 'N', 'G', 'G', 'G', 'L', 'L', 'L', 'L', 'N', 'N', 'N', 'N', 'N', 'h', 'Ch', 'hy', 'h', 'H', '@', 'W', 'oe', 'oe', 'u', 'yu', 'yu', 'W', 'v', 'y', 'Y', 'Y', 'W', '', '', 'y', 'y\'', '.', 'ae', '', '', '', '', '', '', '', '@', '#', '', '', '', '', '', '', '', '', '', '', '^', '', '', '', '', '[?]', '[?]', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'Sh', 'D', 'Gh', '&', '+m', 'h'];
<?php return ['hyeo', 'hyeog', 'hyeogg', 'hyeogs', 'hyeon', 'hyeonj', 'hyeonh', 'hyeod', 'hyeol', 'hyeolg', 'hyeolm', 'hyeolb', 'hyeols', 'hyeolt', 'hyeolp', 'hyeolh', 'hyeom', 'hyeob', 'hyeobs', 'hyeos', 'hyeoss', 'hyeong', 'hyeoj', 'hyeoc', 'hyeok', 'hyeot', 'hyeop', 'hyeoh', 'hye', 'hyeg', 'hyegg', 'hyegs', 'hyen', 'hyenj', 'hyenh', 'hyed', 'hyel', 'hyelg', 'hyelm', 'hyelb', 'hyels', 'hyelt', 'hyelp', 'hyelh', 'hyem', 'hyeb', 'hyebs', 'hyes', 'hyess', 'hyeng', 'hyej', 'hyec', 'hyek', 'hyet', 'hyep', 'hyeh', 'ho', 'hog', 'hogg', 'hogs', 'hon', 'honj', 'honh', 'hod', 'hol', 'holg', 'holm', 'holb', 'hols', 'holt', 'holp', 'holh', 'hom', 'hob', 'hobs', 'hos', 'hoss', 'hong', 'hoj', 'hoc', 'hok', 'hot', 'hop', 'hoh', 'hwa', 'hwag', 'hwagg', 'hwags', 'hwan', 'hwanj', 'hwanh', 'hwad', 'hwal', 'hwalg', 'hwalm', 'hwalb', 'hwals', 'hwalt', 'hwalp', 'hwalh', 'hwam', 'hwab', 'hwabs', 'hwas', 'hwass', 'hwang', 'hwaj', 'hwac', 'hwak', 'hwat', 'hwap', 'hwah', 'hwae', 'hwaeg', 'hwaegg', 'hwaegs', 'hwaen', 'hwaenj', 'hwaenh', 'hwaed', 'hwael', 'hwaelg', 'hwaelm', 'hwaelb', 'hwaels', 'hwaelt', 'hwaelp', 'hwaelh', 'hwaem', 'hwaeb', 'hwaebs', 'hwaes', 'hwaess', 'hwaeng', 'hwaej', 'hwaec', 'hwaek', 'hwaet', 'hwaep', 'hwaeh', 'hoe', 'hoeg', 'hoegg', 'hoegs', 'hoen', 'hoenj', 'hoenh', 'hoed', 'hoel', 'hoelg', 'hoelm', 'hoelb', 'hoels', 'hoelt', 'hoelp', 'hoelh', 'hoem', 'hoeb', 'hoebs', 'hoes', 'hoess', 'hoeng', 'hoej', 'hoec', 'hoek', 'hoet', 'hoep', 'hoeh', 'hyo', 'hyog', 'hyogg', 'hyogs', 'hyon', 'hyonj', 'hyonh', 'hyod', 'hyol', 'hyolg', 'hyolm', 'hyolb', 'hyols', 'hyolt', 'hyolp', 'hyolh', 'hyom', 'hyob', 'hyobs', 'hyos', 'hyoss', 'hyong', 'hyoj', 'hyoc', 'hyok', 'hyot', 'hyop', 'hyoh', 'hu', 'hug', 'hugg', 'hugs', 'hun', 'hunj', 'hunh', 'hud', 'hul', 'hulg', 'hulm', 'hulb', 'huls', 'hult', 'hulp', 'hulh', 'hum', 'hub', 'hubs', 'hus', 'huss', 'hung', 'huj', 'huc', 'huk', 'hut', 'hup', 'huh', 'hweo', 'hweog', 'hweogg', 'hweogs', 'hweon', 'hweonj', 'hweonh', 'hweod', 'hweol', 'hweolg', 'hweolm', 'hweolb', 'hweols', 'hweolt', 'hweolp', 'hweolh', 'hweom', 'hweob', 'hweobs', 'hweos', 'hweoss', 'hweong', 'hweoj', 'hweoc', 'hweok', 'hweot', 'hweop', 'hweoh', 'hwe', 'hweg', 'hwegg', 'hwegs'];
Copyright (C) 2019 Lars Moelleken

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

class CachedWordInflector implements WordInflector
{
    /** @var WordInflector */
    private $wordInflector;

    /** @var string[] */
    private $cache = [];

    public function __construct(WordInflector $wordInflector)
    {
        $this->wordInflector = $wordInflector;
    }

    public function inflect(string $word): string
    {
        return $this->cache[$word] ?? $this->cache[$word] = $this->wordInflector->inflect($word);
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\Rules\Esperanto;
use Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\Rules\Italian;
use Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\Rules\Turkish;
use InvalidArgumentException;

use function sprintf;

final class InflectorFactory
{
    public static function create(): LanguageInflectorFactory
    {
        return self::createForLanguage(Language::ENGLISH);
    }

    public static function createForLanguage(string $language): LanguageInflectorFactory
    {
        switch ($language) {
            case Language::ENGLISH:
                return new English\InflectorFactory();

            case Language::ESPERANTO:
                return new Esperanto\InflectorFactory();

            case Language::FRENCH:
                return new French\InflectorFactory();

            case Language::ITALIAN:
                return new Italian\InflectorFactory();

            case Language::NORWEGIAN_BOKMAL:
                return new NorwegianBokmal\InflectorFactory();

            case Language::PORTUGUESE:
                return new Portuguese\InflectorFactory();

            case Language::SPANISH:
                return new Spanish\InflectorFactory();

            case Language::TURKISH:
                return new Turkish\InflectorFactory();

            default:
                throw new InvalidArgumentException(sprintf(
                    'Language "%s" is not supported.',
                    $language
                ));
        }
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('lunes');
        yield new Pattern('rompecabezas');
        yield new Pattern('crisis');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('/l[ae]r$/i'), '');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\1ler');
        yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\1lar');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word('ben'), new Word('biz'));
        yield new Substitution(new Word('sen'), new Word('siz'));
        yield new Substitution(new Word('o'), new Word('onlar'));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('barn');
        yield new Pattern('fjell');
        yield new Pattern('hus');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('/re$/i'), 'r');
        yield new Transformation(new Pattern('/er$/i'), '');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('/e$/i'), 'er');
        yield new Transformation(new Pattern('/r$/i'), 're');
        yield new Transformation(new Pattern('/$/'), 'er');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word('konto'), new Word('konti'));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

class Ruleset
{
    /** @var Transformations */
    private $regular;

    /** @var Patterns */
    private $uninflected;

    /** @var Substitutions */
    private $irregular;

    public function __construct(Transformations $regular, Patterns $uninflected, Substitutions $irregular)
    {
        $this->regular     = $regular;
        $this->uninflected = $uninflected;
        $this->irregular   = $irregular;
    }

    public function getRegular(): Transformations
    {
        return $this->regular;
    }

    public function getUninflected(): Patterns
    {
        return $this->uninflected;
    }

    public function getIrregular(): Substitutions
    {
        return $this->irregular;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Esperanto;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Esperanto;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Esperanto;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('oj$'), 'o');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('o$'), 'oj');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word(''), new Word(''));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Esperanto;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use function array_map;
use function implode;
use function preg_match;

class Patterns
{
    /** @var string */
    private $regex;

    public function __construct(Pattern ...$patterns)
    {
        $patterns = array_map(static function (Pattern $pattern): string {
            return $pattern->getPattern();
        }, $patterns);

        $this->regex = '/^(?:' . implode('|', $patterns) . ')$/i';
    }

    public function matches(string $word): bool
    {
        return preg_match($this->regex, $word, $regs) === 1;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

class Word
{
    /** @var string */
    private $word;

    public function __construct(string $word)
    {
        $this->word = $word;
    }

    public function getWord(): string
    {
        return $this->word;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use Doctrine\Inflector\WordInflector;

use function strtolower;
use function strtoupper;
use function substr;

class Substitutions implements WordInflector
{
    /** @var Substitution[] */
    private $substitutions;

    public function __construct(Substitution ...$substitutions)
    {
        foreach ($substitutions as $substitution) {
            $this->substitutions[$substitution->getFrom()->getWord()] = $substitution;
        }
    }

    public function getFlippedSubstitutions(): Substitutions
    {
        $substitutions = [];

        foreach ($this->substitutions as $substitution) {
            $substitutions[] = new Substitution(
                $substitution->getTo(),
                $substitution->getFrom()
            );
        }

        return new Substitutions(...$substitutions);
    }

    public function inflect(string $word): string
    {
        $lowerWord = strtolower($word);

        if (isset($this->substitutions[$lowerWord])) {
            $firstLetterUppercase = $lowerWord[0] !== $word[0];

            $toWord = $this->substitutions[$lowerWord]->getTo()->getWord();

            if ($firstLetterUppercase) {
                return strtoupper($toWord[0]) . substr($toWord, 1);
            }

            return $toWord;
        }

        return $word;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use Doctrine\Inflector\WordInflector;

use function preg_replace;

final class Transformation implements WordInflector
{
    /** @var Pattern */
    private $pattern;

    /** @var string */
    private $replacement;

    public function __construct(Pattern $pattern, string $replacement)
    {
        $this->pattern     = $pattern;
        $this->replacement = $replacement;
    }

    public function getPattern(): Pattern
    {
        return $this->pattern;
    }

    public function getReplacement(): string
    {
        return $this->replacement;
    }

    public function inflect(string $word): string
    {
        return (string) preg_replace($this->pattern->getRegex(), $this->replacement, $word);
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('lunes');
        yield new Pattern('rompecabezas');
        yield new Pattern('crisis');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('/ereses$/'), 'erés');
        yield new Transformation(new Pattern('/iones$/'), 'ión');
        yield new Transformation(new Pattern('/ces$/'), 'z');
        yield new Transformation(new Pattern('/es$/'), '');
        yield new Transformation(new Pattern('/s$/'), '');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('/ú([sn])$/i'), 'u\1es');
        yield new Transformation(new Pattern('/ó([sn])$/i'), 'o\1es');
        yield new Transformation(new Pattern('/í([sn])$/i'), 'i\1es');
        yield new Transformation(new Pattern('/é([sn])$/i'), 'e\1es');
        yield new Transformation(new Pattern('/á([sn])$/i'), 'a\1es');
        yield new Transformation(new Pattern('/z$/i'), 'ces');
        yield new Transformation(new Pattern('/([aeiou]s)$/i'), '\1');
        yield new Transformation(new Pattern('/([^aeéiou])$/i'), '\1es');
        yield new Transformation(new Pattern('/$/'), 's');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word('el'), new Word('los'));
        yield new Substitution(new Word('papá'), new Word('papás'));
        yield new Substitution(new Word('mamá'), new Word('mamás'));
        yield new Substitution(new Word('sofá'), new Word('sofás'));
        yield new Substitution(new Word('mes'), new Word('meses'));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Italian;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Italian;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return iterable<Pattern> */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();
    }

    /** @return iterable<Pattern> */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return iterable<Pattern> */
    private static function getDefault(): iterable
    {
        // Invariable words (same form in singular and plural)
        $invariables = [
            'alpaca',
            'auto',
            'bar',
            'blu',
            'boia',
            'boomerang',
            'brindisi',
            'campus',
            'computer',
            'crisi',
            'crocevia',
            'dopocena',
            'film',
            'foto',
            'fuchsia',
            'gnu',
            'gorilla',
            'gru',
            'iguana',
            'kamikaze',
            'karaoke',
            'koala',
            'lama',
            'menu',
            'metropoli',
            'moto',
            'opossum',
            'panda',
            'quiz',
            'radio',
            're',
            'scacciapensieri',
            'serie',
            'smartphone',
            'sosia',
            'sottoscala',
            'specie',
            'sport',
            'tablet',
            'taxi',
            'vaglia',
            'virtù',
            'virus',
            'yogurt',
            'foto',
            'fuchsia',
        ];

        foreach ($invariables as $word) {
            yield new Pattern($word);
        }
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Italian;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return iterable<Transformation> */
    public static function getSingular(): iterable
    {
        // Reverse of -sce → -scia (fasce → fascia)
        yield new Transformation(new Pattern('([aeiou])sce$'), '\\1scia');

        // Reverse of -cie → -cia (farmacia → farmacie)
        yield new Transformation(new Pattern('cie$'), 'cia');

        // Reverse of -gie → -gia (bugia → bugie)
        yield new Transformation(new Pattern('gie$'), 'gia');

        // Reverse of -ce → -cia (arance → arancia)
        yield new Transformation(new Pattern('([^aeiou])ce$'), '\1cia');

        // Reverse of -ge → -gia (valige → valigia)
        yield new Transformation(new Pattern('([^aeiou])ge$'), '\1gia');

        // Reverse of -chi → -co (bachi → baco)
        yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])chi$'), '\1co');

        // Reverse of -ghi → -go (laghi → lago)
        yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])ghi$'), '\1go');

        // Reverse of -ci → -co (medici → medico)
        yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])ci$'), '\1co');

        // Reverse of -gi → -go (psicologi → psicologo)
        yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])gi$'), '\1go');

        // Reverse of -i → -io (zii → zio, negozi → negozio)
        // This is more complex due to Italian's stress patterns, but we'll handle the basic case
        yield new Transformation(new Pattern('([^aeiou])i$'), '\1io');

        // Handle words that end with -i but should go to -co/-go (amici → amico, not amice)
        yield new Transformation(new Pattern('([^aeiou])ci$'), '\1co');
        yield new Transformation(new Pattern('([^aeiou])gi$'), '\1go');

        // Reverse of -a → -e
        yield new Transformation(new Pattern('e$'), 'a');

        // Reverse of -e → -i
        yield new Transformation(new Pattern('i$'), 'e');

        // Reverse of -o → -i
        yield new Transformation(new Pattern('i$'), 'o');
    }

    /** @return iterable<Transformation> */
    public static function getPlural(): iterable
    {
        // Words ending in -scia without stress on 'i' become -sce (e.g. fascia → fasce)
        yield new Transformation(new Pattern('([aeiou])scia$'), '\\1sce');

        // Words ending in -cia/gia with stress on 'i' keep the 'i' in plural
        yield new Transformation(new Pattern('cia$'), 'cie'); // e.g. farmacia → farmacie
        yield new Transformation(new Pattern('gia$'), 'gie'); // e.g. bugia → bugie

        // Words ending in -cia/gia without stress on 'i' lose the 'i' in plural
        yield new Transformation(new Pattern('([^aeiou])cia$'), '\\1ce'); // e.g. arancia → arance
        yield new Transformation(new Pattern('([^aeiou])gia$'), '\\1ge'); // e.g. valigia → valige

        // Words ending in -co/-go with stress on 'o' become -chi/-ghi
        yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])co$'), '\\1chi'); // e.g. baco → bachi
        yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])go$'), '\\1ghi'); // e.g. lago → laghi

        // Words ending in -co/-go with stress on the penultimate syllable become -ci/-gi
        yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])co$'), '\\1ci'); // e.g. medico → medici
        yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])go$'), '\\1gi'); // e.g. psicologo → psicologi

        // Words ending in -io with stress on 'i' keep the 'i' in plural
        yield new Transformation(new Pattern('([^aeiou])io$'), '\\1i'); // e.g. zio → zii

        // Words ending in -io with stress on 'o' lose the 'i' in plural
        yield new Transformation(new Pattern('([aeiou])io$'), '\\1i'); // e.g. negozio → negozi

        // Standard ending rules
        yield new Transformation(new Pattern('a$'), 'e');  // -a → -e
        yield new Transformation(new Pattern('e$'), 'i');  // -e → -i
        yield new Transformation(new Pattern('o$'), 'i');  // -o → -i
    }

    /** @return iterable<Substitution> */
    public static function getIrregular(): iterable
    {
        // Irregular substitutions (singular => plural)
        $irregulars = [
            'ala' => 'ali',
            'albergo' => 'alberghi',
            'amica' => 'amiche',
            'amico' => 'amici',
            'ampio' => 'ampi',
            'arancia' => 'arance',
            'arma' => 'armi',
            'asparago' => 'asparagi',
            'banca' => 'banche',
            'belga' => 'belgi',
            'braccio' => 'braccia',
            'budello' => 'budella',
            'bue' => 'buoi',
            'caccia' => 'cacce',
            'calcagno' => 'calcagna',
            'camicia' => 'camicie',
            'cane' => 'cani',
            'capitale' => 'capitali',
            'carcere' => 'carceri',
            'casa' => 'case',
            'cavaliere' => 'cavalieri',
            'centinaio' => 'centinaia',
            'cerchio' => 'cerchia',
            'cervello' => 'cervella',
            'chiave' => 'chiavi',
            'chirurgo' => 'chirurgi',
            'ciglio' => 'ciglia',
            'città' => 'città',
            'corno' => 'corna',
            'corpo' => 'corpi',
            'crisi' => 'crisi',
            'dente' => 'denti',
            'dio' => 'dei',
            'dito' => 'dita',
            'dottore' => 'dottori',
            'fiore' => 'fiori',
            'fratello' => 'fratelli',
            'fuoco' => 'fuochi',
            'gamba' => 'gambe',
            'ginocchio' => 'ginocchia',
            'gioco' => 'giochi',
            'giornale' => 'giornali',
            'giraffa' => 'giraffe',
            'labbro' => 'labbra',
            'lenzuolo' => 'lenzuola',
            'libro' => 'libri',
            'madre' => 'madri',
            'maestro' => 'maestri',
            'magico' => 'magici',
            'mago' => 'maghi',
            'maniaco' => 'maniaci',
            'manico' => 'manici',
            'mano' => 'mani',
            'medico' => 'medici',
            'membro' => 'membri',
            'metropoli' => 'metropoli',
            'migliaio' => 'migliaia',
            'miglio' => 'miglia',
            'mille' => 'mila',
            'mio' => 'miei',
            'moglie' => 'mogli',
            'mosaico' => 'mosaici',
            'muro' => 'muri',
            'nemico' => 'nemici',
            'nome' => 'nomi',
            'occhio' => 'occhi',
            'orecchio' => 'orecchi',
            'osso' => 'ossa',
            'paio' => 'paia',
            'pane' => 'pani',
            'papa' => 'papi',
            'pasta' => 'paste',
            'penna' => 'penne',
            'pesce' => 'pesci',
            'piede' => 'piedi',
            'pittore' => 'pittori',
            'poeta' => 'poeti',
            'porco' => 'porci',
            'porto' => 'porti',
            'problema' => 'problemi',
            'ragazzo' => 'ragazzi',
            're' => 're',
            'rene' => 'reni',
            'riso' => 'risa',
            'rosa' => 'rosa',
            'sale' => 'sali',
            'sarto' => 'sarti',
            'scuola' => 'scuole',
            'serie' => 'serie',
            'serramento' => 'serramenta',
            'sorella' => 'sorelle',
            'specie' => 'specie',
            'staio' => 'staia',
            'stazione' => 'stazioni',
            'strido' => 'strida',
            'strillo' => 'strilla',
            'studio' => 'studi',
            'suo' => 'suoi',
            'superficie' => 'superfici',
            'tavolo' => 'tavoli',
            'tempio' => 'templi',
            'treno' => 'treni',
            'tuo' => 'tuoi',
            'uomo' => 'uomini',
            'uovo' => 'uova',
            'urlo' => 'urla',
            'valigia' => 'valigie',
            'vestigio' => 'vestigia',
            'vino' => 'vini',
            'viola' => 'viola',
            'zio' => 'zii',
        ];

        foreach ($irregulars as $singular => $plural) {
            yield new Substitution(new Word($singular), new Word($plural));
        }
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Italian;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('tórax');
        yield new Pattern('tênis');
        yield new Pattern('ônibus');
        yield new Pattern('lápis');
        yield new Pattern('fênix');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
        yield new Transformation(new Pattern('/(japon|escoc|ingl|dinamarqu|fregu|portugu)eses$/i'), '\1ês');
        yield new Transformation(new Pattern('/(ae|ao|oe)s$/'), 'ao');
        yield new Transformation(new Pattern('/(ãe|ão|õe)s$/'), 'ão');
        yield new Transformation(new Pattern('/^(.*[^s]s)es$/i'), '\1');
        yield new Transformation(new Pattern('/sses$/i'), 'sse');
        yield new Transformation(new Pattern('/ns$/i'), 'm');
        yield new Transformation(new Pattern('/(r|t|f|v)is$/i'), '\1il');
        yield new Transformation(new Pattern('/uis$/i'), 'ul');
        yield new Transformation(new Pattern('/ois$/i'), 'ol');
        yield new Transformation(new Pattern('/eis$/i'), 'ei');
        yield new Transformation(new Pattern('/éis$/i'), 'el');
        yield new Transformation(new Pattern('/([^p])ais$/i'), '\1al');
        yield new Transformation(new Pattern('/(r|z)es$/i'), '\1');
        yield new Transformation(new Pattern('/^(á|gá)s$/i'), '\1s');
        yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
        yield new Transformation(new Pattern('/^(irm|m)ao$/i'), '\1aos');
        yield new Transformation(new Pattern('/ao$/i'), 'oes');
        yield new Transformation(new Pattern('/^(alem|c|p)ão$/i'), '\1ães');
        yield new Transformation(new Pattern('/^(irm|m)ão$/i'), '\1ãos');
        yield new Transformation(new Pattern('/ão$/i'), 'ões');
        yield new Transformation(new Pattern('/^(|g)ás$/i'), '\1ases');
        yield new Transformation(new Pattern('/^(japon|escoc|ingl|dinamarqu|fregu|portugu)ês$/i'), '\1eses');
        yield new Transformation(new Pattern('/m$/i'), 'ns');
        yield new Transformation(new Pattern('/([^aeou])il$/i'), '\1is');
        yield new Transformation(new Pattern('/ul$/i'), 'uis');
        yield new Transformation(new Pattern('/ol$/i'), 'ois');
        yield new Transformation(new Pattern('/el$/i'), 'eis');
        yield new Transformation(new Pattern('/al$/i'), 'ais');
        yield new Transformation(new Pattern('/(z|r)$/i'), '\1es');
        yield new Transformation(new Pattern('/(s)$/i'), '\1');
        yield new Transformation(new Pattern('/$/'), 's');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word('abdomen'), new Word('abdomens'));
        yield new Substitution(new Word('alemão'), new Word('alemães'));
        yield new Substitution(new Word('artesã'), new Word('artesãos'));
        yield new Substitution(new Word('álcool'), new Word('álcoois'));
        yield new Substitution(new Word('árvore'), new Word('árvores'));
        yield new Substitution(new Word('bencão'), new Word('bencãos'));
        yield new Substitution(new Word('cão'), new Word('cães'));
        yield new Substitution(new Word('campus'), new Word('campi'));
        yield new Substitution(new Word('cadáver'), new Word('cadáveres'));
        yield new Substitution(new Word('capelão'), new Word('capelães'));
        yield new Substitution(new Word('capitão'), new Word('capitães'));
        yield new Substitution(new Word('chão'), new Word('chãos'));
        yield new Substitution(new Word('charlatão'), new Word('charlatães'));
        yield new Substitution(new Word('cidadão'), new Word('cidadãos'));
        yield new Substitution(new Word('consul'), new Word('consules'));
        yield new Substitution(new Word('cristão'), new Word('cristãos'));
        yield new Substitution(new Word('difícil'), new Word('difíceis'));
        yield new Substitution(new Word('email'), new Word('emails'));
        yield new Substitution(new Word('escrivão'), new Word('escrivães'));
        yield new Substitution(new Word('fóssil'), new Word('fósseis'));
        yield new Substitution(new Word('gás'), new Word('gases'));
        yield new Substitution(new Word('germens'), new Word('germen'));
        yield new Substitution(new Word('grão'), new Word('grãos'));
        yield new Substitution(new Word('hífen'), new Word('hífens'));
        yield new Substitution(new Word('irmão'), new Word('irmãos'));
        yield new Substitution(new Word('liquens'), new Word('liquen'));
        yield new Substitution(new Word('mal'), new Word('males'));
        yield new Substitution(new Word('mão'), new Word('mãos'));
        yield new Substitution(new Word('orfão'), new Word('orfãos'));
        yield new Substitution(new Word('país'), new Word('países'));
        yield new Substitution(new Word('pai'), new Word('pais'));
        yield new Substitution(new Word('pão'), new Word('pães'));
        yield new Substitution(new Word('projétil'), new Word('projéteis'));
        yield new Substitution(new Word('réptil'), new Word('répteis'));
        yield new Substitution(new Word('sacristão'), new Word('sacristães'));
        yield new Substitution(new Word('sotão'), new Word('sotãos'));
        yield new Substitution(new Word('tabelião'), new Word('tabeliães'));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();

        yield new Pattern('bois');
        yield new Pattern('mas');
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
        yield new Transformation(new Pattern('/ails$/'), 'ail');
        yield new Transformation(new Pattern('/(journ|chev|loc)aux$/'), '\1al');
        yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/'), '\1');
        yield new Transformation(new Pattern('/s$/'), '');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
        yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/'), '\1aux');
        yield new Transformation(new Pattern('/ail$/'), 'ails');
        yield new Transformation(new Pattern('/(chacal|carnaval|festival|récital)$/'), '\1s');
        yield new Transformation(new Pattern('/al$/'), 'aux');
        yield new Transformation(new Pattern('/(bleu|émeu|landau|pneu|sarrau)$/'), '\1s');
        yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|lieu|pou|au|eu|eau)$/'), '\1x');
        yield new Transformation(new Pattern('/$/'), 's');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word('monsieur'), new Word('messieurs'));
        yield new Substitution(new Word('madame'), new Word('mesdames'));
        yield new Substitution(new Word('mademoiselle'), new Word('mesdemoiselles'));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use Doctrine\Inflector\WordInflector;

class Transformations implements WordInflector
{
    /** @var Transformation[] */
    private $transformations;

    public function __construct(Transformation ...$transformations)
    {
        $this->transformations = $transformations;
    }

    public function inflect(string $word): string
    {
        foreach ($this->transformations as $transformation) {
            if ($transformation->getPattern()->matches($word)) {
                return $transformation->inflect($word);
            }
        }

        return $word;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

final class Substitution
{
    /** @var Word */
    private $from;

    /** @var Word */
    private $to;

    public function __construct(Word $from, Word $to)
    {
        $this->from = $from;
        $this->to   = $to;
    }

    public function getFrom(): Word
    {
        return $this->from;
    }

    public function getTo(): Word
    {
        return $this->to;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use function preg_match;

final class Pattern
{
    /** @var string */
    private $pattern;

    /** @var string */
    private $regex;

    public function __construct(string $pattern)
    {
        $this->pattern = $pattern;

        if (isset($this->pattern[0]) && $this->pattern[0] === '/') {
            $this->regex = $this->pattern;
        } else {
            $this->regex = '/' . $this->pattern . '/i';
        }
    }

    public function getPattern(): string
    {
        return $this->pattern;
    }

    public function getRegex(): string
    {
        return $this->regex;
    }

    public function matches(string $word): bool
    {
        return preg_match($this->getRegex(), $word) === 1;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset(): Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset(): Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /** @return Pattern[] */
    public static function getSingular(): iterable
    {
        yield from self::getDefault();

        yield new Pattern('.*ss');
        yield new Pattern('clothes');
        yield new Pattern('data');
        yield new Pattern('fascia');
        yield new Pattern('fuchsia');
        yield new Pattern('galleria');
        yield new Pattern('mafia');
        yield new Pattern('militia');
        yield new Pattern('pants');
        yield new Pattern('petunia');
        yield new Pattern('sepia');
        yield new Pattern('trivia');
        yield new Pattern('utopia');
    }

    /** @return Pattern[] */
    public static function getPlural(): iterable
    {
        yield from self::getDefault();

        yield new Pattern('people');
        yield new Pattern('trivia');
        yield new Pattern('\w+ware$');
        yield new Pattern('media');
    }

    /** @return Pattern[] */
    private static function getDefault(): iterable
    {
        yield new Pattern('\w+media');
        yield new Pattern('advice');
        yield new Pattern('aircraft');
        yield new Pattern('amoyese');
        yield new Pattern('art');
        yield new Pattern('audio');
        yield new Pattern('baggage');
        yield new Pattern('bison');
        yield new Pattern('borghese');
        yield new Pattern('bream');
        yield new Pattern('breeches');
        yield new Pattern('britches');
        yield new Pattern('buffalo');
        yield new Pattern('butter');
        yield new Pattern('cantus');
        yield new Pattern('carp');
        yield new Pattern('cattle');
        yield new Pattern('chassis');
        yield new Pattern('clippers');
        yield new Pattern('clothing');
        yield new Pattern('coal');
        yield new Pattern('cod');
        yield new Pattern('coitus');
        yield new Pattern('compensation');
        yield new Pattern('congoese');
        yield new Pattern('contretemps');
        yield new Pattern('coreopsis');
        yield new Pattern('corps');
        yield new Pattern('cotton');
        yield new Pattern('data');
        yield new Pattern('debris');
        yield new Pattern('deer');
        yield new Pattern('diabetes');
        yield new Pattern('djinn');
        yield new Pattern('education');
        yield new Pattern('eland');
        yield new Pattern('elk');
        yield new Pattern('emoji');
        yield new Pattern('equipment');
        yield new Pattern('evidence');
        yield new Pattern('faroese');
        yield new Pattern('feedback');
        yield new Pattern('fish');
        yield new Pattern('flounder');
        yield new Pattern('flour');
        yield new Pattern('foochowese');
        yield new Pattern('food');
        yield new Pattern('furniture');
        yield new Pattern('gallows');
        yield new Pattern('genevese');
        yield new Pattern('genoese');
        yield new Pattern('gilbertese');
        yield new Pattern('gold');
        yield new Pattern('headquarters');
        yield new Pattern('herpes');
        yield new Pattern('hijinks');
        yield new Pattern('homework');
        yield new Pattern('hottentotese');
        yield new Pattern('impatience');
        yield new Pattern('information');
        yield new Pattern('innings');
        yield new Pattern('jackanapes');
        yield new Pattern('jeans');
        yield new Pattern('jedi');
        yield new Pattern('kin');
        yield new Pattern('kiplingese');
        yield new Pattern('knowledge');
        yield new Pattern('kongoese');
        yield new Pattern('leather');
        yield new Pattern('love');
        yield new Pattern('lucchese');
        yield new Pattern('luggage');
        yield new Pattern('mackerel');
        yield new Pattern('Maltese');
        yield new Pattern('management');
        yield new Pattern('metadata');
        yield new Pattern('mews');
        yield new Pattern('money');
        yield new Pattern('moose');
        yield new Pattern('mumps');
        yield new Pattern('music');
        yield new Pattern('nankingese');
        yield new Pattern('news');
        yield new Pattern('nexus');
        yield new Pattern('niasese');
        yield new Pattern('nutrition');
        yield new Pattern('offspring');
        yield new Pattern('oil');
        yield new Pattern('patience');
        yield new Pattern('pekingese');
        yield new Pattern('piedmontese');
        yield new Pattern('pincers');
        yield new Pattern('pistoiese');
        yield new Pattern('plankton');
        yield new Pattern('pliers');
        yield new Pattern('pokemon');
        yield new Pattern('police');
        yield new Pattern('polish');
        yield new Pattern('portuguese');
        yield new Pattern('proceedings');
        yield new Pattern('progress');
        yield new Pattern('rabies');
        yield new Pattern('rain');
        yield new Pattern('research');
        yield new Pattern('rhinoceros');
        yield new Pattern('rice');
        yield new Pattern('salmon');
        yield new Pattern('sand');
        yield new Pattern('sarawakese');
        yield new Pattern('scissors');
        yield new Pattern('sea[- ]bass');
        yield new Pattern('series');
        yield new Pattern('shavese');
        yield new Pattern('shears');
        yield new Pattern('sheep');
        yield new Pattern('siemens');
        yield new Pattern('silk');
        yield new Pattern('sms');
        yield new Pattern('soap');
        yield new Pattern('social media');
        yield new Pattern('spam');
        yield new Pattern('species');
        yield new Pattern('staff');
        yield new Pattern('sugar');
        yield new Pattern('swine');
        yield new Pattern('talent');
        yield new Pattern('toothpaste');
        yield new Pattern('traffic');
        yield new Pattern('travel');
        yield new Pattern('trousers');
        yield new Pattern('trout');
        yield new Pattern('tuna');
        yield new Pattern('us');
        yield new Pattern('vermontese');
        yield new Pattern('vinegar');
        yield new Pattern('weather');
        yield new Pattern('wenchowese');
        yield new Pattern('wheat');
        yield new Pattern('whiting');
        yield new Pattern('wildebeest');
        yield new Pattern('wood');
        yield new Pattern('wool');
        yield new Pattern('yengeese');
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /** @return Transformation[] */
    public static function getSingular(): iterable
    {
        yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
        yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatus');
        yield new Transformation(new Pattern('(c)ampus$'), '\1\2ampus');
        yield new Transformation(new Pattern('^(.*)(menu)s$'), '\1\2');
        yield new Transformation(new Pattern('(quiz)zes$'), '\\1');
        yield new Transformation(new Pattern('(matr)ices$'), '\1ix');
        yield new Transformation(new Pattern('(vert|ind)ices$'), '\1ex');
        yield new Transformation(new Pattern('^(ox)en'), '\1');
        yield new Transformation(new Pattern('(alias)(es)*$'), '\1');
        yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)oes$'), '\1o');
        yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$'), '\1us');
        yield new Transformation(new Pattern('([ftw]ax)es'), '\1');
        yield new Transformation(new Pattern('(analys|ax|cris|test|thes)es$'), '\1is');
        yield new Transformation(new Pattern('(shoe|slave)s$'), '\1');
        yield new Transformation(new Pattern('(o)es$'), '\1');
        yield new Transformation(new Pattern('ouses$'), 'ouse');
        yield new Transformation(new Pattern('([^a])uses$'), '\1us');
        yield new Transformation(new Pattern('([m|l])ice$'), '\1ouse');
        yield new Transformation(new Pattern('(x|ch|ss|sh)es$'), '\1');
        yield new Transformation(new Pattern('(m)ovies$'), '\1\2ovie');
        yield new Transformation(new Pattern('(s)eries$'), '\1\2eries');
        yield new Transformation(new Pattern('([^aeiouy]|qu)ies$'), '\1y');
        yield new Transformation(new Pattern('([lr])ves$'), '\1f');
        yield new Transformation(new Pattern('(tive)s$'), '\1');
        yield new Transformation(new Pattern('(hive)s$'), '\1');
        yield new Transformation(new Pattern('(drive)s$'), '\1');
        yield new Transformation(new Pattern('(dive)s$'), '\1');
        yield new Transformation(new Pattern('(olive)s$'), '\1');
        yield new Transformation(new Pattern('([^fo])ves$'), '\1fe');
        yield new Transformation(new Pattern('(^analy)ses$'), '\1sis');
        yield new Transformation(new Pattern('(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$'), '\1\2sis');
        yield new Transformation(new Pattern('(tax)a$'), '\1on');
        yield new Transformation(new Pattern('(c)riteria$'), '\1riterion');
        yield new Transformation(new Pattern('([ti])a(?<!regatta)$'), '\1um');
        yield new Transformation(new Pattern('(p)eople$'), '\1\2erson');
        yield new Transformation(new Pattern('(m)en$'), '\1an');
        yield new Transformation(new Pattern('(c)hildren$'), '\1\2hild');
        yield new Transformation(new Pattern('(f)eet$'), '\1oot');
        yield new Transformation(new Pattern('(n)ews$'), '\1\2ews');
        yield new Transformation(new Pattern('eaus$'), 'eau');
        yield new Transformation(new Pattern('^tights$'), 'tights');
        yield new Transformation(new Pattern('^shorts$'), 'shorts');
        yield new Transformation(new Pattern('s$'), '');
    }

    /** @return Transformation[] */
    public static function getPlural(): iterable
    {
        yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
        yield new Transformation(new Pattern('(quiz)$'), '\1zes');
        yield new Transformation(new Pattern('^(ox)$'), '\1\2en');
        yield new Transformation(new Pattern('([m|l])ouse$'), '\1ice');
        yield new Transformation(new Pattern('(matr|vert|ind)(ix|ex)$'), '\1ices');
        yield new Transformation(new Pattern('(x|ch|ss|sh)$'), '\1es');
        yield new Transformation(new Pattern('([^aeiouy]|qu)y$'), '\1ies');
        yield new Transformation(new Pattern('(hive|gulf)$'), '\1s');
        yield new Transformation(new Pattern('(?:([^f])fe|([lr])f)$'), '\1\2ves');
        yield new Transformation(new Pattern('sis$'), 'ses');
        yield new Transformation(new Pattern('([ti])um$'), '\1a');
        yield new Transformation(new Pattern('(tax)on$'), '\1a');
        yield new Transformation(new Pattern('(c)riterion$'), '\1riteria');
        yield new Transformation(new Pattern('(p)erson$'), '\1eople');
        yield new Transformation(new Pattern('(m)an$'), '\1en');
        yield new Transformation(new Pattern('(c)hild$'), '\1hildren');
        yield new Transformation(new Pattern('(f)oot$'), '\1eet');
        yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)o$'), '\1\2oes');
        yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$'), '\1i');
        yield new Transformation(new Pattern('us$'), 'uses');
        yield new Transformation(new Pattern('(alias)$'), '\1es');
        yield new Transformation(new Pattern('(analys|ax|cris|test|thes)is$'), '\1es');
        yield new Transformation(new Pattern('s$'), 's');
        yield new Transformation(new Pattern('^$'), '');
        yield new Transformation(new Pattern('$'), 's');
    }

    /** @return Substitution[] */
    public static function getIrregular(): iterable
    {
        yield new Substitution(new Word('abuse'), new Word('abuses'));
        yield new Substitution(new Word('alga'), new Word('algae'));
        yield new Substitution(new Word('atlas'), new Word('atlases'));
        yield new Substitution(new Word('avalanche'), new Word('avalanches'));
        yield new Substitution(new Word('axis'), new Word('axes'));
        yield new Substitution(new Word('axe'), new Word('axes'));
        yield new Substitution(new Word('beef'), new Word('beefs'));
        yield new Substitution(new Word('blouse'), new Word('blouses'));
        yield new Substitution(new Word('brother'), new Word('brothers'));
        yield new Substitution(new Word('brownie'), new Word('brownies'));
        yield new Substitution(new Word('cache'), new Word('caches'));
        yield new Substitution(new Word('cafe'), new Word('cafes'));
        yield new Substitution(new Word('canvas'), new Word('canvases'));
        yield new Substitution(new Word('cave'), new Word('caves'));
        yield new Substitution(new Word('chateau'), new Word('chateaux'));
        yield new Substitution(new Word('child'), new Word('children'));
        yield new Substitution(new Word('cookie'), new Word('cookies'));
        yield new Substitution(new Word('corpus'), new Word('corpuses'));
        yield new Substitution(new Word('cow'), new Word('cows'));
        yield new Substitution(new Word('criterion'), new Word('criteria'));
        yield new Substitution(new Word('curriculum'), new Word('curricula'));
        yield new Substitution(new Word('curve'), new Word('curves'));
        yield new Substitution(new Word('demo'), new Word('demos'));
        yield new Substitution(new Word('die'), new Word('dice'));
        yield new Substitution(new Word('domino'), new Word('dominoes'));
        yield new Substitution(new Word('echo'), new Word('echoes'));
        yield new Substitution(new Word('emphasis'), new Word('emphases'));
        yield new Substitution(new Word('epoch'), new Word('epochs'));
        yield new Substitution(new Word('foe'), new Word('foes'));
        yield new Substitution(new Word('foot'), new Word('feet'));
        yield new Substitution(new Word('fungus'), new Word('fungi'));
        yield new Substitution(new Word('ganglion'), new Word('ganglions'));
        yield new Substitution(new Word('gas'), new Word('gases'));
        yield new Substitution(new Word('genie'), new Word('genies'));
        yield new Substitution(new Word('genus'), new Word('genera'));
        yield new Substitution(new Word('goose'), new Word('geese'));
        yield new Substitution(new Word('graffito'), new Word('graffiti'));
        yield new Substitution(new Word('grave'), new Word('graves'));
        yield new Substitution(new Word('hippopotamus'), new Word('hippopotami'));
        yield new Substitution(new Word('hoax'), new Word('hoaxes'));
        yield new Substitution(new Word('hoof'), new Word('hoofs'));
        yield new Substitution(new Word('human'), new Word('humans'));
        yield new Substitution(new Word('iris'), new Word('irises'));
        yield new Substitution(new Word('larva'), new Word('larvae'));
        yield new Substitution(new Word('leaf'), new Word('leaves'));
        yield new Substitution(new Word('lens'), new Word('lenses'));
        yield new Substitution(new Word('loaf'), new Word('loaves'));
        yield new Substitution(new Word('man'), new Word('men'));
        yield new Substitution(new Word('medium'), new Word('media'));
        yield new Substitution(new Word('memorandum'), new Word('memoranda'));
        yield new Substitution(new Word('money'), new Word('monies'));
        yield new Substitution(new Word('mongoose'), new Word('mongooses'));
        yield new Substitution(new Word('motto'), new Word('mottoes'));
        yield new Substitution(new Word('move'), new Word('moves'));
        yield new Substitution(new Word('mythos'), new Word('mythoi'));
        yield new Substitution(new Word('neurosis'), new Word('neuroses'));
        yield new Substitution(new Word('niche'), new Word('niches'));
        yield new Substitution(new Word('niveau'), new Word('niveaux'));
        yield new Substitution(new Word('nucleus'), new Word('nuclei'));
        yield new Substitution(new Word('numen'), new Word('numina'));
        yield new Substitution(new Word('nursery'), new Word('nurseries'));
        yield new Substitution(new Word('oasis'), new Word('oases'));
        yield new Substitution(new Word('occiput'), new Word('occiputs'));
        yield new Substitution(new Word('octopus'), new Word('octopuses'));
        yield new Substitution(new Word('opus'), new Word('opuses'));
        yield new Substitution(new Word('ox'), new Word('oxen'));
        yield new Substitution(new Word('passerby'), new Word('passersby'));
        yield new Substitution(new Word('penis'), new Word('penises'));
        yield new Substitution(new Word('person'), new Word('people'));
        yield new Substitution(new Word('plateau'), new Word('plateaux'));
        yield new Substitution(new Word('runner-up'), new Word('runners-up'));
        yield new Substitution(new Word('safe'), new Word('safes'));
        yield new Substitution(new Word('save'), new Word('saves'));
        yield new Substitution(new Word('sex'), new Word('sexes'));
        yield new Substitution(new Word('sieve'), new Word('sieves'));
        yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
        yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
        yield new Substitution(new Word('stadium'), new Word('stadiums'));
        yield new Substitution(new Word('syllabus'), new Word('syllabi'));
        yield new Substitution(new Word('testis'), new Word('testes'));
        yield new Substitution(new Word('thief'), new Word('thieves'));
        yield new Substitution(new Word('tooth'), new Word('teeth'));
        yield new Substitution(new Word('tornado'), new Word('tornadoes'));
        yield new Substitution(new Word('trilby'), new Word('trilbys'));
        yield new Substitution(new Word('turf'), new Word('turfs'));
        yield new Substitution(new Word('valve'), new Word('valves'));
        yield new Substitution(new Word('volcano'), new Word('volcanoes'));
        yield new Substitution(new Word('wave'), new Word('waves'));
        yield new Substitution(new Word('zombie'), new Word('zombies'));
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset(): Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\Ruleset;

interface LanguageInflectorFactory
{
    /**
     * Applies custom rules for singularisation
     *
     * @param bool $reset If true, will unset default inflections for all new rules
     *
     * @return $this
     */
    public function withSingularRules(?Ruleset $singularRules, bool $reset = false): self;

    /**
     * Applies custom rules for pluralisation
     *
     * @param bool $reset If true, will unset default inflections for all new rules
     *
     * @return $this
     */
    public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): self;

    /**
     * Builds the inflector instance with all applicable rules
     */
    public function build(): Inflector;
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use RuntimeException;

use function chr;
use function function_exists;
use function lcfirst;
use function mb_strtolower;
use function ord;
use function preg_match;
use function preg_replace;
use function sprintf;
use function str_replace;
use function strlen;
use function strtolower;
use function strtr;
use function trim;
use function ucwords;

class Inflector
{
    private const ACCENTED_CHARACTERS = [
        'À' => 'A',
        'Á' => 'A',
        'Â' => 'A',
        'Ã' => 'A',
        'Ä' => 'Ae',
        'Æ' => 'Ae',
        'Å' => 'Aa',
        'æ' => 'a',
        'Ç' => 'C',
        'È' => 'E',
        'É' => 'E',
        'Ê' => 'E',
        'Ë' => 'E',
        'Ì' => 'I',
        'Í' => 'I',
        'Î' => 'I',
        'Ï' => 'I',
        'Ñ' => 'N',
        'Ò' => 'O',
        'Ó' => 'O',
        'Ô' => 'O',
        'Õ' => 'O',
        'Ö' => 'Oe',
        'Ù' => 'U',
        'Ú' => 'U',
        'Û' => 'U',
        'Ü' => 'Ue',
        'Ý' => 'Y',
        'ß' => 'ss',
        'à' => 'a',
        'á' => 'a',
        'â' => 'a',
        'ã' => 'a',
        'ä' => 'ae',
        'å' => 'aa',
        'ç' => 'c',
        'è' => 'e',
        'é' => 'e',
        'ê' => 'e',
        'ë' => 'e',
        'ì' => 'i',
        'í' => 'i',
        'î' => 'i',
        'ï' => 'i',
        'ñ' => 'n',
        'ò' => 'o',
        'ó' => 'o',
        'ô' => 'o',
        'õ' => 'o',
        'ö' => 'oe',
        'ù' => 'u',
        'ú' => 'u',
        'û' => 'u',
        'ü' => 'ue',
        'ý' => 'y',
        'ÿ' => 'y',
        'Ā' => 'A',
        'ā' => 'a',
        'Ă' => 'A',
        'ă' => 'a',
        'Ą' => 'A',
        'ą' => 'a',
        'Ć' => 'C',
        'ć' => 'c',
        'Ĉ' => 'C',
        'ĉ' => 'c',
        'Ċ' => 'C',
        'ċ' => 'c',
        'Č' => 'C',
        'č' => 'c',
        'Ď' => 'D',
        'ď' => 'd',
        'Đ' => 'D',
        'đ' => 'd',
        'Ē' => 'E',
        'ē' => 'e',
        'Ĕ' => 'E',
        'ĕ' => 'e',
        'Ė' => 'E',
        'ė' => 'e',
        'Ę' => 'E',
        'ę' => 'e',
        'Ě' => 'E',
        'ě' => 'e',
        'Ĝ' => 'G',
        'ĝ' => 'g',
        'Ğ' => 'G',
        'ğ' => 'g',
        'Ġ' => 'G',
        'ġ' => 'g',
        'Ģ' => 'G',
        'ģ' => 'g',
        'Ĥ' => 'H',
        'ĥ' => 'h',
        'Ħ' => 'H',
        'ħ' => 'h',
        'Ĩ' => 'I',
        'ĩ' => 'i',
        'Ī' => 'I',
        'ī' => 'i',
        'Ĭ' => 'I',
        'ĭ' => 'i',
        'Į' => 'I',
        'į' => 'i',
        'İ' => 'I',
        'ı' => 'i',
        'Ĳ' => 'IJ',
        'ĳ' => 'ij',
        'Ĵ' => 'J',
        'ĵ' => 'j',
        'Ķ' => 'K',
        'ķ' => 'k',
        'ĸ' => 'k',
        'Ĺ' => 'L',
        'ĺ' => 'l',
        'Ļ' => 'L',
        'ļ' => 'l',
        'Ľ' => 'L',
        'ľ' => 'l',
        'Ŀ' => 'L',
        'ŀ' => 'l',
        'Ł' => 'L',
        'ł' => 'l',
        'Ń' => 'N',
        'ń' => 'n',
        'Ņ' => 'N',
        'ņ' => 'n',
        'Ň' => 'N',
        'ň' => 'n',
        'ŉ' => 'N',
        'Ŋ' => 'n',
        'ŋ' => 'N',
        'Ō' => 'O',
        'ō' => 'o',
        'Ŏ' => 'O',
        'ŏ' => 'o',
        'Ő' => 'O',
        'ő' => 'o',
        'Œ' => 'OE',
        'œ' => 'oe',
        'Ø' => 'O',
        'ø' => 'o',
        'Ŕ' => 'R',
        'ŕ' => 'r',
        'Ŗ' => 'R',
        'ŗ' => 'r',
        'Ř' => 'R',
        'ř' => 'r',
        'Ś' => 'S',
        'ś' => 's',
        'Ŝ' => 'S',
        'ŝ' => 's',
        'Ş' => 'S',
        'ş' => 's',
        'Š' => 'S',
        'š' => 's',
        'Ţ' => 'T',
        'ţ' => 't',
        'Ť' => 'T',
        'ť' => 't',
        'Ŧ' => 'T',
        'ŧ' => 't',
        'Ũ' => 'U',
        'ũ' => 'u',
        'Ū' => 'U',
        'ū' => 'u',
        'Ŭ' => 'U',
        'ŭ' => 'u',
        'Ů' => 'U',
        'ů' => 'u',
        'Ű' => 'U',
        'ű' => 'u',
        'Ų' => 'U',
        'ų' => 'u',
        'Ŵ' => 'W',
        'ŵ' => 'w',
        'Ŷ' => 'Y',
        'ŷ' => 'y',
        'Ÿ' => 'Y',
        'Ź' => 'Z',
        'ź' => 'z',
        'Ż' => 'Z',
        'ż' => 'z',
        'Ž' => 'Z',
        'ž' => 'z',
        'ſ' => 's',
        '€' => 'E',
        '£' => '',
    ];

    /** @var WordInflector */
    private $singularizer;

    /** @var WordInflector */
    private $pluralizer;

    public function __construct(WordInflector $singularizer, WordInflector $pluralizer)
    {
        $this->singularizer = $singularizer;
        $this->pluralizer   = $pluralizer;
    }

    /**
     * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
     */
    public function tableize(string $word): string
    {
        $tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word);

        if ($tableized === null) {
            throw new RuntimeException(sprintf(
                'preg_replace returned null for value "%s"',
                $word
            ));
        }

        return mb_strtolower($tableized);
    }

    /**
     * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
     */
    public function classify(string $word): string
    {
        return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
    }

    /**
     * Camelizes a word. This uses the classify() method and turns the first character to lowercase.
     */
    public function camelize(string $word): string
    {
        return lcfirst($this->classify($word));
    }

    /**
     * Uppercases words with configurable delimiters between words.
     *
     * Takes a string and capitalizes all of the words, like PHP's built-in
     * ucwords function. This extends that behavior, however, by allowing the
     * word delimiters to be configured, rather than only separating on
     * whitespace.
     *
     * Here is an example:
     * <code>
     * <?php
     * $string = 'top-o-the-morning to all_of_you!';
     * echo $inflector->capitalize($string);
     * // Top-O-The-Morning To All_of_you!
     *
     * echo $inflector->capitalize($string, '-_ ');
     * // Top-O-The-Morning To All_Of_You!
     * ?>
     * </code>
     *
     * @param string $string     The string to operate on.
     * @param string $delimiters A list of word separators.
     *
     * @return string The string with all delimiter-separated words capitalized.
     */
    public function capitalize(string $string, string $delimiters = " \n\t\r\0\x0B-"): string
    {
        return ucwords($string, $delimiters);
    }

    /**
     * Checks if the given string seems like it has utf8 characters in it.
     *
     * @param string $string The string to check for utf8 characters in.
     */
    public function seemsUtf8(string $string): bool
    {
        for ($i = 0; $i < strlen($string); $i++) {
            if (ord($string[$i]) < 0x80) {
                continue; // 0bbbbbbb
            }

            if ((ord($string[$i]) & 0xE0) === 0xC0) {
                $n = 1; // 110bbbbb
            } elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
                $n = 2; // 1110bbbb
            } elseif ((ord($string[$i]) & 0xF8) === 0xF0) {
                $n = 3; // 11110bbb
            } elseif ((ord($string[$i]) & 0xFC) === 0xF8) {
                $n = 4; // 111110bb
            } elseif ((ord($string[$i]) & 0xFE) === 0xFC) {
                $n = 5; // 1111110b
            } else {
                return false; // Does not match any model
            }

            for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
                if (++$i === strlen($string) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Remove any illegal characters, accents, etc.
     *
     * @param  string $string String to unaccent
     *
     * @return string Unaccented string
     */
    public function unaccent(string $string): string
    {
        if (preg_match('/[\x80-\xff]/', $string) === false) {
            return $string;
        }

        if ($this->seemsUtf8($string)) {
            $string = strtr($string, self::ACCENTED_CHARACTERS);
        } else {
            $characters = [];

            // Assume ISO-8859-1 if not UTF-8
            $characters['in'] =
                  chr(128)
                . chr(131)
                . chr(138)
                . chr(142)
                . chr(154)
                . chr(158)
                . chr(159)
                . chr(162)
                . chr(165)
                . chr(181)
                . chr(192)
                . chr(193)
                . chr(194)
                . chr(195)
                . chr(196)
                . chr(197)
                . chr(199)
                . chr(200)
                . chr(201)
                . chr(202)
                . chr(203)
                . chr(204)
                . chr(205)
                . chr(206)
                . chr(207)
                . chr(209)
                . chr(210)
                . chr(211)
                . chr(212)
                . chr(213)
                . chr(214)
                . chr(216)
                . chr(217)
                . chr(218)
                . chr(219)
                . chr(220)
                . chr(221)
                . chr(224)
                . chr(225)
                . chr(226)
                . chr(227)
                . chr(228)
                . chr(229)
                . chr(231)
                . chr(232)
                . chr(233)
                . chr(234)
                . chr(235)
                . chr(236)
                . chr(237)
                . chr(238)
                . chr(239)
                . chr(241)
                . chr(242)
                . chr(243)
                . chr(244)
                . chr(245)
                . chr(246)
                . chr(248)
                . chr(249)
                . chr(250)
                . chr(251)
                . chr(252)
                . chr(253)
                . chr(255);

            $characters['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';

            $string = strtr($string, $characters['in'], $characters['out']);

            $doubleChars = [];

            $doubleChars['in'] = [
                chr(140),
                chr(156),
                chr(198),
                chr(208),
                chr(222),
                chr(223),
                chr(230),
                chr(240),
                chr(254),
            ];

            $doubleChars['out'] = ['OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'];

            $string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
        }

        return $string;
    }

    /**
     * Convert any passed string to a url friendly string.
     * Converts 'My first blog post' to 'my-first-blog-post'
     *
     * @param  string $string String to urlize.
     *
     * @return string Urlized string.
     */
    public function urlize(string $string): string
    {
        // Remove all non url friendly characters with the unaccent function
        $unaccented = $this->unaccent($string);

        if (function_exists('mb_strtolower')) {
            $lowered = mb_strtolower($unaccented);
        } else {
            $lowered = strtolower($unaccented);
        }

        $replacements = [
            '/\W/' => ' ',
            '/([A-Z]+)([A-Z][a-z])/' => '\1_\2',
            '/([a-z\d])([A-Z])/' => '\1_\2',
            '/[^A-Z^a-z^0-9^\/]+/' => '-',
        ];

        $urlized = $lowered;

        foreach ($replacements as $pattern => $replacement) {
            $replaced = preg_replace($pattern, $replacement, $urlized);

            if ($replaced === null) {
                throw new RuntimeException(sprintf(
                    'preg_replace returned null for value "%s"',
                    $urlized
                ));
            }

            $urlized = $replaced;
        }

        return trim($urlized, '-');
    }

    /**
     * Returns a word in singular form.
     *
     * @param string $word The word in plural form.
     *
     * @return string The word in singular form.
     */
    public function singularize(string $word): string
    {
        return $this->singularizer->inflect($word);
    }

    /**
     * Returns a word in plural form.
     *
     * @param string $word The word in singular form.
     *
     * @return string The word in plural form.
     */
    public function pluralize(string $word): string
    {
        return $this->pluralizer->inflect($word);
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

interface WordInflector
{
    public function inflect(string $word): string;
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

final class Language
{
    public const ENGLISH          = 'english';
    public const ESPERANTO        = 'esperanto';
    public const FRENCH           = 'french';
    public const ITALIAN          = 'italian';
    public const NORWEGIAN_BOKMAL = 'norwegian-bokmal';
    public const PORTUGUESE       = 'portuguese';
    public const SPANISH          = 'spanish';
    public const TURKISH          = 'turkish';

    private function __construct()
    {
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

class NoopWordInflector implements WordInflector
{
    public function inflect(string $word): string
    {
        return $word;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\Ruleset;

use function array_merge;

/**
 * Inflects based on multiple rulesets.
 *
 * Rules:
 * - If the word matches any uninflected word pattern, it is not inflected
 * - The first ruleset that returns a different value for an irregular word wins
 * - The first ruleset that returns a different value for a regular word wins
 * - If none of the above match, the word is left as-is
 */
class RulesetInflector implements WordInflector
{
    /** @var Ruleset[] */
    private $rulesets;

    public function __construct(Ruleset $ruleset, Ruleset ...$rulesets)
    {
        $this->rulesets = array_merge([$ruleset], $rulesets);
    }

    public function inflect(string $word): string
    {
        if ($word === '') {
            return '';
        }

        foreach ($this->rulesets as $ruleset) {
            if ($ruleset->getUninflected()->matches($word)) {
                return $word;
            }

            $inflected = $ruleset->getIrregular()->inflect($word);

            if ($inflected !== $word) {
                return $inflected;
            }

            $inflected = $ruleset->getRegular()->inflect($word);

            if ($inflected !== $word) {
                return $inflected;
            }
        }

        return $word;
    }
}
<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\Ruleset;

use function array_unshift;

abstract class GenericLanguageInflectorFactory implements LanguageInflectorFactory
{
    /** @var Ruleset[] */
    private $singularRulesets = [];

    /** @var Ruleset[] */
    private $pluralRulesets = [];

    final public function __construct()
    {
        $this->singularRulesets[] = $this->getSingularRuleset();
        $this->pluralRulesets[]   = $this->getPluralRuleset();
    }

    final public function build(): Inflector
    {
        return new Inflector(
            new CachedWordInflector(new RulesetInflector(
                ...$this->singularRulesets
            )),
            new CachedWordInflector(new RulesetInflector(
                ...$this->pluralRulesets
            ))
        );
    }

    final public function withSingularRules(?Ruleset $singularRules, bool $reset = false): LanguageInflectorFactory
    {
        if ($reset) {
            $this->singularRulesets = [];
        }

        if ($singularRules instanceof Ruleset) {
            array_unshift($this->singularRulesets, $singularRules);
        }

        return $this;
    }

    final public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): LanguageInflectorFactory
    {
        if ($reset) {
            $this->pluralRulesets = [];
        }

        if ($pluralRules instanceof Ruleset) {
            array_unshift($this->pluralRulesets, $pluralRules);
        }

        return $this;
    }

    abstract protected function getSingularRuleset(): Ruleset;

    abstract protected function getPluralRuleset(): Ruleset;
}
Copyright (c) 2006-2015 Doctrine Project

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
<?php

namespace Illuminate\Support;

class HigherOrderWhenProxy
{
    /**
     * The target being conditionally operated on.
     *
     * @var mixed
     */
    protected $target;

    /**
     * The condition for proxying.
     *
     * @var bool
     */
    protected $condition;

    /**
     * Indicates whether the proxy has a condition.
     *
     * @var bool
     */
    protected $hasCondition = false;

    /**
     * Determine whether the condition should be negated.
     *
     * @var bool
     */
    protected $negateConditionOnCapture;

    /**
     * Create a new proxy instance.
     *
     * @param  mixed  $target
     */
    public function __construct($target)
    {
        $this->target = $target;
    }

    /**
     * Set the condition on the proxy.
     *
     * @param  bool  $condition
     * @return $this
     */
    public function condition($condition)
    {
        [$this->condition, $this->hasCondition] = [$condition, true];

        return $this;
    }

    /**
     * Indicate that the condition should be negated.
     *
     * @return $this
     */
    public function negateConditionOnCapture()
    {
        $this->negateConditionOnCapture = true;

        return $this;
    }

    /**
     * Proxy accessing an attribute onto the target.
     *
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {
        if (! $this->hasCondition) {
            $condition = $this->target->{$key};

            return $this->condition($this->negateConditionOnCapture ? ! $condition : $condition);
        }

        return $this->condition
            ? $this->target->{$key}
            : $this->target;
    }

    /**
     * Proxy a method call on the target.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        if (! $this->hasCondition) {
            $condition = $this->target->{$method}(...$parameters);

            return $this->condition($this->negateConditionOnCapture ? ! $condition : $condition);
        }

        return $this->condition
            ? $this->target->{$method}(...$parameters)
            : $this->target;
    }
}
<?php

namespace Illuminate\Support\Traits;

use Closure;
use Illuminate\Support\HigherOrderWhenProxy;

trait Conditionable
{
    /**
     * Apply the callback if the given "value" is (or resolves to) truthy.
     *
     * @template TWhenParameter
     * @template TWhenReturnType
     *
     * @param  (\Closure($this): TWhenParameter)|TWhenParameter|null  $value
     * @param  (callable($this, TWhenParameter): TWhenReturnType)|null  $callback
     * @param  (callable($this, TWhenParameter): TWhenReturnType)|null  $default
     * @return $this|TWhenReturnType
     */
    public function when($value = null, ?callable $callback = null, ?callable $default = null)
    {
        $value = $value instanceof Closure ? $value($this) : $value;

        if (func_num_args() === 0) {
            return new HigherOrderWhenProxy($this);
        }

        if (func_num_args() === 1) {
            return (new HigherOrderWhenProxy($this))->condition($value);
        }

        if ($value) {
            return $callback($this, $value) ?? $this;
        } elseif ($default) {
            return $default($this, $value) ?? $this;
        }

        return $this;
    }

    /**
     * Apply the callback if the given "value" is (or resolves to) falsy.
     *
     * @template TUnlessParameter
     * @template TUnlessReturnType
     *
     * @param  (\Closure($this): TUnlessParameter)|TUnlessParameter|null  $value
     * @param  (callable($this, TUnlessParameter): TUnlessReturnType)|null  $callback
     * @param  (callable($this, TUnlessParameter): TUnlessReturnType)|null  $default
     * @return $this|TUnlessReturnType
     */
    public function unless($value = null, ?callable $callback = null, ?callable $default = null)
    {
        $value = $value instanceof Closure ? $value($this) : $value;

        if (func_num_args() === 0) {
            return (new HigherOrderWhenProxy($this))->negateConditionOnCapture();
        }

        if (func_num_args() === 1) {
            return (new HigherOrderWhenProxy($this))->condition(! $value);
        }

        if (! $value) {
            return $callback($this, $value) ?? $this;
        } elseif ($default) {
            return $default($this, $value) ?? $this;
        }

        return $this;
    }
}
<?php

namespace Illuminate\Contracts\Mail;

interface Factory
{
    /**
     * Get a mailer instance by name.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Mail\Mailer
     */
    public function mailer($name = null);
}
<?php

namespace Illuminate\Contracts\Mail;

use Illuminate\Contracts\Queue\Factory as Queue;

interface Mailable
{
    /**
     * Send the message using the given mailer.
     *
     * @param  \Illuminate\Contracts\Mail\Factory|\Illuminate\Contracts\Mail\Mailer  $mailer
     * @return \Illuminate\Mail\SentMessage|null
     */
    public function send($mailer);

    /**
     * Queue the given message.
     *
     * @param  \Illuminate\Contracts\Queue\Factory  $queue
     * @return mixed
     */
    public function queue(Queue $queue);

    /**
     * Deliver the queued message after (n) seconds.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  \Illuminate\Contracts\Queue\Factory  $queue
     * @return mixed
     */
    public function later($delay, Queue $queue);

    /**
     * Set the recipients of the message.
     *
     * @param  object|array|string  $address
     * @param  string|null  $name
     * @return $this
     */
    public function cc($address, $name = null);

    /**
     * Set the recipients of the message.
     *
     * @param  object|array|string  $address
     * @param  string|null  $name
     * @return $this
     */
    public function bcc($address, $name = null);

    /**
     * Set the recipients of the message.
     *
     * @param  object|array|string  $address
     * @param  string|null  $name
     * @return $this
     */
    public function to($address, $name = null);

    /**
     * Set the locale of the message.
     *
     * @param  string  $locale
     * @return $this
     */
    public function locale($locale);

    /**
     * Set the name of the mailer that should be used to send the message.
     *
     * @param  string  $mailer
     * @return $this
     */
    public function mailer($mailer);
}
<?php

namespace Illuminate\Contracts\Mail;

interface Mailer
{
    /**
     * Begin the process of mailing a mailable class instance.
     *
     * @param  mixed  $users
     * @return \Illuminate\Mail\PendingMail
     */
    public function to($users);

    /**
     * Begin the process of mailing a mailable class instance.
     *
     * @param  mixed  $users
     * @return \Illuminate\Mail\PendingMail
     */
    public function cc($users);

    /**
     * Begin the process of mailing a mailable class instance.
     *
     * @param  mixed  $users
     * @return \Illuminate\Mail\PendingMail
     */
    public function bcc($users);

    /**
     * Send a new message with only a raw text part.
     *
     * @param  string  $text
     * @param  mixed  $callback
     * @return \Illuminate\Mail\SentMessage|null
     */
    public function raw($text, $callback);

    /**
     * Send a new message using a view.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  array  $data
     * @param  \Closure|string|null  $callback
     * @return \Illuminate\Mail\SentMessage|null
     */
    public function send($view, array $data = [], $callback = null);

    /**
     * Send a new message synchronously using a view.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $mailable
     * @param  array  $data
     * @param  \Closure|string|null  $callback
     * @return \Illuminate\Mail\SentMessage|null
     */
    public function sendNow($mailable, array $data = [], $callback = null);
}
<?php

namespace Illuminate\Contracts\Mail;

interface Attachable
{
    /**
     * Get an attachment instance for this entity.
     *
     * @return \Illuminate\Mail\Attachment
     */
    public function toMailAttachment();
}
<?php

namespace Illuminate\Contracts\Mail;

interface MailQueue
{
    /**
     * Queue a new e-mail message for sending.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  string|null  $queue
     * @return mixed
     */
    public function queue($view, $queue = null);

    /**
     * Queue a new e-mail message for sending after (n) seconds.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  string|null  $queue
     * @return mixed
     */
    public function later($delay, $view, $queue = null);
}
<?php

namespace Illuminate\Contracts\Cache;

interface Factory
{
    /**
     * Get a cache store instance by name.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Cache\Repository
     */
    public function store($name = null);
}
<?php

namespace Illuminate\Contracts\Cache;

use Closure;
use Psr\SimpleCache\CacheInterface;

interface Repository extends CacheInterface
{
    /**
     * Retrieve an item from the cache and delete it.
     *
     * @template TCacheValue
     *
     * @param  \UnitEnum|array|string  $key
     * @param  TCacheValue|(\Closure(): TCacheValue)  $default
     * @return (TCacheValue is null ? mixed : TCacheValue)
     */
    public function pull($key, $default = null);

    /**
     * Store an item in the cache.
     *
     * @param  \UnitEnum|string  $key
     * @param  mixed  $value
     * @param  \DateTimeInterface|\DateInterval|int|null  $ttl
     * @return bool
     */
    public function put($key, $value, $ttl = null);

    /**
     * Store an item in the cache if the key does not exist.
     *
     * @param  \UnitEnum|string  $key
     * @param  mixed  $value
     * @param  \DateTimeInterface|\DateInterval|int|null  $ttl
     * @return bool
     */
    public function add($key, $value, $ttl = null);

    /**
     * Increment the value of an item in the cache.
     *
     * @param  \UnitEnum|string  $key
     * @param  mixed  $value
     * @return int|bool
     */
    public function increment($key, $value = 1);

    /**
     * Decrement the value of an item in the cache.
     *
     * @param  \UnitEnum|string  $key
     * @param  mixed  $value
     * @return int|bool
     */
    public function decrement($key, $value = 1);

    /**
     * Store an item in the cache indefinitely.
     *
     * @param  \UnitEnum|string  $key
     * @param  mixed  $value
     * @return bool
     */
    public function forever($key, $value);

    /**
     * Get an item from the cache, or execute the given Closure and store the result.
     *
     * @template TCacheValue
     *
     * @param  \UnitEnum|string  $key
     * @param  \DateTimeInterface|\DateInterval|\Closure|int|null  $ttl
     * @param  \Closure(): TCacheValue  $callback
     * @return TCacheValue
     */
    public function remember($key, $ttl, Closure $callback);

    /**
     * Get an item from the cache, or execute the given Closure and store the result forever.
     *
     * @template TCacheValue
     *
     * @param  \UnitEnum|string  $key
     * @param  \Closure(): TCacheValue  $callback
     * @return TCacheValue
     */
    public function sear($key, Closure $callback);

    /**
     * Get an item from the cache, or execute the given Closure and store the result forever.
     *
     * @template TCacheValue
     *
     * @param  \UnitEnum|string  $key
     * @param  \Closure(): TCacheValue  $callback
     * @return TCacheValue
     */
    public function rememberForever($key, Closure $callback);

    /**
     * Set the expiration of a cached item.
     *
     * @param  \UnitEnum|string  $key
     * @param  \DateTimeInterface|\DateInterval|int  $ttl
     * @return bool
     */
    public function touch($key, $ttl);

    /**
     * Remove an item from the cache.
     *
     * @param  \UnitEnum|string  $key
     * @return bool
     */
    public function forget($key);

    /**
     * Get the cache store implementation.
     *
     * @return \Illuminate\Contracts\Cache\Store
     */
    public function getStore();
}
<?php

namespace Illuminate\Contracts\Cache;

interface LockProvider
{
    /**
     * Get a lock instance.
     *
     * @param  string  $name
     * @param  int  $seconds
     * @param  string|null  $owner
     * @return \Illuminate\Contracts\Cache\Lock
     */
    public function lock($name, $seconds = 0, $owner = null);

    /**
     * Restore a lock instance using the owner identifier.
     *
     * @param  string  $name
     * @param  string  $owner
     * @return \Illuminate\Contracts\Cache\Lock
     */
    public function restoreLock($name, $owner);
}
<?php

namespace Illuminate\Contracts\Cache;

interface Lock
{
    /**
     * Attempt to acquire the lock.
     *
     * @param  callable|null  $callback
     * @return mixed
     */
    public function get($callback = null);

    /**
     * Attempt to acquire the lock for the given number of seconds.
     *
     * @param  int  $seconds
     * @param  callable|null  $callback
     * @return mixed
     *
     * @throws \Illuminate\Contracts\Cache\LockTimeoutException
     */
    public function block($seconds, $callback = null);

    /**
     * Release the lock.
     *
     * @return bool
     */
    public function release();

    /**
     * Returns the current owner of the lock.
     *
     * @return string
     */
    public function owner();

    /**
     * Releases this lock in disregard of ownership.
     *
     * @return void
     */
    public function forceRelease();
}
<?php

namespace Illuminate\Contracts\Cache;

interface Store
{
    /**
     * Retrieve an item from the cache by key.
     *
     * @param  string  $key
     * @return mixed
     */
    public function get($key);

    /**
     * Retrieve multiple items from the cache by key.
     *
     * Items not found in the cache will have a null value.
     *
     * @param  array  $keys
     * @return array
     */
    public function many(array $keys);

    /**
     * Store an item in the cache for a given number of seconds.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @param  int  $seconds
     * @return bool
     */
    public function put($key, $value, $seconds);

    /**
     * Store multiple items in the cache for a given number of seconds.
     *
     * @param  array  $values
     * @param  int  $seconds
     * @return bool
     */
    public function putMany(array $values, $seconds);

    /**
     * Increment the value of an item in the cache.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return int|bool
     */
    public function increment($key, $value = 1);

    /**
     * Decrement the value of an item in the cache.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return int|bool
     */
    public function decrement($key, $value = 1);

    /**
     * Store an item in the cache indefinitely.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return bool
     */
    public function forever($key, $value);

    /**
     * Set the expiration of a cached item.
     *
     * @param  string  $key
     * @param  int  $seconds
     * @return bool
     */
    public function touch($key, $seconds);

    /**
     * Remove an item from the cache.
     *
     * @param  string  $key
     * @return bool
     */
    public function forget($key);

    /**
     * Remove all items from the cache.
     *
     * @return bool
     */
    public function flush();

    /**
     * Get the cache key prefix.
     *
     * @return string
     */
    public function getPrefix();
}
<?php

namespace Illuminate\Contracts\Cache;

interface CanFlushLocks
{
    /**
     * Flush all locks managed by the store.
     *
     * @return bool
     */
    public function flushLocks(): bool;

    /**
     * Determine if the lock store is separate from the cache store.
     *
     * @return bool
     */
    public function hasSeparateLockStore(): bool;
}
<?php

namespace Illuminate\Contracts\Cache;

use Exception;

class LockTimeoutException extends Exception
{
    //
}
<?php

namespace Illuminate\Contracts\Container;

use Exception;
use Psr\Container\ContainerExceptionInterface;

class BindingResolutionException extends Exception implements ContainerExceptionInterface
{
    //
}
<?php

namespace Illuminate\Contracts\Container;

/**
 * @method static newInstance(): static
 */
interface SelfBuilding
{
}
<?php

namespace Illuminate\Contracts\Container;

interface ContextualAttribute
{
    //
}
<?php

namespace Illuminate\Contracts\Container;

use Closure;
use Psr\Container\ContainerInterface;

interface Container extends ContainerInterface
{
    /**
     * {@inheritdoc}
     *
     * @template TClass of object
     *
     * @param  string|class-string<TClass>  $id
     * @return ($id is class-string<TClass> ? TClass : mixed)
     */
    public function get(string $id);

    /**
     * Determine if the given abstract type has been bound.
     *
     * @param  string  $abstract
     * @return bool
     */
    public function bound($abstract);

    /**
     * Alias a type to a different name.
     *
     * @param  string  $abstract
     * @param  string  $alias
     * @return void
     *
     * @throws \LogicException
     */
    public function alias($abstract, $alias);

    /**
     * Assign a set of tags to a given binding.
     *
     * @param  array|string  $abstracts
     * @param  mixed  ...$tags
     * @return void
     */
    public function tag($abstracts, $tags);

    /**
     * Resolve all of the bindings for a given tag.
     *
     * @param  string  $tag
     * @return iterable
     */
    public function tagged($tag);

    /**
     * Register a binding with the container.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|string|null  $concrete
     * @param  bool  $shared
     * @return void
     */
    public function bind($abstract, $concrete = null, $shared = false);

    /**
     * Bind a callback to resolve with Container::call.
     *
     * @param  array|string  $method
     * @param  \Closure  $callback
     * @return void
     */
    public function bindMethod($method, $callback);

    /**
     * Register a binding if it hasn't already been registered.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|string|null  $concrete
     * @param  bool  $shared
     * @return void
     */
    public function bindIf($abstract, $concrete = null, $shared = false);

    /**
     * Register a shared binding in the container.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|string|null  $concrete
     * @return void
     */
    public function singleton($abstract, $concrete = null);

    /**
     * Register a shared binding if it hasn't already been registered.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|string|null  $concrete
     * @return void
     */
    public function singletonIf($abstract, $concrete = null);

    /**
     * Register a scoped binding in the container.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|string|null  $concrete
     * @return void
     */
    public function scoped($abstract, $concrete = null);

    /**
     * Register a scoped binding if it hasn't already been registered.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|string|null  $concrete
     * @return void
     */
    public function scopedIf($abstract, $concrete = null);

    /**
     * "Extend" an abstract type in the container.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure  $closure
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    public function extend($abstract, Closure $closure);

    /**
     * Register an existing instance as shared in the container.
     *
     * @template TInstance of mixed
     *
     * @param  \Closure|string  $abstract
     * @param  TInstance  $instance
     * @return TInstance
     */
    public function instance($abstract, $instance);

    /**
     * Add a contextual binding to the container.
     *
     * @param  string  $concrete
     * @param  \Closure|string  $abstract
     * @param  \Closure|string  $implementation
     * @return void
     */
    public function addContextualBinding($concrete, $abstract, $implementation);

    /**
     * Define a contextual binding.
     *
     * @param  string|array  $concrete
     * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
     */
    public function when($concrete);

    /**
     * Get a closure to resolve the given type from the container.
     *
     * @template TClass of object
     *
     * @param  string|class-string<TClass>  $abstract
     * @return ($abstract is class-string<TClass> ? \Closure(): TClass : \Closure(): mixed)
     */
    public function factory($abstract);

    /**
     * Flush the container of all bindings and resolved instances.
     *
     * @return void
     */
    public function flush();

    /**
     * Resolve the given type from the container.
     *
     * @template TClass of object
     *
     * @param  string|class-string<TClass>  $abstract
     * @param  array  $parameters
     * @return ($abstract is class-string<TClass> ? TClass : mixed)
     *
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function make($abstract, array $parameters = []);

    /**
     * Call the given Closure / class@method and inject its dependencies.
     *
     * @param  callable|string  $callback
     * @param  array  $parameters
     * @param  string|null  $defaultMethod
     * @return mixed
     */
    public function call($callback, array $parameters = [], $defaultMethod = null);

    /**
     * Determine if the given abstract type has been resolved.
     *
     * @param  string  $abstract
     * @return bool
     */
    public function resolved($abstract);

    /**
     * Register a new before resolving callback.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|null  $callback
     * @return void
     */
    public function beforeResolving($abstract, ?Closure $callback = null);

    /**
     * Register a new resolving callback.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|null  $callback
     * @return void
     */
    public function resolving($abstract, ?Closure $callback = null);

    /**
     * Register a new after resolving callback.
     *
     * @param  \Closure|string  $abstract
     * @param  \Closure|null  $callback
     * @return void
     */
    public function afterResolving($abstract, ?Closure $callback = null);
}
<?php

namespace Illuminate\Contracts\Container;

use Exception;
use Psr\Container\ContainerExceptionInterface;

class CircularDependencyException extends Exception implements ContainerExceptionInterface
{
    //
}
<?php

namespace Illuminate\Contracts\Container;

interface ContextualBindingBuilder
{
    /**
     * Define the abstract target that depends on the context.
     *
     * @param  string  $abstract
     * @return $this
     */
    public function needs($abstract);

    /**
     * Define the implementation for the contextual binding.
     *
     * @param  \Closure|string|array  $implementation
     * @return $this
     */
    public function give($implementation);

    /**
     * Define tagged services to be used as the implementation for the contextual binding.
     *
     * @param  string  $tag
     * @return $this
     */
    public function giveTagged($tag);

    /**
     * Specify the configuration item to bind as a primitive.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return $this
     */
    public function giveConfig($key, $default = null);
}
<?php

namespace Illuminate\Contracts\Foundation;

interface CachesConfiguration
{
    /**
     * Determine if the application configuration is cached.
     *
     * @return bool
     */
    public function configurationIsCached();

    /**
     * Get the path to the configuration cache file.
     *
     * @return string
     */
    public function getCachedConfigPath();

    /**
     * Get the path to the cached services.php file.
     *
     * @return string
     */
    public function getCachedServicesPath();
}
<?php

namespace Illuminate\Contracts\Foundation;

use Illuminate\Contracts\Container\Container;

interface Application extends Container
{
    /**
     * Get the version number of the application.
     *
     * @return string
     */
    public function version();

    /**
     * Get the base path of the Laravel installation.
     *
     * @param  string  $path
     * @return string
     */
    public function basePath($path = '');

    /**
     * Get the path to the bootstrap directory.
     *
     * @param  string  $path
     * @return string
     */
    public function bootstrapPath($path = '');

    /**
     * Get the path to the application configuration files.
     *
     * @param  string  $path
     * @return string
     */
    public function configPath($path = '');

    /**
     * Get the path to the database directory.
     *
     * @param  string  $path
     * @return string
     */
    public function databasePath($path = '');

    /**
     * Get the path to the language files.
     *
     * @param  string  $path
     * @return string
     */
    public function langPath($path = '');

    /**
     * Get the path to the public directory.
     *
     * @param  string  $path
     * @return string
     */
    public function publicPath($path = '');

    /**
     * Get the path to the resources directory.
     *
     * @param  string  $path
     * @return string
     */
    public function resourcePath($path = '');

    /**
     * Get the path to the storage directory.
     *
     * @param  string  $path
     * @return string
     */
    public function storagePath($path = '');

    /**
     * Get or check the current application environment.
     *
     * @param  string|array  ...$environments
     * @return string|bool
     */
    public function environment(...$environments);

    /**
     * Determine if the application is running in the console.
     *
     * @return bool
     */
    public function runningInConsole();

    /**
     * Determine if the application is running unit tests.
     *
     * @return bool
     */
    public function runningUnitTests();

    /**
     * Determine if the application is running with debug mode enabled.
     *
     * @return bool
     */
    public function hasDebugModeEnabled();

    /**
     * Get an instance of the maintenance mode manager implementation.
     *
     * @return \Illuminate\Contracts\Foundation\MaintenanceMode
     */
    public function maintenanceMode();

    /**
     * Determine if the application is currently down for maintenance.
     *
     * @return bool
     */
    public function isDownForMaintenance();

    /**
     * Register all of the configured providers.
     *
     * @return void
     */
    public function registerConfiguredProviders();

    /**
     * Register a service provider with the application.
     *
     * @param  \Illuminate\Support\ServiceProvider|string  $provider
     * @param  bool  $force
     * @return \Illuminate\Support\ServiceProvider
     */
    public function register($provider, $force = false);

    /**
     * Register a deferred provider and service.
     *
     * @param  string  $provider
     * @param  string|null  $service
     * @return void
     */
    public function registerDeferredProvider($provider, $service = null);

    /**
     * Resolve a service provider instance from the class name.
     *
     * @param  string  $provider
     * @return \Illuminate\Support\ServiceProvider
     */
    public function resolveProvider($provider);

    /**
     * Boot the application's service providers.
     *
     * @return void
     */
    public function boot();

    /**
     * Register a new boot listener.
     *
     * @param  callable  $callback
     * @return void
     */
    public function booting($callback);

    /**
     * Register a new "booted" listener.
     *
     * @param  callable  $callback
     * @return void
     */
    public function booted($callback);

    /**
     * Run the given array of bootstrap classes.
     *
     * @param  array  $bootstrappers
     * @return void
     */
    public function bootstrapWith(array $bootstrappers);

    /**
     * Get the current application locale.
     *
     * @return string
     */
    public function getLocale();

    /**
     * Get the application namespace.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    public function getNamespace();

    /**
     * Get the registered service provider instances if any exist.
     *
     * @param  \Illuminate\Support\ServiceProvider|string  $provider
     * @return array
     */
    public function getProviders($provider);

    /**
     * Determine if the application has been bootstrapped before.
     *
     * @return bool
     */
    public function hasBeenBootstrapped();

    /**
     * Load and boot all of the remaining deferred providers.
     *
     * @return void
     */
    public function loadDeferredProviders();

    /**
     * Set the current application locale.
     *
     * @param  string  $locale
     * @return void
     */
    public function setLocale($locale);

    /**
     * Determine if middleware has been disabled for the application.
     *
     * @return bool
     */
    public function shouldSkipMiddleware();

    /**
     * Register a terminating callback with the application.
     *
     * @param  callable|string  $callback
     * @return \Illuminate\Contracts\Foundation\Application
     */
    public function terminating($callback);

    /**
     * Terminate the application.
     *
     * @return void
     */
    public function terminate();
}
<?php

namespace Illuminate\Contracts\Foundation;

interface CachesRoutes
{
    /**
     * Determine if the application routes are cached.
     *
     * @return bool
     */
    public function routesAreCached();

    /**
     * Get the path to the routes cache file.
     *
     * @return string
     */
    public function getCachedRoutesPath();
}
<?php

namespace Illuminate\Contracts\Foundation;

interface MaintenanceMode
{
    /**
     * Take the application down for maintenance.
     *
     * @param  array  $payload
     * @return void
     */
    public function activate(array $payload): void;

    /**
     * Take the application out of maintenance.
     *
     * @return void
     */
    public function deactivate(): void;

    /**
     * Determine if the application is currently down for maintenance.
     *
     * @return bool
     */
    public function active(): bool;

    /**
     * Get the data array which was provided when the application was placed into maintenance.
     *
     * @return array
     */
    public function data(): array;
}
<?php

namespace Illuminate\Contracts\Foundation;

interface ExceptionRenderer
{
    /**
     * Renders the given exception as HTML.
     *
     * @param  \Throwable  $throwable
     * @return string
     */
    public function render($throwable);
}
<?php

namespace Illuminate\Contracts\Log;

use Monolog\Processor\ProcessorInterface;

interface ContextLogProcessor extends ProcessorInterface
{
}
<?php

namespace Illuminate\Contracts\Session\Middleware;

interface AuthenticatesSessions
{
    //
}
<?php

namespace Illuminate\Contracts\Session;

interface Session
{
    /**
     * Get the name of the session.
     *
     * @return string
     */
    public function getName();

    /**
     * Set the name of the session.
     *
     * @param  string  $name
     * @return void
     */
    public function setName($name);

    /**
     * Get the current session ID.
     *
     * @return string
     */
    public function getId();

    /**
     * Set the session ID.
     *
     * @param  string  $id
     * @return void
     */
    public function setId($id);

    /**
     * Start the session, reading the data from a handler.
     *
     * @return bool
     */
    public function start();

    /**
     * Save the session data to storage.
     *
     * @return void
     */
    public function save();

    /**
     * Get all of the session data.
     *
     * @return array
     */
    public function all();

    /**
     * Checks if a key exists.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function exists($key);

    /**
     * Checks if a key is present and not null.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function has($key);

    /**
     * Get an item from the session.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return mixed
     */
    public function get($key, $default = null);

    /**
     * Get the value of a given key and then forget it.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return mixed
     */
    public function pull($key, $default = null);

    /**
     * Put a key / value pair or array of key / value pairs in the session.
     *
     * @param  string|array  $key
     * @param  mixed  $value
     * @return void
     */
    public function put($key, $value = null);

    /**
     * Flash a key / value pair to the session.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function flash(string $key, $value = true);

    /**
     * Get the CSRF token value.
     *
     * @return string
     */
    public function token();

    /**
     * Regenerate the CSRF token value.
     *
     * @return void
     */
    public function regenerateToken();

    /**
     * Remove an item from the session, returning its value.
     *
     * @param  string  $key
     * @return mixed
     */
    public function remove($key);

    /**
     * Remove one or many items from the session.
     *
     * @param  string|array  $keys
     * @return void
     */
    public function forget($keys);

    /**
     * Remove all of the items from the session.
     *
     * @return void
     */
    public function flush();

    /**
     * Flush the session data and regenerate the ID.
     *
     * @return bool
     */
    public function invalidate();

    /**
     * Generate a new session identifier.
     *
     * @param  bool  $destroy
     * @return bool
     */
    public function regenerate($destroy = false);

    /**
     * Generate a new session ID for the session.
     *
     * @param  bool  $destroy
     * @return bool
     */
    public function migrate($destroy = false);

    /**
     * Determine if the session has been started.
     *
     * @return bool
     */
    public function isStarted();

    /**
     * Get the previous URL from the session.
     *
     * @return string|null
     */
    public function previousUrl();

    /**
     * Set the "previous" URL in the session.
     *
     * @param  string  $url
     * @return void
     */
    public function setPreviousUrl($url);

    /**
     * Get the session handler instance.
     *
     * @return \SessionHandlerInterface
     */
    public function getHandler();

    /**
     * Determine if the session handler needs a request.
     *
     * @return bool
     */
    public function handlerNeedsRequest();

    /**
     * Set the request on the handler instance.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    public function setRequestOnHandler($request);
}
<?php

namespace Illuminate\Contracts\Concurrency;

use Closure;
use Illuminate\Support\Defer\DeferredCallback;

interface Driver
{
    /**
     * Run the given tasks concurrently and return an array containing the results.
     */
    public function run(Closure|array $tasks): array;

    /**
     * Defer the execution of the given tasks.
     */
    public function defer(Closure|array $tasks): DeferredCallback;
}
<?php

namespace Illuminate\Contracts\Hashing;

interface Hasher
{
    /**
     * Get information about the given hashed value.
     *
     * @param  string  $hashedValue
     * @return array
     */
    public function info($hashedValue);

    /**
     * Hash the given value.
     *
     * @param  string  $value
     * @param  array  $options
     * @return string
     */
    public function make(#[\SensitiveParameter] $value, array $options = []);

    /**
     * Check the given plain value against a hash.
     *
     * @param  string  $value
     * @param  string  $hashedValue
     * @param  array  $options
     * @return bool
     */
    public function check(#[\SensitiveParameter] $value, $hashedValue, array $options = []);

    /**
     * Check if the given hash has been hashed using the given options.
     *
     * @param  string  $hashedValue
     * @param  array  $options
     * @return bool
     */
    public function needsRehash($hashedValue, array $options = []);
}
<?php

namespace Illuminate\Contracts\Bus;

interface QueueingDispatcher extends Dispatcher
{
    /**
     * Attempt to find the batch with the given ID.
     *
     * @param  string  $batchId
     * @return \Illuminate\Bus\Batch|null
     */
    public function findBatch(string $batchId);

    /**
     * Create a new batch of queueable jobs.
     *
     * @param  \Illuminate\Support\Collection|array  $jobs
     * @return \Illuminate\Bus\PendingBatch
     */
    public function batch($jobs);

    /**
     * Dispatch a command to its appropriate handler behind a queue.
     *
     * @param  mixed  $command
     * @return mixed
     */
    public function dispatchToQueue($command);
}
<?php

namespace Illuminate\Contracts\Bus;

interface Dispatcher
{
    /**
     * Dispatch a command to its appropriate handler.
     *
     * @param  mixed  $command
     * @return mixed
     */
    public function dispatch($command);

    /**
     * Dispatch a command to its appropriate handler in the current process.
     *
     * Queueable jobs will be dispatched to the "sync" queue.
     *
     * @param  mixed  $command
     * @param  mixed  $handler
     * @return mixed
     */
    public function dispatchSync($command, $handler = null);

    /**
     * Dispatch a command to its appropriate handler in the current process.
     *
     * @param  mixed  $command
     * @param  mixed  $handler
     * @return mixed
     */
    public function dispatchNow($command, $handler = null);

    /**
     * Dispatch a command to its appropriate handler after the current process.
     *
     * @param  mixed  $command
     * @param  mixed  $handler
     * @return void
     */
    public function dispatchAfterResponse($command, $handler = null);

    /**
     * Create a new chain of queueable jobs.
     *
     * @param  \Illuminate\Support\Collection|array|null  $jobs
     * @return mixed
     */
    public function chain($jobs = null);

    /**
     * Determine if the given command has a handler.
     *
     * @param  mixed  $command
     * @return bool
     */
    public function hasCommandHandler($command);

    /**
     * Retrieve the handler for a command.
     *
     * @param  mixed  $command
     * @return mixed
     */
    public function getCommandHandler($command);

    /**
     * Set the pipes commands should be piped through before dispatching.
     *
     * @param  array  $pipes
     * @return $this
     */
    public function pipeThrough(array $pipes);

    /**
     * Map a command to a handler.
     *
     * @param  array  $map
     * @return $this
     */
    public function map(array $map);
}
<?php

namespace Illuminate\Contracts\Filesystem;

interface Factory
{
    /**
     * Get a filesystem implementation.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function disk($name = null);
}
<?php

namespace Illuminate\Contracts\Filesystem;

interface Cloud extends Filesystem
{
    /**
     * Get the URL for the file at the given path.
     *
     * @param  string  $path
     * @return string
     */
    public function url($path);
}
<?php

namespace Illuminate\Contracts\Filesystem;

use Exception;

class LockTimeoutException extends Exception
{
    //
}
<?php

namespace Illuminate\Contracts\Filesystem;

interface Filesystem
{
    /**
     * The public visibility setting.
     *
     * @var string
     */
    const VISIBILITY_PUBLIC = 'public';

    /**
     * The private visibility setting.
     *
     * @var string
     */
    const VISIBILITY_PRIVATE = 'private';

    /**
     * Get the full path to the file that exists at the given relative path.
     *
     * @param  string  $path
     * @return string
     */
    public function path($path);

    /**
     * Determine if a file exists.
     *
     * @param  string  $path
     * @return bool
     */
    public function exists($path);

    /**
     * Get the contents of a file.
     *
     * @param  string  $path
     * @return string|null
     */
    public function get($path);

    /**
     * Get a resource to read the file.
     *
     * @param  string  $path
     * @return resource|null The path resource or null on failure.
     */
    public function readStream($path);

    /**
     * Write the contents of a file.
     *
     * @param  string  $path
     * @param  \Psr\Http\Message\StreamInterface|\Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|resource  $contents
     * @param  mixed  $options
     * @return bool
     */
    public function put($path, $contents, $options = []);

    /**
     * Store the uploaded file on the disk.
     *
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string  $path
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|array|null  $file
     * @param  mixed  $options
     * @return string|false
     */
    public function putFile($path, $file = null, $options = []);

    /**
     * Store the uploaded file on the disk with a given name.
     *
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string  $path
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|array|null  $file
     * @param  string|array|null  $name
     * @param  mixed  $options
     * @return string|false
     */
    public function putFileAs($path, $file, $name = null, $options = []);

    /**
     * Write a new file using a stream.
     *
     * @param  string  $path
     * @param  resource  $resource
     * @param  array  $options
     * @return bool
     */
    public function writeStream($path, $resource, array $options = []);

    /**
     * Get the visibility for the given path.
     *
     * @param  string  $path
     * @return string
     */
    public function getVisibility($path);

    /**
     * Set the visibility for the given path.
     *
     * @param  string  $path
     * @param  string  $visibility
     * @return bool
     */
    public function setVisibility($path, $visibility);

    /**
     * Prepend to a file.
     *
     * @param  string  $path
     * @param  string  $data
     * @return bool
     */
    public function prepend($path, $data);

    /**
     * Append to a file.
     *
     * @param  string  $path
     * @param  string  $data
     * @return bool
     */
    public function append($path, $data);

    /**
     * Delete the file at a given path.
     *
     * @param  string|array  $paths
     * @return bool
     */
    public function delete($paths);

    /**
     * Copy a file to a new location.
     *
     * @param  string  $from
     * @param  string  $to
     * @return bool
     */
    public function copy($from, $to);

    /**
     * Move a file to a new location.
     *
     * @param  string  $from
     * @param  string  $to
     * @return bool
     */
    public function move($from, $to);

    /**
     * Get the file size of a given file.
     *
     * @param  string  $path
     * @return int
     */
    public function size($path);

    /**
     * Get the file's last modification time.
     *
     * @param  string  $path
     * @return int
     */
    public function lastModified($path);

    /**
     * Get an array of all files in a directory.
     *
     * @param  string|null  $directory
     * @param  bool  $recursive
     * @return array<string>
     */
    public function files($directory = null, $recursive = false);

    /**
     * Get all of the files from the given directory (recursive).
     *
     * @param  string|null  $directory
     * @return array<string>
     */
    public function allFiles($directory = null);

    /**
     * Get all of the directories within a given directory.
     *
     * @param  string|null  $directory
     * @param  bool  $recursive
     * @return array<string>
     */
    public function directories($directory = null, $recursive = false);

    /**
     * Get all (recursive) of the directories within a given directory.
     *
     * @param  string|null  $directory
     * @return array<string>
     */
    public function allDirectories($directory = null);

    /**
     * Create a directory.
     *
     * @param  string  $path
     * @return bool
     */
    public function makeDirectory($path);

    /**
     * Recursively delete a directory.
     *
     * @param  string  $directory
     * @return bool
     */
    public function deleteDirectory($directory);
}
<?php

namespace Illuminate\Contracts\Filesystem;

use Exception;

class FileNotFoundException extends Exception
{
    //
}
<?php

namespace Illuminate\Contracts\Cookie;

interface Factory
{
    /**
     * Create a new cookie instance.
     *
     * @param  string  $name
     * @param  string  $value
     * @param  int  $minutes
     * @param  string|null  $path
     * @param  string|null  $domain
     * @param  bool|null  $secure
     * @param  bool  $httpOnly
     * @param  bool  $raw
     * @param  string|null  $sameSite
     * @return \Symfony\Component\HttpFoundation\Cookie
     */
    public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null);

    /**
     * Create a cookie that lasts "forever" (400 days).
     *
     * @param  string  $name
     * @param  string  $value
     * @param  string|null  $path
     * @param  string|null  $domain
     * @param  bool|null  $secure
     * @param  bool  $httpOnly
     * @param  bool  $raw
     * @param  string|null  $sameSite
     * @return \Symfony\Component\HttpFoundation\Cookie
     */
    public function forever($name, $value, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null);

    /**
     * Expire the given cookie.
     *
     * @param  string  $name
     * @param  string|null  $path
     * @param  string|null  $domain
     * @return \Symfony\Component\HttpFoundation\Cookie
     */
    public function forget($name, $path = null, $domain = null);
}
<?php

namespace Illuminate\Contracts\Cookie;

interface QueueingFactory extends Factory
{
    /**
     * Queue a cookie to send with the next response.
     *
     * @param  mixed  ...$parameters
     * @return void
     */
    public function queue(...$parameters);

    /**
     * Remove a cookie from the queue.
     *
     * @param  string  $name
     * @param  string|null  $path
     * @return void
     */
    public function unqueue($name, $path = null);

    /**
     * Get the cookies which have been queued for the next request.
     *
     * @return array
     */
    public function getQueuedCookies();
}
<?php

namespace Illuminate\Contracts\Config;

interface Repository
{
    /**
     * Determine if the given configuration value exists.
     *
     * @param  string  $key
     * @return bool
     */
    public function has($key);

    /**
     * Get the specified configuration value.
     *
     * @param  array|string  $key
     * @param  mixed  $default
     * @return mixed
     */
    public function get($key, $default = null);

    /**
     * Get all of the configuration items for the application.
     *
     * @return array
     */
    public function all();

    /**
     * Set a given configuration value.
     *
     * @param  array|string  $key
     * @param  mixed  $value
     * @return void
     */
    public function set($key, $value = null);

    /**
     * Prepend a value onto an array configuration value.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function prepend($key, $value);

    /**
     * Push a value onto an array configuration value.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    public function push($key, $value);
}
<?php

namespace Illuminate\Contracts\View;

interface Factory
{
    /**
     * Determine if a given view exists.
     *
     * @param  string  $view
     * @return bool
     */
    public function exists($view);

    /**
     * Get the evaluated view contents for the given path.
     *
     * @param  string  $path
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
     * @param  array  $mergeData
     * @return \Illuminate\Contracts\View\View
     */
    public function file($path, $data = [], $mergeData = []);

    /**
     * Get the evaluated view contents for the given view.
     *
     * @param  string  $view
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
     * @param  array  $mergeData
     * @return \Illuminate\Contracts\View\View
     */
    public function make($view, $data = [], $mergeData = []);

    /**
     * Add a piece of shared data to the environment.
     *
     * @param  array|string  $key
     * @param  mixed  $value
     * @return mixed
     */
    public function share($key, $value = null);

    /**
     * Register a view composer event.
     *
     * @param  array|string  $views
     * @param  \Closure|string  $callback
     * @return array
     */
    public function composer($views, $callback);

    /**
     * Register a view creator event.
     *
     * @param  array|string  $views
     * @param  \Closure|string  $callback
     * @return array
     */
    public function creator($views, $callback);

    /**
     * Add a new namespace to the loader.
     *
     * @param  string  $namespace
     * @param  string|array  $hints
     * @return $this
     */
    public function addNamespace($namespace, $hints);

    /**
     * Replace the namespace hints for the given namespace.
     *
     * @param  string  $namespace
     * @param  string|array  $hints
     * @return $this
     */
    public function replaceNamespace($namespace, $hints);
}
<?php

namespace Illuminate\Contracts\View;

interface Engine
{
    /**
     * Get the evaluated contents of the view.
     *
     * @param  string  $path
     * @param  array  $data
     * @return string
     */
    public function get($path, array $data = []);
}
<?php

namespace Illuminate\Contracts\View;

use Exception;

class ViewCompilationException extends Exception
{
    //
}
<?php

namespace Illuminate\Contracts\View;

use Illuminate\Contracts\Support\Renderable;

interface View extends Renderable
{
    /**
     * Get the name of the view.
     *
     * @return string
     */
    public function name();

    /**
     * Add a piece of data to the view.
     *
     * @param  string|array  $key
     * @param  mixed  $value
     * @return $this
     */
    public function with($key, $value = null);

    /**
     * Get the array of view data.
     *
     * @return array
     */
    public function getData();
}
<?php

namespace Illuminate\Contracts\Auth;

interface Factory
{
    /**
     * Get a guard instance by name.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
     */
    public function guard($name = null);

    /**
     * Set the default guard the factory should serve.
     *
     * @param  \UnitEnum|string|null  $name
     * @return void
     */
    public function shouldUse($name);
}
<?php

namespace Illuminate\Contracts\Auth\Access;

interface Gate
{
    /**
     * Determine if a given ability has been defined.
     *
     * @param  \UnitEnum|string  $ability
     * @return bool
     */
    public function has($ability);

    /**
     * Define a new ability.
     *
     * @param  \UnitEnum|string  $ability
     * @param  callable|string  $callback
     * @return $this
     */
    public function define($ability, $callback);

    /**
     * Define abilities for a resource.
     *
     * @param  string  $name
     * @param  string  $class
     * @param  array|null  $abilities
     * @return $this
     */
    public function resource($name, $class, ?array $abilities = null);

    /**
     * Define a policy class for a given class type.
     *
     * @param  string  $class
     * @param  string  $policy
     * @return $this
     */
    public function policy($class, $policy);

    /**
     * Register a callback to run before all Gate checks.
     *
     * @param  callable  $callback
     * @return $this
     */
    public function before(callable $callback);

    /**
     * Register a callback to run after all Gate checks.
     *
     * @param  callable  $callback
     * @return $this
     */
    public function after(callable $callback);

    /**
     * Determine if all of the given abilities should be granted for the current user.
     *
     * @param  iterable|\UnitEnum|string  $ability
     * @param  mixed  $arguments
     * @return bool
     */
    public function allows($ability, $arguments = []);

    /**
     * Determine if any of the given abilities should be denied for the current user.
     *
     * @param  iterable|\UnitEnum|string  $ability
     * @param  mixed  $arguments
     * @return bool
     */
    public function denies($ability, $arguments = []);

    /**
     * Determine if all of the given abilities should be granted for the current user.
     *
     * @param  iterable|\UnitEnum|string  $abilities
     * @param  mixed  $arguments
     * @return bool
     */
    public function check($abilities, $arguments = []);

    /**
     * Determine if any one of the given abilities should be granted for the current user.
     *
     * @param  iterable|\UnitEnum|string  $abilities
     * @param  mixed  $arguments
     * @return bool
     */
    public function any($abilities, $arguments = []);

    /**
     * Determine if the given ability should be granted for the current user.
     *
     * @param  \UnitEnum|string  $ability
     * @param  mixed  $arguments
     * @return \Illuminate\Auth\Access\Response
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function authorize($ability, $arguments = []);

    /**
     * Inspect the user for the given ability.
     *
     * @param  \UnitEnum|string  $ability
     * @param  mixed  $arguments
     * @return \Illuminate\Auth\Access\Response
     */
    public function inspect($ability, $arguments = []);

    /**
     * Get the raw result from the authorization callback.
     *
     * @param  string  $ability
     * @param  mixed  $arguments
     * @return mixed
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function raw($ability, $arguments = []);

    /**
     * Get a policy instance for a given class.
     *
     * @param  object|string  $class
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    public function getPolicyFor($class);

    /**
     * Get a guard instance for the given user.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable|mixed  $user
     * @return static
     */
    public function forUser($user);

    /**
     * Get all of the defined abilities.
     *
     * @return array
     */
    public function abilities();
}
<?php

namespace Illuminate\Contracts\Auth\Access;

interface Authorizable
{
    /**
     * Determine if the entity has a given ability.
     *
     * @param  iterable|string  $abilities
     * @param  mixed  $arguments
     * @return bool
     */
    public function can($abilities, $arguments = []);
}
<?php

namespace Illuminate\Contracts\Auth;

interface StatefulGuard extends Guard
{
    /**
     * Attempt to authenticate a user using the given credentials.
     *
     * @param  array  $credentials
     * @param  bool  $remember
     * @return bool
     */
    public function attempt(array $credentials = [], $remember = false);

    /**
     * Log a user into the application without sessions or cookies.
     *
     * @param  array  $credentials
     * @return bool
     */
    public function once(array $credentials = []);

    /**
     * Log a user into the application.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  bool  $remember
     * @return void
     */
    public function login(Authenticatable $user, $remember = false);

    /**
     * Log the given user ID into the application.
     *
     * @param  mixed  $id
     * @param  bool  $remember
     * @return \Illuminate\Contracts\Auth\Authenticatable|false
     */
    public function loginUsingId($id, $remember = false);

    /**
     * Log the given user ID into the application without sessions or cookies.
     *
     * @param  mixed  $id
     * @return \Illuminate\Contracts\Auth\Authenticatable|false
     */
    public function onceUsingId($id);

    /**
     * Determine if the user was authenticated via "remember me" cookie.
     *
     * @return bool
     */
    public function viaRemember();

    /**
     * Log the user out of the application.
     *
     * @return void
     */
    public function logout();
}
<?php

namespace Illuminate\Contracts\Auth\Middleware;

interface AuthenticatesRequests
{
    //
}
<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider
{
    /**
     * Retrieve a user by their unique identifier.
     *
     * @param  mixed  $identifier
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveById($identifier);

    /**
     * Retrieve a user by their unique identifier and "remember me" token.
     *
     * @param  mixed  $identifier
     * @param  string  $token
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByToken($identifier, #[\SensitiveParameter] $token);

    /**
     * Update the "remember me" token for the given user in storage.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  string  $token
     * @return void
     */
    public function updateRememberToken(Authenticatable $user, #[\SensitiveParameter] $token);

    /**
     * Retrieve a user by the given credentials.
     *
     * @param  array  $credentials
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(#[\SensitiveParameter] array $credentials);

    /**
     * Validate a user against the given credentials.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  array  $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable $user, #[\SensitiveParameter] array $credentials);

    /**
     * Rehash the user's password if required and supported.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  array  $credentials
     * @param  bool  $force
     * @return void
     */
    public function rehashPasswordIfRequired(Authenticatable $user, #[\SensitiveParameter] array $credentials, bool $force = false);
}
<?php

namespace Illuminate\Contracts\Auth;

interface PasswordBrokerFactory
{
    /**
     * Get a password broker instance by name.
     *
     * @param  string|null  $name
     * @return \Illuminate\Contracts\Auth\PasswordBroker
     */
    public function broker($name = null);
}
<?php

namespace Illuminate\Contracts\Auth;

interface Authenticatable
{
    /**
     * Get the name of the unique identifier for the user.
     *
     * @return string
     */
    public function getAuthIdentifierName();

    /**
     * Get the unique identifier for the user.
     *
     * @return mixed
     */
    public function getAuthIdentifier();

    /**
     * Get the name of the password attribute for the user.
     *
     * @return string
     */
    public function getAuthPasswordName();

    /**
     * Get the password for the user.
     *
     * @return string
     */
    public function getAuthPassword();

    /**
     * Get the token value for the "remember me" session.
     *
     * @return string
     */
    public function getRememberToken();

    /**
     * Set the token value for the "remember me" session.
     *
     * @param  string  $value
     * @return void
     */
    public function setRememberToken($value);

    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName();
}
<?php

namespace Illuminate\Contracts\Auth;

interface MustVerifyEmail
{
    /**
     * Determine if the user has verified their email address.
     *
     * @return bool
     */
    public function hasVerifiedEmail();

    /**
     * Mark the given user's email as verified.
     *
     * @return bool
     */
    public function markEmailAsVerified();

    /**
     * Mark the given user's email as unverified.
     *
     * @return bool
     */
    public function markEmailAsUnverified();

    /**
     * Send the email verification notification.
     *
     * @return void
     */
    public function sendEmailVerificationNotification();

    /**
     * Get the email address that should be used for verification.
     *
     * @return string
     */
    public function getEmailForVerification();
}
<?php

namespace Illuminate\Contracts\Auth;

interface CanResetPassword
{
    /**
     * Get the e-mail address where password reset links are sent.
     *
     * @return string
     */
    public function getEmailForPasswordReset();

    /**
     * Send the password reset notification.
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token);
}
<?php

namespace Illuminate\Contracts\Auth;

interface Guard
{
    /**
     * Determine if the current user is authenticated.
     *
     * @return bool
     */
    public function check();

    /**
     * Determine if the current user is a guest.
     *
     * @return bool
     */
    public function guest();

    /**
     * Get the currently authenticated user.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user();

    /**
     * Get the ID for the currently authenticated user.
     *
     * @return int|string|null
     */
    public function id();

    /**
     * Validate a user's credentials.
     *
     * @param  array  $credentials
     * @return bool
     */
    public function validate(array $credentials = []);

    /**
     * Determine if the guard has a user instance.
     *
     * @return bool
     */
    public function hasUser();

    /**
     * Set the current user.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @return $this
     */
    public function setUser(Authenticatable $user);
}
<?php

namespace Illuminate\Contracts\Auth;

use Closure;

interface PasswordBroker
{
    /**
     * Constant representing a successfully sent reminder.
     *
     * @var string
     */
    const RESET_LINK_SENT = 'passwords.sent';

    /**
     * Constant representing a successfully reset password.
     *
     * @var string
     */
    const PASSWORD_RESET = 'passwords.reset';

    /**
     * Constant representing the user not found response.
     *
     * @var string
     */
    const INVALID_USER = 'passwords.user';

    /**
     * Constant representing an invalid token.
     *
     * @var string
     */
    const INVALID_TOKEN = 'passwords.token';

    /**
     * Constant representing a throttled reset attempt.
     *
     * @var string
     */
    const RESET_THROTTLED = 'passwords.throttled';

    /**
     * Send a password reset link to a user.
     *
     * @param  array  $credentials
     * @param  \Closure|null  $callback
     * @return string
     */
    public function sendResetLink(array $credentials, ?Closure $callback = null);

    /**
     * Reset the password for the given token.
     *
     * @param  array  $credentials
     * @param  \Closure  $callback
     * @return mixed
     */
    public function reset(array $credentials, Closure $callback);
}
<?php

namespace Illuminate\Contracts\Auth;

interface SupportsBasicAuth
{
    /**
     * Attempt to authenticate using HTTP Basic Auth.
     *
     * @param  string  $field
     * @param  array  $extraConditions
     * @return \Symfony\Component\HttpFoundation\Response|null
     */
    public function basic($field = 'email', $extraConditions = []);

    /**
     * Perform a stateless HTTP Basic login attempt.
     *
     * @param  string  $field
     * @param  array  $extraConditions
     * @return \Symfony\Component\HttpFoundation\Response|null
     */
    public function onceBasic($field = 'email', $extraConditions = []);
}
<?php

namespace Illuminate\Contracts\Pagination;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @method $this through(callable(TValue): mixed $callback)
 */
interface Paginator
{
    /**
     * Get the URL for a given page.
     *
     * @param  int  $page
     * @return string
     */
    public function url($page);

    /**
     * Add a set of query string values to the paginator.
     *
     * @param  array|string|null  $key
     * @param  string|null  $value
     * @return $this
     */
    public function appends($key, $value = null);

    /**
     * Get / set the URL fragment to be appended to URLs.
     *
     * @param  string|null  $fragment
     * @return $this|string|null
     */
    public function fragment($fragment = null);

    /**
     * Add all current query string values to the paginator.
     *
     * @return $this
     */
    public function withQueryString();

    /**
     * The URL for the next page, or null.
     *
     * @return string|null
     */
    public function nextPageUrl();

    /**
     * Get the URL for the previous page, or null.
     *
     * @return string|null
     */
    public function previousPageUrl();

    /**
     * Get all of the items being paginated.
     *
     * @return array<TKey, TValue>
     */
    public function items();

    /**
     * Get the "index" of the first item being paginated.
     *
     * @return int|null
     */
    public function firstItem();

    /**
     * Get the "index" of the last item being paginated.
     *
     * @return int|null
     */
    public function lastItem();

    /**
     * Determine how many items are being shown per page.
     *
     * @return int
     */
    public function perPage();

    /**
     * Determine the current page being paginated.
     *
     * @return int
     */
    public function currentPage();

    /**
     * Determine if there are enough items to split into multiple pages.
     *
     * @return bool
     */
    public function hasPages();

    /**
     * Determine if there are more items in the data store.
     *
     * @return bool
     */
    public function hasMorePages();

    /**
     * Get the base path for paginator generated URLs.
     *
     * @return string|null
     */
    public function path();

    /**
     * Determine if the list of items is empty or not.
     *
     * @return bool
     */
    public function isEmpty();

    /**
     * Determine if the list of items is not empty.
     *
     * @return bool
     */
    public function isNotEmpty();

    /**
     * Render the paginator using a given view.
     *
     * @param  string|null  $view
     * @param  array  $data
     * @return string
     */
    public function render($view = null, $data = []);
}
<?php

namespace Illuminate\Contracts\Pagination;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @extends Paginator<TKey, TValue>
 */
interface LengthAwarePaginator extends Paginator
{
    /**
     * Create a range of pagination URLs.
     *
     * @param  int  $start
     * @param  int  $end
     * @return array
     */
    public function getUrlRange($start, $end);

    /**
     * Determine the total number of items in the data store.
     *
     * @return int
     */
    public function total();

    /**
     * Get the page number of the last available page.
     *
     * @return int
     */
    public function lastPage();
}
<?php

namespace Illuminate\Contracts\Pagination;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @method $this through(callable(TValue): mixed $callback)
 */
interface CursorPaginator
{
    /**
     * Get the URL for a given cursor.
     *
     * @param  \Illuminate\Pagination\Cursor|null  $cursor
     * @return string
     */
    public function url($cursor);

    /**
     * Add a set of query string values to the paginator.
     *
     * @param  array|string|null  $key
     * @param  string|null  $value
     * @return $this
     */
    public function appends($key, $value = null);

    /**
     * Get / set the URL fragment to be appended to URLs.
     *
     * @param  string|null  $fragment
     * @return $this|string|null
     */
    public function fragment($fragment = null);

    /**
     * Add all current query string values to the paginator.
     *
     * @return $this
     */
    public function withQueryString();

    /**
     * Get the URL for the previous page, or null.
     *
     * @return string|null
     */
    public function previousPageUrl();

    /**
     * The URL for the next page, or null.
     *
     * @return string|null
     */
    public function nextPageUrl();

    /**
     * Get all of the items being paginated.
     *
     * @return array<TKey, TValue>
     */
    public function items();

    /**
     * Get the "cursor" of the previous set of items.
     *
     * @return \Illuminate\Pagination\Cursor|null
     */
    public function previousCursor();

    /**
     * Get the "cursor" of the next set of items.
     *
     * @return \Illuminate\Pagination\Cursor|null
     */
    public function nextCursor();

    /**
     * Determine how many items are being shown per page.
     *
     * @return int
     */
    public function perPage();

    /**
     * Get the current cursor being paginated.
     *
     * @return \Illuminate\Pagination\Cursor|null
     */
    public function cursor();

    /**
     * Determine if there are enough items to split into multiple pages.
     *
     * @return bool
     */
    public function hasPages();

    /**
     * Determine if there are more items in the data source.
     *
     * @return bool
     */
    public function hasMorePages();

    /**
     * Get the base path for paginator generated URLs.
     *
     * @return string|null
     */
    public function path();

    /**
     * Determine if the list of items is empty or not.
     *
     * @return bool
     */
    public function isEmpty();

    /**
     * Determine if the list of items is not empty.
     *
     * @return bool
     */
    public function isNotEmpty();

    /**
     * Render the paginator using a given view.
     *
     * @param  string|null  $view
     * @param  array  $data
     * @return string
     */
    public function render($view = null, $data = []);
}
<?php

namespace Illuminate\Contracts\Routing;

interface BindingRegistrar
{
    /**
     * Add a new route parameter binder.
     *
     * @param  string  $key
     * @param  string|callable  $binder
     * @return void
     */
    public function bind($key, $binder);

    /**
     * Get the binding callback for a given binding.
     *
     * @param  string  $key
     * @return \Closure
     */
    public function getBindingCallback($key);
}
<?php

namespace Illuminate\Contracts\Routing;

interface UrlRoutable
{
    /**
     * Get the value of the model's route key.
     *
     * @return mixed
     */
    public function getRouteKey();

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName();

    /**
     * Retrieve the model for a bound value.
     *
     * @param  mixed  $value
     * @param  string|null  $field
     * @return \Illuminate\Database\Eloquent\Model|null
     */
    public function resolveRouteBinding($value, $field = null);

    /**
     * Retrieve the child model for a bound value.
     *
     * @param  string  $childType
     * @param  mixed  $value
     * @param  string|null  $field
     * @return \Illuminate\Database\Eloquent\Model|null
     */
    public function resolveChildRouteBinding($childType, $value, $field);
}
<?php

namespace Illuminate\Contracts\Routing;

interface Registrar
{
    /**
     * Register a new GET route with the router.
     *
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function get($uri, $action);

    /**
     * Register a new POST route with the router.
     *
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function post($uri, $action);

    /**
     * Register a new PUT route with the router.
     *
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function put($uri, $action);

    /**
     * Register a new DELETE route with the router.
     *
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function delete($uri, $action);

    /**
     * Register a new PATCH route with the router.
     *
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function patch($uri, $action);

    /**
     * Register a new OPTIONS route with the router.
     *
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function options($uri, $action);

    /**
     * Register a new route with the given verbs.
     *
     * @param  array|string  $methods
     * @param  string  $uri
     * @param  array|string|callable  $action
     * @return \Illuminate\Routing\Route
     */
    public function match($methods, $uri, $action);

    /**
     * Route a resource to a controller.
     *
     * @param  string  $name
     * @param  string  $controller
     * @param  array  $options
     * @return \Illuminate\Routing\PendingResourceRegistration
     */
    public function resource($name, $controller, array $options = []);

    /**
     * Create a route group with shared attributes.
     *
     * @param  array  $attributes
     * @param  \Closure|string  $routes
     * @return void
     */
    public function group(array $attributes, $routes);

    /**
     * Substitute the route bindings onto the route.
     *
     * @param  \Illuminate\Routing\Route  $route
     * @return \Illuminate\Routing\Route
     */
    public function substituteBindings($route);

    /**
     * Substitute the implicit Eloquent model bindings for the route.
     *
     * @param  \Illuminate\Routing\Route  $route
     * @return void
     */
    public function substituteImplicitBindings($route);
}
<?php

namespace Illuminate\Contracts\Routing;

interface UrlGenerator
{
    /**
     * Get the current URL for the request.
     *
     * @return string
     */
    public function current();

    /**
     * Get the URL for the previous request.
     *
     * @param  mixed  $fallback
     * @return string
     */
    public function previous($fallback = false);

    /**
     * Generate an absolute URL to the given path.
     *
     * @param  string  $path
     * @param  mixed  $extra
     * @param  bool|null  $secure
     * @return string
     */
    public function to($path, $extra = [], $secure = null);

    /**
     * Generate a secure, absolute URL to the given path.
     *
     * @param  string  $path
     * @param  array  $parameters
     * @return string
     */
    public function secure($path, $parameters = []);

    /**
     * Generate the URL to an application asset.
     *
     * @param  string  $path
     * @param  bool|null  $secure
     * @return string
     */
    public function asset($path, $secure = null);

    /**
     * Get the URL to a named route.
     *
     * @param  string  $name
     * @param  mixed  $parameters
     * @param  bool  $absolute
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    public function route($name, $parameters = [], $absolute = true);

    /**
     * Create a signed route URL for a named route.
     *
     * @param  string  $name
     * @param  mixed  $parameters
     * @param  \DateTimeInterface|\DateInterval|int|null  $expiration
     * @param  bool  $absolute
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    public function signedRoute($name, $parameters = [], $expiration = null, $absolute = true);

    /**
     * Create a temporary signed route URL for a named route.
     *
     * @param  string  $name
     * @param  \DateTimeInterface|\DateInterval|int  $expiration
     * @param  array  $parameters
     * @param  bool  $absolute
     * @return string
     */
    public function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true);

    /**
     * Generate an absolute URL with the given query parameters.
     *
     * @param  string  $path
     * @param  array  $query
     * @param  mixed  $extra
     * @param  bool|null  $secure
     * @return string
     */
    public function query($path, $query = [], $extra = [], $secure = null);

    /**
     * Get the URL to a controller action.
     *
     * @param  string|array  $action
     * @param  mixed  $parameters
     * @param  bool  $absolute
     * @return string
     */
    public function action($action, $parameters = [], $absolute = true);

    /**
     * Get the root controller namespace.
     *
     * @return string
     */
    public function getRootControllerNamespace();

    /**
     * Set the root controller namespace.
     *
     * @param  string  $rootNamespace
     * @return $this
     */
    public function setRootControllerNamespace($rootNamespace);
}
<?php

namespace Illuminate\Contracts\Routing;

use Closure;
use Illuminate\Http\StreamedEvent;

interface ResponseFactory
{
    /**
     * Create a new response instance.
     *
     * @param  array|string  $content
     * @param  int  $status
     * @param  array  $headers
     * @return \Illuminate\Http\Response
     */
    public function make($content = '', $status = 200, array $headers = []);

    /**
     * Create a new "no content" response.
     *
     * @param  int  $status
     * @param  array  $headers
     * @return \Illuminate\Http\Response
     */
    public function noContent($status = 204, array $headers = []);

    /**
     * Create a new response for a given view.
     *
     * @param  string|array  $view
     * @param  array  $data
     * @param  int  $status
     * @param  array  $headers
     * @return \Illuminate\Http\Response
     */
    public function view($view, $data = [], $status = 200, array $headers = []);

    /**
     * Create a new JSON response instance.
     *
     * @param  mixed  $data
     * @param  int  $status
     * @param  array  $headers
     * @param  int  $options
     * @return \Illuminate\Http\JsonResponse
     */
    public function json($data = [], $status = 200, array $headers = [], $options = 0);

    /**
     * Create a new JSONP response instance.
     *
     * @param  string  $callback
     * @param  mixed  $data
     * @param  int  $status
     * @param  array  $headers
     * @param  int  $options
     * @return \Illuminate\Http\JsonResponse
     */
    public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0);

    /**
     * Create a new event stream response.
     *
     * @param  \Closure  $callback
     * @param  array  $headers
     * @param  \Illuminate\Http\StreamedEvent|string|null  $endStreamWith
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     */
    public function eventStream(Closure $callback, array $headers = [], StreamedEvent|string|null $endStreamWith = '</stream>');

    /**
     * Create a new streamed response instance.
     *
     * @param  callable  $callback
     * @param  int  $status
     * @param  array  $headers
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     */
    public function stream($callback, $status = 200, array $headers = []);

    /**
     * Create a new streamed JSON response instance.
     *
     * @param  array  $data
     * @param  int  $status
     * @param  array  $headers
     * @param  int  $encodingOptions
     * @return \Symfony\Component\HttpFoundation\StreamedJsonResponse
     */
    public function streamJson($data, $status = 200, $headers = [], $encodingOptions = 15);

    /**
     * Create a new streamed response instance as a file download.
     *
     * @param  callable  $callback
     * @param  string|null  $name
     * @param  array  $headers
     * @param  string|null  $disposition
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     */
    public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment');

    /**
     * Create a new file download response.
     *
     * @param  \SplFileInfo|string  $file
     * @param  string|null  $name
     * @param  array  $headers
     * @param  string|null  $disposition
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function download($file, $name = null, array $headers = [], $disposition = 'attachment');

    /**
     * Return the raw contents of a binary file.
     *
     * @param  \SplFileInfo|string  $file
     * @param  array  $headers
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function file($file, array $headers = []);

    /**
     * Create a new redirect response to the given path.
     *
     * @param  string  $path
     * @param  int  $status
     * @param  array  $headers
     * @param  bool|null  $secure
     * @return \Illuminate\Http\RedirectResponse
     */
    public function redirectTo($path, $status = 302, $headers = [], $secure = null);

    /**
     * Create a new redirect response to a named route.
     *
     * @param  \BackedEnum|string  $route
     * @param  mixed  $parameters
     * @param  int  $status
     * @param  array  $headers
     * @return \Illuminate\Http\RedirectResponse
     */
    public function redirectToRoute($route, $parameters = [], $status = 302, $headers = []);

    /**
     * Create a new redirect response to a controller action.
     *
     * @param  array|string  $action
     * @param  mixed  $parameters
     * @param  int  $status
     * @param  array  $headers
     * @return \Illuminate\Http\RedirectResponse
     */
    public function redirectToAction($action, $parameters = [], $status = 302, $headers = []);

    /**
     * Create a new redirect response, while putting the current URL in the session.
     *
     * @param  string  $path
     * @param  int  $status
     * @param  array  $headers
     * @param  bool|null  $secure
     * @return \Illuminate\Http\RedirectResponse
     */
    public function redirectGuest($path, $status = 302, $headers = [], $secure = null);

    /**
     * Create a new redirect response to the previously intended location.
     *
     * @param  string  $default
     * @param  int  $status
     * @param  array  $headers
     * @param  bool|null  $secure
     * @return \Illuminate\Http\RedirectResponse
     */
    public function redirectToIntended($default = '/', $status = 302, $headers = [], $secure = null);
}
<?php

namespace Illuminate\Contracts\Http;

interface Kernel
{
    /**
     * Bootstrap the application for HTTP requests.
     *
     * @return void
     */
    public function bootstrap();

    /**
     * Handle an incoming HTTP request.
     *
     * @param  \Symfony\Component\HttpFoundation\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handle($request);

    /**
     * Perform any final actions for the request lifecycle.
     *
     * @param  \Symfony\Component\HttpFoundation\Request  $request
     * @param  \Symfony\Component\HttpFoundation\Response  $response
     * @return void
     */
    public function terminate($request, $response);

    /**
     * Get the Laravel application instance.
     *
     * @return \Illuminate\Contracts\Foundation\Application
     */
    public function getApplication();
}
<?php

namespace Illuminate\Contracts\Validation;

interface Factory
{
    /**
     * Create a new Validator instance.
     *
     * @param  array  $data
     * @param  array  $rules
     * @param  array  $messages
     * @param  array  $attributes
     * @return \Illuminate\Contracts\Validation\Validator
     */
    public function make(array $data, array $rules, array $messages = [], array $attributes = []);

    /**
     * Register a custom validator extension.
     *
     * @param  string  $rule
     * @param  \Closure|string  $extension
     * @param  string|null  $message
     * @return void
     */
    public function extend($rule, $extension, $message = null);

    /**
     * Register a custom implicit validator extension.
     *
     * @param  string  $rule
     * @param  \Closure|string  $extension
     * @param  string|null  $message
     * @return void
     */
    public function extendImplicit($rule, $extension, $message = null);

    /**
     * Register a custom implicit validator message replacer.
     *
     * @param  string  $rule
     * @param  \Closure|string  $replacer
     * @return void
     */
    public function replacer($rule, $replacer);
}
<?php

namespace Illuminate\Contracts\Validation;

use Illuminate\Contracts\Support\MessageProvider;

interface Validator extends MessageProvider
{
    /**
     * Run the validator's rules against its data.
     *
     * @return array
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function validate();

    /**
     * Get the attributes and values that were validated.
     *
     * @return array
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function validated();

    /**
     * Determine if the data fails the validation rules.
     *
     * @return bool
     */
    public function fails();

    /**
     * Get the failed validation rules.
     *
     * @return array
     */
    public function failed();

    /**
     * Add conditions to a given field based on a Closure.
     *
     * @param  string|array  $attribute
     * @param  string|array  $rules
     * @param  callable  $callback
     * @return $this
     */
    public function sometimes($attribute, $rules, callable $callback);

    /**
     * Add an after validation callback.
     *
     * @param  callable|string  $callback
     * @return $this
     */
    public function after($callback);

    /**
     * Get all of the validation error messages.
     *
     * @return \Illuminate\Support\MessageBag
     */
    public function errors();
}
<?php

namespace Illuminate\Contracts\Validation;

interface UncompromisedVerifier
{
    /**
     * Verify that the given data has not been compromised in data leaks.
     *
     * @param  array  $data
     * @return bool
     */
    public function verify($data);
}
<?php

namespace Illuminate\Contracts\Validation;

interface CompilableRules
{
    /**
     * Compile the object into usable rules.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  mixed  $data
     * @param  mixed  $context
     * @return \stdClass
     */
    public function compile($attribute, $value, $data = null, $context = null);
}
<?php

namespace Illuminate\Contracts\Validation;

use Illuminate\Validation\Validator;

interface ValidatorAwareRule
{
    /**
     * Set the current validator.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return $this
     */
    public function setValidator(Validator $validator);
}
<?php

namespace Illuminate\Contracts\Validation;

/**
 * @deprecated see ValidationRule
 */
interface Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value);

    /**
     * Get the validation error message.
     *
     * @return string|array
     */
    public function message();
}
<?php

namespace Illuminate\Contracts\Validation;

/**
 * @deprecated see ValidationRule
 */
interface ImplicitRule extends Rule
{
    //
}
<?php

namespace Illuminate\Contracts\Validation;

use Closure;

interface ValidationRule
{
    /**
     * Run the validation rule.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     * @return void
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void;
}
<?php

namespace Illuminate\Contracts\Validation;

interface DataAwareRule
{
    /**
     * Set the data under validation.
     *
     * @param  array  $data
     * @return $this
     */
    public function setData(array $data);
}
<?php

namespace Illuminate\Contracts\Validation;

use Closure;

/**
 * @deprecated see ValidationRule
 */
interface InvokableRule
{
    /**
     * Run the validation rule.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     * @return void
     */
    public function __invoke(string $attribute, mixed $value, Closure $fail);
}
<?php

namespace Illuminate\Contracts\Validation;

interface ValidatesWhenResolved
{
    /**
     * Validate the given class instance.
     *
     * @return void
     */
    public function validateResolved();
}
<?php

namespace Illuminate\Contracts\Encryption;

use RuntimeException;

class EncryptException extends RuntimeException
{
    //
}
<?php

namespace Illuminate\Contracts\Encryption;

interface StringEncrypter
{
    /**
     * Encrypt a string without serialization.
     *
     * @param  string  $value
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\EncryptException
     */
    public function encryptString(#[\SensitiveParameter] $value);

    /**
     * Decrypt the given string without unserialization.
     *
     * @param  string  $payload
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\DecryptException
     */
    public function decryptString($payload);
}
<?php

namespace Illuminate\Contracts\Encryption;

interface Encrypter
{
    /**
     * Encrypt the given value.
     *
     * @param  mixed  $value
     * @param  bool  $serialize
     * @return string
     *
     * @throws \Illuminate\Contracts\Encryption\EncryptException
     */
    public function encrypt(#[\SensitiveParameter] $value, $serialize = true);

    /**
     * Decrypt the given value.
     *
     * @param  string  $payload
     * @param  bool  $unserialize
     * @return mixed
     *
     * @throws \Illuminate\Contracts\Encryption\DecryptException
     */
    public function decrypt($payload, $unserialize = true);

    /**
     * Get the encryption key that the encrypter is currently using.
     *
     * @return string
     */
    public function getKey();

    /**
     * Get the current encryption key and all previous encryption keys.
     *
     * @return array
     */
    public function getAllKeys();

    /**
     * Get the previous encryption keys.
     *
     * @return array
     */
    public function getPreviousKeys();
}
<?php

namespace Illuminate\Contracts\Encryption;

use RuntimeException;

class DecryptException extends RuntimeException
{
    //
}
<?php

namespace Illuminate\Contracts\Support;

interface DeferrableProvider
{
    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides();
}
<?php

namespace Illuminate\Contracts\Support;

/**
 * @template TKey of array-key
 * @template TValue
 */
interface Arrayable
{
    /**
     * Get the instance as an array.
     *
     * @return array<TKey, TValue>
     */
    public function toArray();
}
<?php

namespace Illuminate\Contracts\Support;

interface DeferringDisplayableValue
{
    /**
     * Resolve the displayable value that the class is deferring.
     *
     * @return \Illuminate\Contracts\Support\Htmlable|string
     */
    public function resolveDisplayableValue();
}
<?php

namespace Illuminate\Contracts\Support;

use Countable;

interface MessageBag extends Arrayable, Countable
{
    /**
     * Get the keys present in the message bag.
     *
     * @return array
     */
    public function keys();

    /**
     * Add a message to the bag.
     *
     * @param  string  $key
     * @param  string  $message
     * @return $this
     */
    public function add($key, $message);

    /**
     * Merge a new array of messages into the bag.
     *
     * @param  \Illuminate\Contracts\Support\MessageProvider|array  $messages
     * @return $this
     */
    public function merge($messages);

    /**
     * Determine if messages exist for a given key.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function has($key);

    /**
     * Get the first message from the bag for a given key.
     *
     * @param  string|null  $key
     * @param  string|null  $format
     * @return string
     */
    public function first($key = null, $format = null);

    /**
     * Get all of the messages from the bag for a given key.
     *
     * @param  string  $key
     * @param  string|null  $format
     * @return array
     */
    public function get($key, $format = null);

    /**
     * Get all of the messages for every key in the bag.
     *
     * @param  string|null  $format
     * @return array
     */
    public function all($format = null);

    /**
     * Remove a message from the bag.
     *
     * @param  string  $key
     * @return $this
     */
    public function forget($key);

    /**
     * Get the raw messages in the container.
     *
     * @return array
     */
    public function getMessages();

    /**
     * Get the default message format.
     *
     * @return string
     */
    public function getFormat();

    /**
     * Set the default message format.
     *
     * @param  string  $format
     * @return $this
     */
    public function setFormat($format = ':message');

    /**
     * Determine if the message bag has any messages.
     *
     * @return bool
     */
    public function isEmpty();

    /**
     * Determine if the message bag has any messages.
     *
     * @return bool
     */
    public function isNotEmpty();
}
<?php

namespace Illuminate\Contracts\Support;

interface Htmlable
{
    /**
     * Get content as a string of HTML.
     *
     * @return string
     */
    public function toHtml();
}
<?php

namespace Illuminate\Contracts\Support;

interface CanBeEscapedWhenCastToString
{
    /**
     * Indicate that the object's string representation should be escaped when __toString is invoked.
     *
     * @param  bool  $escape
     * @return $this
     */
    public function escapeWhenCastingToString($escape = true);
}
<?php

namespace Illuminate\Contracts\Support;

use ArrayAccess;
use IteratorAggregate;

interface ValidatedData extends Arrayable, ArrayAccess, IteratorAggregate
{
    //
}
<?php

namespace Illuminate\Contracts\Support;

interface Renderable
{
    /**
     * Get the evaluated contents of the object.
     *
     * @return string
     */
    public function render();
}
<?php

namespace Illuminate\Contracts\Support;

interface Responsable
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request);
}
<?php

namespace Illuminate\Contracts\Support;

interface Jsonable
{
    /**
     * Convert the object to its JSON representation.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0);
}
<?php

namespace Illuminate\Contracts\Support;

interface MessageProvider
{
    /**
     * Get the messages for the instance.
     *
     * @return \Illuminate\Contracts\Support\MessageBag
     */
    public function getMessageBag();
}
<?php

namespace Illuminate\Contracts\Support;

interface HasOnceHash
{
    /**
     * Compute the hash that should be used to represent the object when given to a function using "once".
     *
     * @return string
     */
    public function onceHash();
}
<?php

namespace Illuminate\Contracts\Database;

use Illuminate\Database\Eloquent\Relations\Relation;

class ModelIdentifier
{
    /**
     * Use the Relation morphMap for a Model's name when serializing.
     */
    protected static bool $useMorphMap = false;

    /**
     * The class name of the model.
     *
     * @var class-string<\Illuminate\Database\Eloquent\Model>|string|null
     */
    public $class;

    /**
     * The unique identifier of the model.
     *
     * This may be either a single ID or an array of IDs.
     *
     * @var mixed
     */
    public $id;

    /**
     * The relationships loaded on the model.
     *
     * @var array
     */
    public $relations;

    /**
     * The connection name of the model.
     *
     * @var string|null
     */
    public $connection;

    /**
     * The class name of the model collection.
     *
     * @var class-string<\Illuminate\Database\Eloquent\Collection>|null
     */
    public $collectionClass;

    /**
     * Create a new model identifier.
     *
     * @param  class-string<\Illuminate\Database\Eloquent\Model>|null  $class
     * @param  mixed  $id
     * @param  array  $relations
     * @param  mixed  $connection
     */
    public function __construct($class, $id, array $relations, $connection)
    {
        if ($class !== null && self::$useMorphMap) {
            $class = Relation::getMorphAlias($class);
        }

        $this->class = $class;
        $this->id = $id;
        $this->relations = $relations;
        $this->connection = $connection;
    }

    /**
     * Specify the collection class that should be used when serializing / restoring collections.
     *
     * @param  class-string<\Illuminate\Database\Eloquent\Collection>  $collectionClass
     * @return $this
     */
    public function useCollectionClass(?string $collectionClass)
    {
        $this->collectionClass = $collectionClass;

        return $this;
    }

    /**
     * Get the fully-qualified class name of the Model.
     *
     * @return class-string<\Illuminate\Database\Eloquent\Model>|null
     */
    public function getClass(): ?string
    {
        if (self::$useMorphMap && $this->class !== null) {
            return Relation::getMorphedModel($this->class) ?? $this->class;
        }

        return $this->class;
    }

    /**
     * Indicate whether to use the relational morph-map when serializing Models.
     */
    public static function useMorphMap(bool $useMorphMap = true): void
    {
        static::$useMorphMap = $useMorphMap;
    }
}
<?php

namespace Illuminate\Contracts\Database;

use Throwable;

interface LostConnectionDetector
{
    /**
     * Determine if the given exception was caused by a lost connection.
     *
     * @param  \Throwable  $e
     * @return bool
     */
    public function causedByLostConnection(Throwable $e): bool;
}
<?php

namespace Illuminate\Contracts\Database;

use Throwable;

interface ConcurrencyErrorDetector
{
    /**
     * Determine if the given exception was caused by a concurrency error such as a deadlock or serialization failure.
     *
     * @param  \Throwable  $e
     * @return bool
     */
    public function causedByConcurrencyError(Throwable $e): bool;
}
<?php

namespace Illuminate\Contracts\Database\Query;

interface ConditionExpression extends Expression
{
}
<?php

namespace Illuminate\Contracts\Database\Query;

/**
 * This interface is intentionally empty and exists to improve IDE support.
 *
 * @mixin \Illuminate\Database\Query\Builder
 */
interface Builder
{
}
<?php

namespace Illuminate\Contracts\Database\Query;

use Illuminate\Database\Grammar;

interface Expression
{
    /**
     * Get the value of the expression.
     *
     * @param  \Illuminate\Database\Grammar  $grammar
     * @return string|int|float
     */
    public function getValue(Grammar $grammar);
}
<?php

namespace Illuminate\Contracts\Database\Events;

interface MigrationEvent
{
    //
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

interface DeviatesCastableAttributes
{
    /**
     * Increment the attribute.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return mixed
     */
    public function increment($model, string $key, $value, array $attributes);

    /**
     * Decrement the attribute.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return mixed
     */
    public function decrement($model, string $key, $value, array $attributes);
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

use Illuminate\Database\Eloquent\Model;

/**
 * @template TGet
 * @template TSet
 */
interface CastsAttributes
{
    /**
     * Transform the attribute from the underlying model values.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array<string, mixed>  $attributes
     * @return TGet|null
     */
    public function get(Model $model, string $key, mixed $value, array $attributes);

    /**
     * Transform the attribute to its underlying model values.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  TSet|null  $value
     * @param  array<string, mixed>  $attributes
     * @return mixed
     */
    public function set(Model $model, string $key, mixed $value, array $attributes);
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

interface Castable
{
    /**
     * Get the name of the caster class to use when casting from / to this cast target.
     *
     * @param  string[]  $arguments
     * @return class-string<CastsAttributes|CastsInboundAttributes>|CastsAttributes|CastsInboundAttributes
     */
    public static function castUsing(array $arguments);
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

use Illuminate\Database\Eloquent\Model;

interface SerializesCastableAttributes
{
    /**
     * Serialize the attribute when converting the model to an array.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array<string, mixed>  $attributes
     * @return mixed
     */
    public function serialize(Model $model, string $key, mixed $value, array $attributes);
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

interface SupportsPartialRelations
{
    /**
     * Indicate that the relation is a single result of a larger one-to-many relationship.
     *
     * @param  string|null  $column
     * @param  string|\Closure|null  $aggregate
     * @param  string|null  $relation
     * @return $this
     */
    public function ofMany($column = 'id', $aggregate = 'MAX', $relation = null);

    /**
     * Determine whether the relationship is a one-of-many relationship.
     *
     * @return bool
     */
    public function isOneOfMany();

    /**
     * Get the one of many inner join subselect query builder instance.
     *
     * @return \Illuminate\Database\Eloquent\Builder|void
     */
    public function getOneOfManySubQuery();
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

use Illuminate\Database\Eloquent\Model;

interface ComparesCastableAttributes
{
    /**
     * Determine if the given values are equal.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $firstValue
     * @param  mixed  $secondValue
     * @return bool
     */
    public function compare(Model $model, string $key, mixed $firstValue, mixed $secondValue);
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

use Illuminate\Contracts\Database\Query\Builder as BaseContract;

/**
 * This interface is intentionally empty and exists to improve IDE support.
 *
 * @mixin \Illuminate\Database\Eloquent\Builder
 */
interface Builder extends BaseContract
{
}
<?php

namespace Illuminate\Contracts\Database\Eloquent;

use Illuminate\Database\Eloquent\Model;

interface CastsInboundAttributes
{
    /**
     * Transform the attribute to its underlying model values.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array<string, mixed>  $attributes
     * @return mixed
     */
    public function set(Model $model, string $key, mixed $value, array $attributes);
}
<?php

namespace Illuminate\Contracts\Process;

interface InvokedProcess
{
    /**
     * Get the process ID if the process is still running.
     *
     * @return int|null
     */
    public function id();

    /**
     * Get the command line for the process.
     *
     * @return string
     */
    public function command();

    /**
     * Send a signal to the process.
     *
     * @param  int  $signal
     * @return $this
     */
    public function signal(int $signal);

    /**
     * Determine if the process is still running.
     *
     * @return bool
     */
    public function running();

    /**
     * Get the standard output for the process.
     *
     * @return string
     */
    public function output();

    /**
     * Get the error output for the process.
     *
     * @return string
     */
    public function errorOutput();

    /**
     * Get the latest standard output for the process.
     *
     * @return string
     */
    public function latestOutput();

    /**
     * Get the latest error output for the process.
     *
     * @return string
     */
    public function latestErrorOutput();

    /**
     * Wait for the process to finish.
     *
     * @param  callable|null  $output
     * @return \Illuminate\Process\ProcessResult
     */
    public function wait(?callable $output = null);

    /**
     * Wait until the given callback returns true.
     *
     * @param  callable|null  $output
     * @return \Illuminate\Process\ProcessResult
     */
    public function waitUntil(?callable $output = null);
}
<?php

namespace Illuminate\Contracts\Process;

interface ProcessResult
{
    /**
     * Get the original command executed by the process.
     *
     * @return string
     */
    public function command();

    /**
     * Determine if the process was successful.
     *
     * @return bool
     */
    public function successful();

    /**
     * Determine if the process failed.
     *
     * @return bool
     */
    public function failed();

    /**
     * Get the exit code of the process.
     *
     * @return int|null
     */
    public function exitCode();

    /**
     * Get the standard output of the process.
     *
     * @return string
     */
    public function output();

    /**
     * Determine if the output contains the given string.
     *
     * @param  string  $output
     * @return bool
     */
    public function seeInOutput(string $output);

    /**
     * Get the error output of the process.
     *
     * @return string
     */
    public function errorOutput();

    /**
     * Determine if the error output contains the given string.
     *
     * @param  string  $output
     * @return bool
     */
    public function seeInErrorOutput(string $output);

    /**
     * Throw an exception if the process failed.
     *
     * @param  callable|null  $callback
     * @return $this
     */
    public function throw(?callable $callback = null);

    /**
     * Throw an exception if the process failed and the given condition is true.
     *
     * @param  bool  $condition
     * @param  callable|null  $callback
     * @return $this
     */
    public function throwIf(bool $condition, ?callable $callback = null);
}
<?php

namespace Illuminate\Contracts\Events;

interface Dispatcher
{
    /**
     * Register an event listener with the dispatcher.
     *
     * @param  \Closure|string|array  $events
     * @param  \Closure|string|array|null  $listener
     * @return void
     */
    public function listen($events, $listener = null);

    /**
     * Determine if a given event has listeners.
     *
     * @param  string  $eventName
     * @return bool
     */
    public function hasListeners($eventName);

    /**
     * Register an event subscriber with the dispatcher.
     *
     * @param  object|string  $subscriber
     * @return void
     */
    public function subscribe($subscriber);

    /**
     * Dispatch an event until the first non-null response is returned.
     *
     * @param  string|object  $event
     * @param  mixed  $payload
     * @return mixed
     */
    public function until($event, $payload = []);

    /**
     * Dispatch an event and call the listeners.
     *
     * @param  string|object  $event
     * @param  mixed  $payload
     * @param  bool  $halt
     * @return array|null
     */
    public function dispatch($event, $payload = [], $halt = false);

    /**
     * Register an event and payload to be fired later.
     *
     * @param  string  $event
     * @param  array  $payload
     * @return void
     */
    public function push($event, $payload = []);

    /**
     * Flush a set of pushed events.
     *
     * @param  string  $event
     * @return void
     */
    public function flush($event);

    /**
     * Remove a set of listeners from the dispatcher.
     *
     * @param  string  $event
     * @return void
     */
    public function forget($event);

    /**
     * Forget all of the queued listeners.
     *
     * @return void
     */
    public function forgetPushed();
}
<?php

namespace Illuminate\Contracts\Events;

interface ShouldHandleEventsAfterCommit
{
    //
}
<?php

namespace Illuminate\Contracts\Events;

interface ShouldDispatchAfterCommit
{
    //
}
<?php

namespace Illuminate\Contracts\Debug;

use Throwable;

/**
 * @method bool isReporting(\Throwable $e)
 * @method array buildContextForException()
 */
interface ExceptionHandler
{
    /**
     * Report or log an exception.
     *
     * @param  \Throwable  $e
     * @return void
     *
     * @throws \Throwable
     */
    public function report(Throwable $e);

    /**
     * Determine if the exception should be reported.
     *
     * @param  \Throwable  $e
     * @return bool
     */
    public function shouldReport(Throwable $e);

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $e
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $e);

    /**
     * Render an exception to the console.
     *
     * @param  \Symfony\Component\Console\Output\OutputInterface  $output
     * @param  \Throwable  $e
     * @return void
     *
     * @internal This method is not meant to be used or overwritten outside the framework.
     */
    public function renderForConsole($output, Throwable $e);
}
<?php

namespace Illuminate\Contracts\Debug;

interface ShouldntReport
{
    //
}
<?php

namespace Illuminate\Contracts\Pipeline;

use Closure;

interface Pipeline
{
    /**
     * Set the object being sent through the pipeline.
     *
     * @param  mixed  $passable
     * @return $this
     */
    public function send($passable);

    /**
     * Set the array of pipes.
     *
     * @param  mixed  $pipes
     * @return $this
     */
    public function through($pipes);

    /**
     * Set the method to call on the pipes.
     *
     * @param  string  $method
     * @return $this
     */
    public function via($method);

    /**
     * Run the pipeline with a final destination callback.
     *
     * @param  \Closure  $destination
     * @return mixed
     */
    public function then(Closure $destination);
}
<?php

namespace Illuminate\Contracts\Pipeline;

interface Hub
{
    /**
     * Send an object through one of the available pipelines.
     *
     * @param  mixed  $object
     * @param  string|null  $pipeline
     * @return mixed
     */
    public function pipe($object, $pipeline = null);
}
<?php

namespace Illuminate\Contracts\Redis;

interface Factory
{
    /**
     * Get a Redis connection by name.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Redis\Connections\Connection
     */
    public function connection($name = null);
}
<?php

namespace Illuminate\Contracts\Redis;

use Exception;

class LimiterTimeoutException extends Exception
{
    //
}
<?php

namespace Illuminate\Contracts\Redis;

use Closure;

interface Connection
{
    /**
     * Subscribe to a set of given channels for messages.
     *
     * @param  array|string  $channels
     * @param  \Closure  $callback
     * @return void
     */
    public function subscribe($channels, Closure $callback);

    /**
     * Subscribe to a set of given channels with wildcards.
     *
     * @param  array|string  $channels
     * @param  \Closure  $callback
     * @return void
     */
    public function psubscribe($channels, Closure $callback);

    /**
     * Run a command against the Redis database.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function command($method, array $parameters = []);
}
<?php

namespace Illuminate\Contracts\Redis;

interface Connector
{
    /**
     * Create a connection to a Redis cluster.
     *
     * @param  array  $config
     * @param  array  $options
     * @return \Illuminate\Redis\Connections\Connection
     */
    public function connect(array $config, array $options);

    /**
     * Create a connection to a Redis instance.
     *
     * @param  array  $config
     * @param  array  $clusterOptions
     * @param  array  $options
     * @return \Illuminate\Redis\Connections\Connection
     */
    public function connectToCluster(array $config, array $clusterOptions, array $options);
}
<?php

namespace Illuminate\Contracts\Queue;

use InvalidArgumentException;

class EntityNotFoundException extends InvalidArgumentException
{
    /**
     * Create a new exception instance.
     *
     * @param  string  $type
     * @param  mixed  $id
     */
    public function __construct($type, $id)
    {
        $id = (string) $id;

        parent::__construct("Queueable entity [{$type}] not found for ID [{$id}].");
    }
}
<?php

namespace Illuminate\Contracts\Queue;

interface Factory
{
    /**
     * Resolve a queue connection instance.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Queue\Queue
     */
    public function connection($name = null);
}
<?php

namespace Illuminate\Contracts\Queue;

interface ShouldBeUnique
{
    //
}
<?php

namespace Illuminate\Contracts\Queue;

interface PreparesForDispatch
{
    /**
     * Run preparation logic before dispatch. Return false to abort.
     *
     * @return bool|void
     */
    public function prepareForDispatch();
}
<?php

namespace Illuminate\Contracts\Queue;

interface Monitor
{
    /**
     * Register a callback to be executed when a daemon queue is starting.
     *
     * @param  mixed  $callback
     * @return void
     */
    public function starting($callback);

    /**
     * Register a callback to be executed on every iteration through the queue loop.
     *
     * @param  mixed  $callback
     * @return void
     */
    public function looping($callback);

    /**
     * Register a callback to be executed when a job fails after the maximum number of retries.
     *
     * @param  mixed  $callback
     * @return void
     */
    public function failing($callback);

    /**
     * Register a callback to be executed when a daemon queue is stopping.
     *
     * @param  mixed  $callback
     * @return void
     */
    public function stopping($callback);
}
<?php

namespace Illuminate\Contracts\Queue;

interface ClearableQueue
{
    /**
     * Delete all of the jobs from the queue.
     *
     * @param  string  $queue
     * @return int
     */
    public function clear($queue);
}
<?php

namespace Illuminate\Contracts\Queue;

interface Queue
{
    /**
     * Get the size of the queue.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function size($queue = null);

    /**
     * Get the number of pending jobs.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function pendingSize($queue = null);

    /**
     * Get the number of delayed jobs.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function delayedSize($queue = null);

    /**
     * Get the number of reserved jobs.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function reservedSize($queue = null);

    /**
     * Get the creation timestamp of the oldest pending job, excluding delayed jobs.
     *
     * @param  string|null  $queue
     * @return int|null
     */
    public function creationTimeOfOldestPendingJob($queue = null);

    /**
     * Push a new job onto the queue.
     *
     * @param  string|object  $job
     * @param  mixed  $data
     * @param  string|null  $queue
     * @return mixed
     */
    public function push($job, $data = '', $queue = null);

    /**
     * Push a new job onto the queue.
     *
     * @param  string  $queue
     * @param  string|object  $job
     * @param  mixed  $data
     * @return mixed
     */
    public function pushOn($queue, $job, $data = '');

    /**
     * Push a raw payload onto the queue.
     *
     * @param  string  $payload
     * @param  string|null  $queue
     * @return mixed
     */
    public function pushRaw($payload, $queue = null, array $options = []);

    /**
     * Push a new job onto the queue after (n) seconds.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  string|object  $job
     * @param  mixed  $data
     * @param  string|null  $queue
     * @return mixed
     */
    public function later($delay, $job, $data = '', $queue = null);

    /**
     * Push a new job onto a specific queue after (n) seconds.
     *
     * @param  string  $queue
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  string|object  $job
     * @param  mixed  $data
     * @return mixed
     */
    public function laterOn($queue, $delay, $job, $data = '');

    /**
     * Push an array of jobs onto the queue.
     *
     * @param  array  $jobs
     * @param  mixed  $data
     * @param  string|null  $queue
     * @return mixed
     */
    public function bulk($jobs, $data = '', $queue = null);

    /**
     * Pop the next job off of the queue.
     *
     * @param  string|null  $queue
     * @return \Illuminate\Contracts\Queue\Job|null
     */
    public function pop($queue = null);

    /**
     * Get the connection name for the queue.
     *
     * @return string
     */
    public function getConnectionName();

    /**
     * Set the connection name for the queue.
     *
     * @param  string  $name
     * @return $this
     */
    public function setConnectionName($name);
}
<?php

namespace Illuminate\Contracts\Queue;

interface ShouldQueueAfterCommit extends ShouldQueue
{
    //
}
<?php

namespace Illuminate\Contracts\Queue;

interface QueueableEntity
{
    /**
     * Get the queueable identity for the entity.
     *
     * @return mixed
     */
    public function getQueueableId();

    /**
     * Get the relationships for the entity.
     *
     * @return array
     */
    public function getQueueableRelations();

    /**
     * Get the connection of the entity.
     *
     * @return string|null
     */
    public function getQueueableConnection();
}
<?php

namespace Illuminate\Contracts\Queue;

interface ShouldBeUniqueUntilProcessing extends ShouldBeUnique
{
    //
}
<?php

namespace Illuminate\Contracts\Queue;

interface Interruptible
{
    /**
     * Handle a signal received by the queue worker.
     *
     * @param  int  $signal
     * @return void
     */
    public function interrupted(int $signal): void;
}
<?php

namespace Illuminate\Contracts\Queue;

interface ShouldQueue
{
    //
}
<?php

namespace Illuminate\Contracts\Queue;

interface EntityResolver
{
    /**
     * Resolve the entity for the given ID.
     *
     * @param  string  $type
     * @param  mixed  $id
     * @return mixed
     */
    public function resolve($type, $id);
}
<?php

namespace Illuminate\Contracts\Queue;

interface Job
{
    /**
     * Get the UUID of the job.
     *
     * @return string|null
     */
    public function uuid();

    /**
     * Get the job identifier.
     *
     * @return string
     */
    public function getJobId();

    /**
     * Get the decoded body of the job.
     *
     * @return array
     */
    public function payload();

    /**
     * Fire the job.
     *
     * @return void
     */
    public function fire();

    /**
     * Release the job back into the queue after (n) seconds.
     *
     * @param  int  $delay
     * @return void
     */
    public function release($delay = 0);

    /**
     * Determine if the job was released back into the queue.
     *
     * @return bool
     */
    public function isReleased();

    /**
     * Delete the job from the queue.
     *
     * @return void
     */
    public function delete();

    /**
     * Determine if the job has been deleted.
     *
     * @return bool
     */
    public function isDeleted();

    /**
     * Determine if the job has been deleted or released.
     *
     * @return bool
     */
    public function isDeletedOrReleased();

    /**
     * Get the number of times the job has been attempted.
     *
     * @return int
     */
    public function attempts();

    /**
     * Determine if the job has been marked as a failure.
     *
     * @return bool
     */
    public function hasFailed();

    /**
     * Mark the job as "failed".
     *
     * @return void
     */
    public function markAsFailed();

    /**
     * Delete the job, call the "failed" method, and raise the failed job event.
     *
     * @param  \Throwable|null  $e
     * @return void
     */
    public function fail($e = null);

    /**
     * Get the number of times to attempt a job.
     *
     * @return int|null
     */
    public function maxTries();

    /**
     * Get the maximum number of exceptions allowed, regardless of attempts.
     *
     * @return int|null
     */
    public function maxExceptions();

    /**
     * Get the number of seconds the job can run.
     *
     * @return int|null
     */
    public function timeout();

    /**
     * Get the timestamp indicating when the job should timeout.
     *
     * @return int|null
     */
    public function retryUntil();

    /**
     * Get the name of the queued job class.
     *
     * @return string
     */
    public function getName();

    /**
     * Get the display name of the queued job class.
     *
     * Resolves the name of "wrapped" jobs such as class-based handlers.
     *
     * @return string
     */
    public function resolveName();

    /**
     * Get the class of the queued job.
     *
     * Resolves the class of "wrapped" jobs such as class-based handlers.
     *
     * @return string
     */
    public function resolveQueuedJobClass();

    /**
     * Get the name of the connection the job belongs to.
     *
     * @return string
     */
    public function getConnectionName();

    /**
     * Get the name of the queue the job belongs to.
     *
     * @return string
     */
    public function getQueue();

    /**
     * Get the raw body string for the job.
     *
     * @return string
     */
    public function getRawBody();
}
<?php

namespace Illuminate\Contracts\Queue;

interface QueueableCollection
{
    /**
     * Get the type of the entities being queued.
     *
     * @return string|null
     */
    public function getQueueableClass();

    /**
     * Get the identifiers for all of the entities.
     *
     * @return array<int, mixed>
     */
    public function getQueueableIds();

    /**
     * Get the relationships of the entities being queued.
     *
     * @return array<int, string>
     */
    public function getQueueableRelations();

    /**
     * Get the connection of the entities being queued.
     *
     * @return string|null
     */
    public function getQueueableConnection();
}
<?php

namespace Illuminate\Contracts\Queue;

interface ShouldBeEncrypted
{
    //
}
<?php

namespace Illuminate\Contracts\Notifications;

interface Factory
{
    /**
     * Get a channel instance by name.
     *
     * @param  string|null  $name
     * @return mixed
     */
    public function channel($name = null);

    /**
     * Send the given notification to the given notifiable entities.
     *
     * @param  \Illuminate\Support\Collection|mixed  $notifiables
     * @param  mixed  $notification
     * @return void
     */
    public function send($notifiables, $notification);

    /**
     * Send the given notification immediately.
     *
     * @param  \Illuminate\Support\Collection|mixed  $notifiables
     * @param  mixed  $notification
     * @return void
     */
    public function sendNow($notifiables, $notification);
}
<?php

namespace Illuminate\Contracts\Notifications;

interface Dispatcher
{
    /**
     * Send the given notification to the given notifiable entities.
     *
     * @param  \Illuminate\Support\Collection|mixed  $notifiables
     * @param  mixed  $notification
     * @return void
     */
    public function send($notifiables, $notification);

    /**
     * Send the given notification immediately.
     *
     * @param  \Illuminate\Support\Collection|mixed  $notifiables
     * @param  mixed  $notification
     * @param  array|null  $channels
     * @return void
     */
    public function sendNow($notifiables, $notification, ?array $channels = null);
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface Factory
{
    /**
     * Get a broadcaster implementation by name.
     *
     * @param  string|null  $name
     * @return \Illuminate\Contracts\Broadcasting\Broadcaster
     */
    public function connection($name = null);
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface ShouldRescue
{
    //
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface ShouldBeUnique
{
    //
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface HasBroadcastChannel
{
    /**
     * Get the broadcast channel route definition that is associated with the given entity.
     *
     * @return string
     */
    public function broadcastChannelRoute();

    /**
     * Get the broadcast channel name that is associated with the given entity.
     *
     * @return string
     */
    public function broadcastChannel();
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface Broadcaster
{
    /**
     * Authenticate the incoming request for a given channel.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    public function auth($request);

    /**
     * Return the valid authentication response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $result
     * @return mixed
     */
    public function validAuthenticationResponse($request, $result);

    /**
     * Broadcast the given event.
     *
     * @param  array  $channels
     * @param  string  $event
     * @param  array  $payload
     * @return void
     *
     * @throws \Illuminate\Broadcasting\BroadcastException
     */
    public function broadcast(array $channels, $event, array $payload = []);
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface ShouldBroadcast
{
    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[]|string[]|string
     */
    public function broadcastOn();
}
<?php

namespace Illuminate\Contracts\Broadcasting;

interface ShouldBroadcastNow extends ShouldBroadcast
{
    //
}
<?php

namespace Illuminate\Contracts\Translation;

interface Loader
{
    /**
     * Load the messages for the given locale.
     *
     * @param  string  $locale
     * @param  string  $group
     * @param  string|null  $namespace
     * @return array
     */
    public function load($locale, $group, $namespace = null);

    /**
     * Add a new namespace to the loader.
     *
     * @param  string  $namespace
     * @param  string  $hint
     * @return void
     */
    public function addNamespace($namespace, $hint);

    /**
     * Add a new JSON path to the loader.
     *
     * @param  string  $path
     * @return void
     */
    public function addJsonPath($path);

    /**
     * Get an array of all the registered namespaces.
     *
     * @return array<string, string>
     */
    public function namespaces();
}
<?php

namespace Illuminate\Contracts\Translation;

interface Translator
{
    /**
     * Get the translation for a given key.
     *
     * @param  string  $key
     * @param  array  $replace
     * @param  string|null  $locale
     * @return mixed
     */
    public function get($key, array $replace = [], $locale = null);

    /**
     * Get a translation according to an integer value.
     *
     * @param  string  $key
     * @param  \Countable|int|float|array  $number
     * @param  array  $replace
     * @param  string|null  $locale
     * @return string
     */
    public function choice($key, $number, array $replace = [], $locale = null);

    /**
     * Get the default locale being used.
     *
     * @return string
     */
    public function getLocale();

    /**
     * Set the default locale.
     *
     * @param  string  $locale
     * @return void
     */
    public function setLocale($locale);
}
<?php

namespace Illuminate\Contracts\Translation;

interface HasLocalePreference
{
    /**
     * Get the preferred locale of the entity.
     *
     * @return string|null
     */
    public function preferredLocale();
}
<?php

namespace Illuminate\Contracts\JsonSchema;

use Closure;

interface JsonSchema
{
    /**
     * Create a new object schema instance.
     *
     * @param  (Closure(JsonSchema): array<string, \Illuminate\JsonSchema\Types\Type>)|array<string, \Illuminate\JsonSchema\Types\Type>  $properties
     * @return \Illuminate\JsonSchema\Types\ObjectType
     */
    public function object(Closure|array $properties = []);

    /**
     * Create a new array property instance.
     *
     * @return \Illuminate\JsonSchema\Types\ArrayType
     */
    public function array();

    /**
     * Create a new string property instance.
     *
     * @return \Illuminate\JsonSchema\Types\StringType
     */
    public function string();

    /**
     * Create a new integer property instance.
     *
     * @return \Illuminate\JsonSchema\Types\IntegerType
     */
    public function integer();

    /**
     * Create a new number property instance.
     *
     * @return \Illuminate\JsonSchema\Types\NumberType
     */
    public function number();

    /**
     * Create a new boolean property instance.
     *
     * @return \Illuminate\JsonSchema\Types\BooleanType
     */
    public function boolean();
}
<?php

namespace Illuminate\Contracts\Console;

interface Application
{
    /**
     * Run an Artisan console command by name.
     *
     * @param  string  $command
     * @param  array  $parameters
     * @param  \Symfony\Component\Console\Output\OutputInterface|null  $outputBuffer
     * @return int
     */
    public function call($command, array $parameters = [], $outputBuffer = null);

    /**
     * Get the output from the last command.
     *
     * @return string
     */
    public function output();
}
<?php

namespace Illuminate\Contracts\Console;

interface PromptsForMissingInput
{
    //
}
<?php

namespace Illuminate\Contracts\Console;

interface Kernel
{
    /**
     * Bootstrap the application for artisan commands.
     *
     * @return void
     */
    public function bootstrap();

    /**
     * Handle an incoming console command.
     *
     * @param  \Symfony\Component\Console\Input\InputInterface  $input
     * @param  \Symfony\Component\Console\Output\OutputInterface|null  $output
     * @return int
     */
    public function handle($input, $output = null);

    /**
     * Run an Artisan console command by name.
     *
     * @param  string  $command
     * @param  array  $parameters
     * @param  \Symfony\Component\Console\Output\OutputInterface|null  $outputBuffer
     * @return int
     */
    public function call($command, array $parameters = [], $outputBuffer = null);

    /**
     * Queue an Artisan console command by name.
     *
     * @param  string  $command
     * @param  array  $parameters
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public function queue($command, array $parameters = []);

    /**
     * Get all of the commands registered with the console.
     *
     * @return array
     */
    public function all();

    /**
     * Get the output for the last run command.
     *
     * @return string
     */
    public function output();

    /**
     * Terminate the application.
     *
     * @param  \Symfony\Component\Console\Input\InputInterface  $input
     * @param  int  $status
     * @return void
     */
    public function terminate($input, $status);
}
<?php

namespace Illuminate\Contracts\Console;

interface Isolatable
{
    //
}
<?php

namespace Illuminate\Support;

use ArrayIterator;
use Illuminate\Contracts\Support\ValidatedData;
use Illuminate\Support\Traits\Dumpable;
use Illuminate\Support\Traits\InteractsWithData;
use Traversable;

class ValidatedInput implements ValidatedData
{
    use Dumpable, InteractsWithData;

    /**
     * The underlying input.
     *
     * @var array
     */
    protected $input;

    /**
     * Create a new validated input container.
     *
     * @param  array  $input
     */
    public function __construct(array $input)
    {
        $this->input = $input;
    }

    /**
     * Merge the validated input with the given array of additional data.
     *
     * @param  array  $items
     * @return static
     */
    public function merge(array $items)
    {
        return new static(array_merge($this->all(), $items));
    }

    /**
     * Get the raw, underlying input array.
     *
     * @param  mixed  $keys
     * @return array
     */
    public function all($keys = null)
    {
        if (! $keys) {
            return $this->input;
        }

        $input = [];

        foreach (is_array($keys) ? $keys : func_get_args() as $key) {
            Arr::set($input, $key, Arr::get($this->input, $key));
        }

        return $input;
    }

    /**
     * Retrieve data from the instance.
     *
     * @param  string|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    protected function data($key = null, $default = null)
    {
        return $this->input($key, $default);
    }

    /**
     * Get the keys for all of the input.
     *
     * @return array
     */
    public function keys()
    {
        return array_keys($this->input());
    }

    /**
     * Retrieve an input item from the validated inputs.
     *
     * @param  string|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    public function input($key = null, $default = null)
    {
        return data_get(
            $this->all(), $key, $default
        );
    }

    /**
     * Retrieve a file from the validated inputs.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return \Illuminate\Http\UploadedFile|null
     */
    public function file($key, $default = null)
    {
        $value = $this->input($key, $default);

        return $value instanceof \Illuminate\Http\UploadedFile ? $value : $default;
    }

    /**
     * Dump the items.
     *
     * @param  mixed  ...$keys
     * @return $this
     */
    public function dump(...$keys)
    {
        dump($keys !== [] ? $this->only($keys) : $this->all());

        return $this;
    }

    /**
     * Get the instance as an array.
     *
     * @return array
     */
    public function toArray()
    {
        return $this->all();
    }

    /**
     * Dynamically access input data.
     *
     * @param  string  $name
     * @return mixed
     */
    public function __get($name)
    {
        return $this->input($name);
    }

    /**
     * Dynamically set input data.
     *
     * @param  string  $name
     * @param  mixed  $value
     * @return mixed
     */
    public function __set($name, $value)
    {
        $this->input[$name] = $value;
    }

    /**
     * Determine if an input item is set.
     *
     * @param  string  $name
     * @return bool
     */
    public function __isset($name)
    {
        return $this->exists($name);
    }

    /**
     * Remove an input item.
     *
     * @param  string  $name
     * @return void
     */
    public function __unset($name)
    {
        unset($this->input[$name]);
    }

    /**
     * Determine if an item exists at an offset.
     *
     * @param  mixed  $key
     * @return bool
     */
    public function offsetExists($key): bool
    {
        return $this->exists($key);
    }

    /**
     * Get an item at a given offset.
     *
     * @param  mixed  $key
     * @return mixed
     */
    public function offsetGet($key): mixed
    {
        return $this->input($key);
    }

    /**
     * Set the item at a given offset.
     *
     * @param  mixed  $key
     * @param  mixed  $value
     * @return void
     */
    public function offsetSet($key, $value): void
    {
        if (is_null($key)) {
            $this->input[] = $value;
        } else {
            $this->input[$key] = $value;
        }
    }

    /**
     * Unset the item at a given offset.
     *
     * @param  string  $key
     * @return void
     */
    public function offsetUnset($key): void
    {
        unset($this->input[$key]);
    }

    /**
     * Get an iterator for the input.
     *
     * @return \ArrayIterator
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->input);
    }
}
<?php

namespace Illuminate\Support;

use Carbon\CarbonInterval;
use Closure;
use DateInterval;
use Illuminate\Support\Traits\Macroable;
use PHPUnit\Framework\Assert as PHPUnit;
use RuntimeException;

class Sleep
{
    use Macroable;

    /**
     * The fake sleep callbacks.
     *
     * @var array
     */
    public static $fakeSleepCallbacks = [];

    /**
     * Keep Carbon's "now" in sync when sleeping.
     *
     * @var bool
     */
    protected static $syncWithCarbon = false;

    /**
     * The total duration to sleep.
     *
     * @var \Carbon\CarbonInterval
     */
    public $duration;

    /**
     * The callback that determines if sleeping should continue.
     *
     * @var \Closure
     */
    public $while;

    /**
     * The pending duration to sleep.
     *
     * @var int|float|null
     */
    protected $pending = null;

    /**
     * Indicates that all sleeping should be faked.
     *
     * @var bool
     */
    protected static $fake = false;

    /**
     * The sequence of sleep durations encountered while faking.
     *
     * @var array<int, \Carbon\CarbonInterval>
     */
    protected static $sequence = [];

    /**
     * Indicates if the instance should sleep.
     *
     * @var bool
     */
    protected $shouldSleep = true;

    /**
     * Indicates if the instance already slept via `then()`.
     *
     * @var bool
     */
    protected $alreadySlept = false;

    /**
     * Create a new class instance.
     *
     * @param  int|float|\DateInterval  $duration
     */
    public function __construct($duration)
    {
        $this->duration($duration);
    }

    /**
     * Sleep for the given duration.
     *
     * @param  \DateInterval|int|float  $duration
     * @return static
     */
    public static function for($duration)
    {
        return new static($duration);
    }

    /**
     * Sleep until the given timestamp.
     *
     * @param  \DateTimeInterface|int|float|numeric-string  $timestamp
     * @return static
     */
    public static function until($timestamp)
    {
        if (is_numeric($timestamp)) {
            $timestamp = Carbon::createFromTimestamp($timestamp, date_default_timezone_get());
        }

        return new static(Carbon::now()->diff($timestamp));
    }

    /**
     * Sleep for the given number of microseconds.
     *
     * @param  int  $duration
     * @return static
     */
    public static function usleep($duration)
    {
        return (new static($duration))->microseconds();
    }

    /**
     * Sleep for the given number of seconds.
     *
     * @param  int|float  $duration
     * @return static
     */
    public static function sleep($duration)
    {
        return (new static($duration))->seconds();
    }

    /**
     * Sleep for the given duration. Replaces any previously defined duration.
     *
     * @param  \DateInterval|int|float  $duration
     * @return $this
     */
    protected function duration($duration)
    {
        if (! $duration instanceof DateInterval) {
            $this->duration = CarbonInterval::microsecond(0);

            $this->pending = $duration;
        } else {
            $duration = CarbonInterval::instance($duration);

            if ($duration->totalMicroseconds < 0) {
                $duration = CarbonInterval::seconds(0);
            }

            $this->duration = $duration;
            $this->pending = null;
        }

        return $this;
    }

    /**
     * Sleep for the given number of minutes.
     *
     * @return $this
     */
    public function minutes()
    {
        $this->duration->add('minutes', $this->pullPending());

        return $this;
    }

    /**
     * Sleep for one minute.
     *
     * @return $this
     */
    public function minute()
    {
        return $this->minutes();
    }

    /**
     * Sleep for the given number of seconds.
     *
     * @return $this
     */
    public function seconds()
    {
        $this->duration->add('seconds', $this->pullPending());

        return $this;
    }

    /**
     * Sleep for one second.
     *
     * @return $this
     */
    public function second()
    {
        return $this->seconds();
    }

    /**
     * Sleep for the given number of milliseconds.
     *
     * @return $this
     */
    public function milliseconds()
    {
        $this->duration->add('milliseconds', $this->pullPending());

        return $this;
    }

    /**
     * Sleep for one millisecond.
     *
     * @return $this
     */
    public function millisecond()
    {
        return $this->milliseconds();
    }

    /**
     * Sleep for the given number of microseconds.
     *
     * @return $this
     */
    public function microseconds()
    {
        $this->duration->add('microseconds', $this->pullPending());

        return $this;
    }

    /**
     * Sleep for on microsecond.
     *
     * @return $this
     */
    public function microsecond()
    {
        return $this->microseconds();
    }

    /**
     * Add additional time to sleep for.
     *
     * @param  int|float  $duration
     * @return $this
     */
    public function and($duration)
    {
        $this->pending = $duration;

        return $this;
    }

    /**
     * Sleep while a given callback returns "true".
     *
     * @param  \Closure  $callback
     * @return $this
     */
    public function while(Closure $callback)
    {
        $this->while = $callback;

        return $this;
    }

    /**
     * Specify a callback that should be executed after sleeping.
     *
     * @param  callable  $then
     * @return mixed
     */
    public function then(callable $then)
    {
        $this->goodnight();

        $this->alreadySlept = true;

        return $then();
    }

    /**
     * Handle the object's destruction.
     *
     * @return void
     */
    public function __destruct()
    {
        $this->goodnight();
    }

    /**
     * Handle the object's destruction.
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    protected function goodnight()
    {
        if ($this->alreadySlept || ! $this->shouldSleep) {
            return;
        }

        if ($this->pending !== null) {
            throw new RuntimeException('Unknown duration unit.');
        }

        if (static::$fake) {
            static::$sequence[] = $this->duration;

            if (static::$syncWithCarbon) {
                Carbon::setTestNow(Carbon::now()->add($this->duration));
            }

            foreach (static::$fakeSleepCallbacks as $callback) {
                $callback($this->duration);
            }

            return;
        }

        $remaining = $this->duration->copy();

        $seconds = (int) $remaining->totalSeconds;

        $while = $this->while ?: function () {
            static $return = [true, false];

            return array_shift($return);
        };

        while ($while()) {
            if ($seconds > 0) {
                sleep($seconds);

                $remaining = $remaining->subSeconds($seconds);
            }

            $microseconds = (int) $remaining->totalMicroseconds;

            if ($microseconds > 0) {
                usleep($microseconds);
            }
        }
    }

    /**
     * Resolve the pending duration.
     *
     * @return int|float
     *
     * @throws \RuntimeException
     */
    protected function pullPending()
    {
        if ($this->pending === null) {
            $this->shouldNotSleep();

            throw new RuntimeException('No duration specified.');
        }

        if ($this->pending < 0) {
            $this->pending = 0;
        }

        return tap($this->pending, function () {
            $this->pending = null;
        });
    }

    /**
     * Stay awake and capture any attempts to sleep.
     *
     * @param  bool  $value
     * @param  bool  $syncWithCarbon
     * @return void
     */
    public static function fake($value = true, $syncWithCarbon = false)
    {
        static::$fake = $value;

        static::$sequence = [];
        static::$fakeSleepCallbacks = [];
        static::$syncWithCarbon = $syncWithCarbon;
    }

    /**
     * Assert a given amount of sleeping occurred a specific number of times.
     *
     * @param  \Closure  $expected
     * @param  int  $times
     * @return void
     */
    public static function assertSlept($expected, $times = 1)
    {
        $count = (new Collection(static::$sequence))->filter($expected)->count();

        PHPUnit::assertSame(
            $times,
            $count,
            "The expected sleep was found [{$count}] times instead of [{$times}]."
        );
    }

    /**
     * Assert sleeping occurred a given number of times.
     *
     * @param  int  $expected
     * @return void
     */
    public static function assertSleptTimes($expected)
    {
        PHPUnit::assertSame($expected, $count = count(static::$sequence), "Expected [{$expected}] sleeps but found [{$count}].");
    }

    /**
     * Assert the given sleep sequence was encountered.
     *
     * @param  array  $sequence
     * @return void
     */
    public static function assertSequence($sequence)
    {
        try {
            static::assertSleptTimes(count($sequence));

            (new Collection($sequence))
                ->zip(static::$sequence)
                ->eachSpread(function (?Sleep $expected, CarbonInterval $actual) {
                    if ($expected === null) {
                        return;
                    }

                    PHPUnit::assertTrue(
                        $expected->shouldNotSleep()->duration->equalTo($actual),
                        vsprintf('Expected sleep duration of [%s] but actually slept for [%s].', [
                            $expected->duration->cascade()->forHumans([
                                'options' => 0,
                                'minimumUnit' => 'microsecond',
                            ]),
                            $actual->cascade()->forHumans([
                                'options' => 0,
                                'minimumUnit' => 'microsecond',
                            ]),
                        ])
                    );
                });
        } finally {
            foreach ($sequence as $expected) {
                if ($expected instanceof self) {
                    $expected->shouldNotSleep();
                }
            }
        }
    }

    /**
     * Assert that no sleeping occurred.
     *
     * @return void
     */
    public static function assertNeverSlept()
    {
        static::assertSleptTimes(0);
    }

    /**
     * Assert that no sleeping occurred.
     *
     * @return void
     */
    public static function assertInsomniac()
    {
        if (static::$sequence === []) {
            PHPUnit::assertTrue(true);
        }

        foreach (static::$sequence as $duration) {
            PHPUnit::assertSame(0, (int) $duration->totalMicroseconds, vsprintf('Unexpected sleep duration of [%s] found.', [
                $duration->cascade()->forHumans([
                    'options' => 0,
                    'minimumUnit' => 'microsecond',
                ]),
            ]));
        }
    }

    /**
     * Indicate that the instance should not sleep.
     *
     * @return $this
     */
    protected function shouldNotSleep()
    {
        $this->shouldSleep = false;

        return $this;
    }

    /**
     * Only sleep when the given condition is true.
     *
     * @param  (\Closure($this): bool)|bool  $condition
     * @return $this
     */
    public function when($condition)
    {
        $this->shouldSleep = (bool) value($condition, $this);

        return $this;
    }

    /**
     * Don't sleep when the given condition is true.
     *
     * @param  (\Closure($this): bool)|bool  $condition
     * @return $this
     */
    public function unless($condition)
    {
        return $this->when(! value($condition, $this));
    }

    /**
     * Specify a callback that should be invoked when faking sleep within a test.
     *
     * @param  callable  $callback
     * @return void
     */
    public static function whenFakingSleep($callback)
    {
        static::$fakeSleepCallbacks[] = $callback;
    }

    /**
     * Indicate that Carbon's "now" should be kept in sync when sleeping.
     *
     * @return void
     */
    public static function syncWithCarbon($value = true)
    {
        static::$syncWithCarbon = $value;
    }
}
<?php

namespace Illuminate\Support;

use Doctrine\Inflector\InflectorFactory;

class Pluralizer
{
    /**
     * The cached inflector instance.
     *
     * @var static
     */
    protected static $inflector;

    /**
     * The language that should be used by the inflector.
     *
     * @var string
     */
    protected static $language = 'english';

    /**
     * Uncountable non-nouns word forms.
     *
     * Contains words supported by Doctrine/Inflector/Rules/English/Uninflected.php
     *
     * @var string[]
     */
    public static $uncountable = [
        'recommended',
        'related',
    ];

    /**
     * Get the plural form of an English word.
     *
     * @param  string  $value
     * @param  int|array|\Countable  $count
     * @return string
     */
    public static function plural($value, $count = 2)
    {
        if (is_countable($count)) {
            $count = count($count);
        }

        if ((int) abs($count) === 1 || static::uncountable($value) || preg_match('/^(.*)[A-Za-z0-9\x{0080}-\x{FFFF}]$/u', $value) == 0) {
            return $value;
        }

        $plural = static::inflector()->pluralize($value);

        return static::matchCase($plural, $value);
    }

    /**
     * Get the singular form of an English word.
     *
     * @param  string  $value
     * @return string
     */
    public static function singular($value)
    {
        $singular = static::inflector()->singularize($value);

        return static::matchCase($singular, $value);
    }

    /**
     * Determine if the given value is uncountable.
     *
     * @param  string  $value
     * @return bool
     */
    protected static function uncountable($value)
    {
        return in_array(strtolower($value), static::$uncountable);
    }

    /**
     * Attempt to match the case on two strings.
     *
     * @param  string  $value
     * @param  string  $comparison
     * @return string
     */
    protected static function matchCase($value, $comparison)
    {
        $functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords'];

        foreach ($functions as $function) {
            if ($function($comparison) === $comparison) {
                return $function($value);
            }
        }

        return $value;
    }

    /**
     * Get the inflector instance.
     *
     * @return \Doctrine\Inflector\Inflector
     */
    public static function inflector()
    {
        if (is_null(static::$inflector)) {
            static::$inflector = InflectorFactory::createForLanguage(static::$language)->build();
        }

        return static::$inflector;
    }

    /**
     * Specify the language that should be used by the inflector.
     *
     * @param  string  $language
     * @return void
     */
    public static function useLanguage(string $language)
    {
        static::$language = $language;

        static::$inflector = null;
    }
}
<?php

namespace Illuminate\Support;

use ArrayAccess;
use ArrayObject;
use Illuminate\Support\Traits\Macroable;

class Optional implements ArrayAccess
{
    use Macroable {
        __call as macroCall;
    }

    /**
     * The underlying object.
     *
     * @var mixed
     */
    protected $value;

    /**
     * Create a new optional instance.
     *
     * @param  mixed  $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }

    /**
     * Dynamically access a property on the underlying object.
     *
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {
        if (is_object($this->value)) {
            return $this->value->{$key} ?? null;
        }
    }

    /**
     * Dynamically check a property exists on the underlying object.
     *
     * @param  mixed  $name
     * @return bool
     */
    public function __isset($name)
    {
        if (is_object($this->value)) {
            return isset($this->value->{$name});
        }

        if (is_array($this->value) || $this->value instanceof ArrayObject) {
            return isset($this->value[$name]);
        }

        return false;
    }

    /**
     * Determine if an item exists at an offset.
     *
     * @param  mixed  $offset
     * @return bool
     */
    public function offsetExists($offset): bool
    {
        return Arr::accessible($this->value) && Arr::exists($this->value, $offset);
    }

    /**
     * Get an item at a given offset.
     *
     * @param  mixed  $offset
     * @return mixed
     */
    public function offsetGet($offset): mixed
    {
        return Arr::get($this->value, $offset);
    }

    /**
     * Set the item at a given offset.
     *
     * @param  mixed  $offset
     * @param  mixed  $value
     * @return void
     */
    public function offsetSet($offset, $value): void
    {
        if (Arr::accessible($this->value)) {
            $this->value[$offset] = $value;
        }
    }

    /**
     * Unset the item at a given offset.
     *
     * @param  string  $offset
     * @return void
     */
    public function offsetUnset($offset): void
    {
        if (Arr::accessible($this->value)) {
            unset($this->value[$offset]);
        }
    }

    /**
     * Dynamically pass a method to the underlying object.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        if (static::hasMacro($method)) {
            return $this->macroCall($method, $parameters);
        }

        if (is_object($this->value)) {
            return $this->value->{$method}(...$parameters);
        }
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Validation\Validator make(array $data, array $rules, array $messages = [], array $attributes = [])
 * @method static array validate(array $data, array $rules, array $messages = [], array $attributes = [])
 * @method static void extend(string $rule, \Closure|string $extension, string|null $message = null)
 * @method static void extendImplicit(string $rule, \Closure|string $extension, string|null $message = null)
 * @method static void extendDependent(string $rule, \Closure|string $extension, string|null $message = null)
 * @method static void replacer(string $rule, \Closure|string $replacer)
 * @method static void includeUnvalidatedArrayKeys()
 * @method static void excludeUnvalidatedArrayKeys()
 * @method static void resolver(\Closure $resolver)
 * @method static \Illuminate\Contracts\Translation\Translator getTranslator()
 * @method static \Illuminate\Validation\PresenceVerifierInterface getPresenceVerifier()
 * @method static void setPresenceVerifier(\Illuminate\Validation\PresenceVerifierInterface $presenceVerifier)
 * @method static \Illuminate\Contracts\Container\Container|null getContainer()
 * @method static \Illuminate\Validation\Factory setContainer(\Illuminate\Contracts\Container\Container $container)
 *
 * @see \Illuminate\Validation\Factory
 */
class Validator extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'validator';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Closure;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Benchmark;
use Illuminate\Support\Collection;
use Illuminate\Support\Js;
use Illuminate\Support\Number;
use Illuminate\Support\Str;
use Illuminate\Support\Testing\Fakes\Fake;
use Illuminate\Support\Uri;
use Mockery;
use Mockery\LegacyMockInterface;
use RuntimeException;

abstract class Facade
{
    /**
     * The application instance being facaded.
     *
     * @var \Illuminate\Contracts\Foundation\Application|null
     */
    protected static $app;

    /**
     * The resolved object instances.
     *
     * @var array
     */
    protected static $resolvedInstance;

    /**
     * Indicates if the resolved instance should be cached.
     *
     * @var bool
     */
    protected static $cached = true;

    /**
     * Run a Closure when the facade has been resolved.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public static function resolved(Closure $callback)
    {
        $accessor = static::getFacadeAccessor();

        if (static::$app->resolved($accessor) === true) {
            $callback(static::getFacadeRoot(), static::$app);
        }

        static::$app->afterResolving($accessor, function ($service, $app) use ($callback) {
            $callback($service, $app);
        });
    }

    /**
     * Convert the facade into a Mockery spy.
     *
     * @return \Mockery\MockInterface
     */
    public static function spy()
    {
        if (! static::isMock()) {
            $class = static::getMockableClass();

            return tap($class ? Mockery::spy($class) : Mockery::spy(), function ($spy) {
                static::swap($spy);
            });
        }
    }

    /**
     * Initiate a partial mock on the facade.
     *
     * @return \Mockery\MockInterface
     */
    public static function partialMock()
    {
        $name = static::getFacadeAccessor();

        $mock = static::isMock()
            ? static::$resolvedInstance[$name]
            : static::createFreshMockInstance();

        return $mock->makePartial();
    }

    /**
     * Initiate a mock expectation on the facade.
     *
     * @return \Mockery\Expectation
     */
    public static function shouldReceive()
    {
        $name = static::getFacadeAccessor();

        $mock = static::isMock()
            ? static::$resolvedInstance[$name]
            : static::createFreshMockInstance();

        return $mock->shouldReceive(...func_get_args());
    }

    /**
     * Initiate a mock expectation on the facade.
     *
     * @return \Mockery\Expectation
     */
    public static function expects()
    {
        $name = static::getFacadeAccessor();

        $mock = static::isMock()
            ? static::$resolvedInstance[$name]
            : static::createFreshMockInstance();

        return $mock->expects(...func_get_args());
    }

    /**
     * Create a fresh mock instance for the given class.
     *
     * @return \Mockery\MockInterface
     */
    protected static function createFreshMockInstance()
    {
        return tap(static::createMock(), function ($mock) {
            static::swap($mock);

            $mock->shouldAllowMockingProtectedMethods();
        });
    }

    /**
     * Create a fresh mock instance for the given class.
     *
     * @return \Mockery\MockInterface
     */
    protected static function createMock()
    {
        $class = static::getMockableClass();

        return $class ? Mockery::mock($class) : Mockery::mock();
    }

    /**
     * Determines whether a mock is set as the instance of the facade.
     *
     * @return bool
     */
    protected static function isMock()
    {
        $name = static::getFacadeAccessor();

        return isset(static::$resolvedInstance[$name]) &&
               static::$resolvedInstance[$name] instanceof LegacyMockInterface;
    }

    /**
     * Get the mockable class for the bound instance.
     *
     * @return string|null
     */
    protected static function getMockableClass()
    {
        if ($root = static::getFacadeRoot()) {
            return get_class($root);
        }
    }

    /**
     * Hotswap the underlying instance behind the facade.
     *
     * @param  mixed  $instance
     * @return void
     */
    public static function swap($instance)
    {
        static::$resolvedInstance[static::getFacadeAccessor()] = $instance;

        if (isset(static::$app)) {
            static::$app->instance(static::getFacadeAccessor(), $instance);
        }
    }

    /**
     * Determines whether a "fake" has been set as the facade instance.
     *
     * @return bool
     */
    public static function isFake()
    {
        $name = static::getFacadeAccessor();

        return isset(static::$resolvedInstance[$name]) &&
               static::$resolvedInstance[$name] instanceof Fake;
    }

    /**
     * Get the root object behind the facade.
     *
     * @return mixed
     */
    public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    protected static function getFacadeAccessor()
    {
        throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
    }

    /**
     * Resolve the facade root instance from the container.
     *
     * @param  string  $name
     * @return mixed
     */
    protected static function resolveFacadeInstance($name)
    {
        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }

        if (static::$app) {
            if (static::$cached) {
                return static::$resolvedInstance[$name] = static::$app[$name];
            }

            return static::$app[$name];
        }
    }

    /**
     * Clear a resolved facade instance.
     *
     * @param  ?string  $name
     * @return void
     */
    public static function clearResolvedInstance($name = null)
    {
        unset(static::$resolvedInstance[$name ?? static::getFacadeAccessor()]);
    }

    /**
     * Clear all of the resolved instances.
     *
     * @return void
     */
    public static function clearResolvedInstances()
    {
        static::$resolvedInstance = [];
    }

    /**
     * Get the application default aliases.
     *
     * @return \Illuminate\Support\Collection
     */
    public static function defaultAliases()
    {
        return new Collection([
            'App' => App::class,
            'Arr' => Arr::class,
            'Artisan' => Artisan::class,
            'Auth' => Auth::class,
            'Benchmark' => Benchmark::class,
            'Blade' => Blade::class,
            'Broadcast' => Broadcast::class,
            'Bus' => Bus::class,
            'Cache' => Cache::class,
            'Concurrency' => Concurrency::class,
            'Config' => Config::class,
            'Context' => Context::class,
            'Cookie' => Cookie::class,
            'Crypt' => Crypt::class,
            'Date' => Date::class,
            'DB' => DB::class,
            'Eloquent' => Model::class,
            'Event' => Event::class,
            'File' => File::class,
            'Gate' => Gate::class,
            'Hash' => Hash::class,
            'Http' => Http::class,
            'Js' => Js::class,
            'Lang' => Lang::class,
            'Log' => Log::class,
            'Mail' => Mail::class,
            'Notification' => Notification::class,
            'Number' => Number::class,
            'Password' => Password::class,
            'Process' => Process::class,
            'Queue' => Queue::class,
            'RateLimiter' => RateLimiter::class,
            'Redirect' => Redirect::class,
            'Request' => Request::class,
            'Response' => Response::class,
            'Route' => Route::class,
            'Schedule' => Schedule::class,
            'Schema' => Schema::class,
            'Session' => Session::class,
            'Storage' => Storage::class,
            'Str' => Str::class,
            'Uri' => Uri::class,
            'URL' => URL::class,
            'Validator' => Validator::class,
            'View' => View::class,
            'Vite' => Vite::class,
        ]);
    }

    /**
     * Get the application instance behind the facade.
     *
     * @return \Illuminate\Contracts\Foundation\Application|null
     */
    public static function getFacadeApplication()
    {
        return static::$app;
    }

    /**
     * Set the application instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application|null  $app
     * @return void
     */
    public static function setFacadeApplication($app)
    {
        static::$app = $app;
    }

    /**
     * Handle dynamic, static calls to the object.
     *
     * @param  string  $method
     * @param  array  $args
     * @return mixed
     *
     * @throws \RuntimeException
     */
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Testing\Fakes\EventFake;

/**
 * @method static void listen(\Illuminate\Events\QueuedClosure|callable|array|string $events, \Illuminate\Events\QueuedClosure|callable|array|string|null $listener = null)
 * @method static bool hasListeners(string $eventName)
 * @method static bool hasWildcardListeners(string $eventName)
 * @method static void push(string $event, object|array $payload = [])
 * @method static void flush(string $event)
 * @method static void subscribe(object|string $subscriber)
 * @method static array|null until(string|object $event, mixed $payload = [])
 * @method static array|null dispatch(string|object $event, mixed $payload = [], bool $halt = false)
 * @method static array getListeners(string $eventName)
 * @method static \Closure makeListener(\Closure|string|array $listener, bool $wildcard = false)
 * @method static \Closure createClassListener(string $listener, bool $wildcard = false)
 * @method static void forget(string $event)
 * @method static void forgetPushed()
 * @method static \Illuminate\Events\Dispatcher setQueueResolver(callable $resolver)
 * @method static \Illuminate\Events\Dispatcher setTransactionManagerResolver(callable $resolver)
 * @method static mixed defer(callable $callback, string[]|null $events = null)
 * @method static array getRawListeners()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static string|null resolveConnectionFromQueueRoute(object $queueable)
 * @method static string|null resolveQueueFromQueueRoute(object $queueable)
 * @method static \Illuminate\Support\Testing\Fakes\EventFake except(array|string $eventsToDispatch)
 * @method static void assertListening(string $expectedEvent, string|array $expectedListener)
 * @method static void assertDispatched(string|\Closure $event, callable|int|null $callback = null)
 * @method static void assertDispatchedOnce(string $event)
 * @method static void assertDispatchedTimes(string $event, int $times = 1)
 * @method static void assertNotDispatched(string|\Closure $event, callable|null $callback = null)
 * @method static void assertNothingDispatched()
 * @method static \Illuminate\Support\Collection dispatched(string $event, callable|null $callback = null)
 * @method static bool hasDispatched(string $event)
 * @method static array dispatchedEvents()
 *
 * @see \Illuminate\Events\Dispatcher
 * @see \Illuminate\Support\Testing\Fakes\EventFake
 */
class Event extends Facade
{
    /**
     * Replace the bound instance with a fake.
     *
     * @param  array|string  $eventsToFake
     * @return \Illuminate\Support\Testing\Fakes\EventFake
     */
    public static function fake($eventsToFake = [])
    {
        $actualDispatcher = static::isFake()
            ? static::getFacadeRoot()->dispatcher
            : static::getFacadeRoot();

        return tap(new EventFake($actualDispatcher, $eventsToFake), function ($fake) {
            static::swap($fake);

            Model::setEventDispatcher($fake);
            Cache::refreshEventDispatcher();
        });
    }

    /**
     * Replace the bound instance with a fake that fakes all events except the given events.
     *
     * @param  string[]|string  $eventsToAllow
     * @return \Illuminate\Support\Testing\Fakes\EventFake
     */
    public static function fakeExcept($eventsToAllow)
    {
        return static::fake([
            function ($eventName) use ($eventsToAllow) {
                return ! in_array($eventName, (array) $eventsToAllow);
            },
        ]);
    }

    /**
     * Replace the bound instance with a fake during the given callable's execution.
     *
     * @param  callable  $callable
     * @param  array  $eventsToFake
     * @return mixed
     */
    public static function fakeFor(callable $callable, array $eventsToFake = [])
    {
        $originalDispatcher = static::getFacadeRoot();

        static::fake($eventsToFake);

        try {
            return $callable();
        } finally {
            static::swap($originalDispatcher);

            Model::setEventDispatcher($originalDispatcher);
            Cache::refreshEventDispatcher();
        }
    }

    /**
     * Replace the bound instance with a fake during the given callable's execution.
     *
     * @param  callable  $callable
     * @param  array  $eventsToAllow
     * @return mixed
     */
    public static function fakeExceptFor(callable $callable, array $eventsToAllow = [])
    {
        $originalDispatcher = static::getFacadeRoot();

        static::fakeExcept($eventsToAllow);

        try {
            return $callable();
        } finally {
            static::swap($originalDispatcher);

            Model::setEventDispatcher($originalDispatcher);
            Cache::refreshEventDispatcher();
        }
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'events';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Http\Request capture()
 * @method static \Illuminate\Http\Request instance()
 * @method static string method()
 * @method static \Illuminate\Support\Uri uri()
 * @method static string root()
 * @method static string url()
 * @method static string fullUrl()
 * @method static string fullUrlWithQuery(array $query)
 * @method static string fullUrlWithoutQuery(array|string $keys)
 * @method static string path()
 * @method static string decodedPath()
 * @method static string|null segment(int $index, string|null $default = null)
 * @method static array segments()
 * @method static bool is(mixed ...$patterns)
 * @method static bool routeIs(mixed ...$patterns)
 * @method static bool fullUrlIs(mixed ...$patterns)
 * @method static string host()
 * @method static string httpHost()
 * @method static string schemeAndHttpHost()
 * @method static bool ajax()
 * @method static bool pjax()
 * @method static bool prefetch()
 * @method static bool secure()
 * @method static string|null ip()
 * @method static array ips()
 * @method static string|null userAgent()
 * @method static array getAcceptableContentTypes()
 * @method static \Illuminate\Http\Request merge(array $input)
 * @method static \Illuminate\Http\Request mergeIfMissing(array $input)
 * @method static \Illuminate\Http\Request replace(array $input)
 * @method static \Symfony\Component\HttpFoundation\InputBag|mixed json(string|null $key = null, mixed $default = null)
 * @method static \Illuminate\Http\Request createFrom(\Illuminate\Http\Request $from, \Illuminate\Http\Request|null $to = null)
 * @method static \Illuminate\Http\Request createFromBase(\Symfony\Component\HttpFoundation\Request $request)
 * @method static \Illuminate\Http\Request duplicate(array|null $query = null, array|null $request = null, array|null $attributes = null, array|null $cookies = null, array|null $files = null, array|null $server = null)
 * @method static bool hasSession(bool $skipIfUninitialized = false)
 * @method static \Symfony\Component\HttpFoundation\Session\SessionInterface getSession()
 * @method static \Illuminate\Contracts\Session\Session session()
 * @method static void setLaravelSession(\Illuminate\Contracts\Session\Session $session)
 * @method static void setRequestLocale(string $locale)
 * @method static void setDefaultRequestLocale(string $locale)
 * @method static mixed user(string|null $guard = null)
 * @method static \Illuminate\Routing\Route|object|string|null route(string|null $param = null, mixed $default = null)
 * @method static string fingerprint()
 * @method static \Illuminate\Http\Request setJson(\Symfony\Component\HttpFoundation\InputBag $json)
 * @method static \Closure getUserResolver()
 * @method static \Illuminate\Http\Request setUserResolver(\Closure $callback)
 * @method static \Closure getRouteResolver()
 * @method static \Illuminate\Http\Request setRouteResolver(\Closure $callback)
 * @method static array toArray()
 * @method static void initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], string|resource|null $content = null)
 * @method static \Illuminate\Http\Request createFromGlobals()
 * @method static \Illuminate\Http\Request create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], string|resource|null $content = null)
 * @method static void setFactory(callable|null $callable)
 * @method static void overrideGlobals()
 * @method static void setTrustedProxies(array $proxies, int $trustedHeaderSet)
 * @method static string[] getTrustedProxies()
 * @method static int getTrustedHeaderSet()
 * @method static void setTrustedHosts(array $hostPatterns)
 * @method static string[] getTrustedHosts()
 * @method static string normalizeQueryString(string|null $qs)
 * @method static void enableHttpMethodParameterOverride()
 * @method static bool getHttpMethodParameterOverride()
 * @method static void setAllowedHttpMethodOverride(string[]|null $methods)
 * @method static string[]|null getAllowedHttpMethodOverride()
 * @method static bool hasPreviousSession()
 * @method static void setSession(\Symfony\Component\HttpFoundation\Session\SessionInterface $session)
 * @method static array getClientIps()
 * @method static string|null getClientIp()
 * @method static string getScriptName()
 * @method static string getPathInfo()
 * @method static string getBasePath()
 * @method static string getBaseUrl()
 * @method static string getScheme()
 * @method static int|string|null getPort()
 * @method static string|null getUser()
 * @method static string|null getPassword()
 * @method static string|null getUserInfo()
 * @method static string getHttpHost()
 * @method static string getRequestUri()
 * @method static string getSchemeAndHttpHost()
 * @method static string getUri()
 * @method static string getUriForPath(string $path)
 * @method static string getRelativeUriForPath(string $path)
 * @method static string|null getQueryString()
 * @method static bool isSecure()
 * @method static string getHost()
 * @method static void setMethod(string $method)
 * @method static string getMethod()
 * @method static string getRealMethod()
 * @method static string|null getMimeType(string $format)
 * @method static string[] getMimeTypes(string $format)
 * @method static string|null getFormat(string|null $mimeType, bool $subtypeFallback = null)
 * @method static void setFormat(string $format, string|string[] $mimeTypes)
 * @method static string|null getRequestFormat(string|null $default = 'html')
 * @method static void setRequestFormat(string|null $format)
 * @method static string|null getContentTypeFormat()
 * @method static void setDefaultLocale(string $locale)
 * @method static string getDefaultLocale()
 * @method static void setLocale(string $locale)
 * @method static string getLocale()
 * @method static bool isMethod(string $method)
 * @method static bool isMethodSafe()
 * @method static bool isMethodIdempotent()
 * @method static bool isMethodCacheable()
 * @method static string|null getProtocolVersion()
 * @method static string|resource getContent(bool $asResource = false)
 * @method static \Symfony\Component\HttpFoundation\InputBag getPayload()
 * @method static array getETags()
 * @method static bool isNoCache()
 * @method static string|null getPreferredFormat(string|null $default = 'html')
 * @method static string|null getPreferredLanguage(string[] $locales = null)
 * @method static string[] getLanguages()
 * @method static string[] getCharsets()
 * @method static string[] getEncodings()
 * @method static bool isXmlHttpRequest()
 * @method static bool preferSafeContent()
 * @method static bool isFromTrustedProxy()
 * @method static array filterPrecognitiveRules(array $rules)
 * @method static bool isAttemptingPrecognition()
 * @method static bool isPrecognitive()
 * @method static bool isJson()
 * @method static bool expectsJson()
 * @method static bool wantsJson()
 * @method static bool wantsMarkdown()
 * @method static bool accepts(string|array $contentTypes)
 * @method static string|null prefers(string|array $contentTypes)
 * @method static bool acceptsAnyContentType()
 * @method static bool acceptsJson()
 * @method static bool acceptsMarkdown()
 * @method static bool acceptsHtml()
 * @method static bool matchesType(string $actual, string $type)
 * @method static string format(string $default = 'html')
 * @method static string|array|null old(string|null $key = null, \Illuminate\Database\Eloquent\Model|string|array|null $default = null)
 * @method static void flash()
 * @method static void flashOnly(mixed $keys)
 * @method static void flashExcept(mixed $keys)
 * @method static void flush()
 * @method static string|array|null server(string|null $key = null, string|array|null $default = null)
 * @method static bool hasHeader(string $key)
 * @method static string|array|null header(string|null $key = null, string|array|null $default = null)
 * @method static string|null bearerToken()
 * @method static array keys()
 * @method static array all(mixed $keys = null)
 * @method static mixed input(string|null $key = null, mixed $default = null)
 * @method static \Illuminate\Support\Fluent fluent(array|string|null $key = null, array $default = [])
 * @method static string|array|null query(string|null $key = null, string|array|null $default = null)
 * @method static string|array|null post(string|null $key = null, string|array|null $default = null)
 * @method static bool hasCookie(string $key)
 * @method static string|array|null cookie(string|null $key = null, string|array|null $default = null)
 * @method static array allFiles()
 * @method static bool hasFile(string $key)
 * @method static array|\Illuminate\Http\UploadedFile|\Illuminate\Http\UploadedFile[]|null file(string|null $key = null, mixed $default = null)
 * @method static \Illuminate\Http\Request dump(mixed $keys = [])
 * @method static never dd(mixed ...$args)
 * @method static bool exists(string|array $key)
 * @method static bool has(string|array $key)
 * @method static bool hasAny(string|array $keys)
 * @method static \Illuminate\Http\Request|mixed whenHas(string $key, callable $callback, callable|null $default = null)
 * @method static bool filled(string|array $key)
 * @method static bool isNotFilled(string|array $key)
 * @method static bool anyFilled(string|array $keys)
 * @method static \Illuminate\Http\Request|mixed whenFilled(string $key, callable $callback, callable|null $default = null)
 * @method static bool missing(string|array $key)
 * @method static \Illuminate\Http\Request|mixed whenMissing(string $key, callable $callback, callable|null $default = null)
 * @method static \Illuminate\Support\Stringable str(string $key, mixed $default = null)
 * @method static \Illuminate\Support\Stringable string(string $key, mixed $default = null)
 * @method static bool boolean(string|null $key = null, bool $default = false)
 * @method static int integer(string $key, int $default = 0)
 * @method static float float(string $key, float $default = 0)
 * @method static float|int clamp(string $key, int|float $min, int|float $max, int|float $default = 0)
 * @method static \Illuminate\Support\Carbon|null date(string $key, string|null $format = null, \UnitEnum|string|null $tz = null)
 * @method static \Carbon\CarbonInterval|null interval(string $key, \Carbon\Unit|string|null $unit = null)
 * @method static \BackedEnum|\BackedEnum|null enum(string $key, string $enumClass, \BackedEnum|null $default = null)
 * @method static \BackedEnum[] enums(string $key, string $enumClass)
 * @method static array array(array|string|null $key = null)
 * @method static \Illuminate\Support\Collection collect(array|string|null $key = null)
 * @method static array only(mixed $keys)
 * @method static array except(mixed $keys)
 * @method static \Illuminate\Http\Request|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Http\Request|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static array validate(array $rules, ...$params)
 * @method static array validateWithBag(string $errorBag, array $rules, ...$params)
 * @method static bool hasValidSignature(bool $absolute = true)
 * @method static bool hasValidRelativeSignature()
 * @method static bool hasValidSignatureWhileIgnoring($ignoreQuery = [], $absolute = true)
 * @method static bool hasValidRelativeSignatureWhileIgnoring($ignoreQuery = [])
 *
 * @see \Illuminate\Http\Request
 */
class Request extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'request';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static bool has(string $key)
 * @method static bool missing(string $key)
 * @method static bool hasHidden(string $key)
 * @method static bool missingHidden(string $key)
 * @method static array all()
 * @method static array allHidden()
 * @method static mixed get(string $key, mixed $default = null)
 * @method static mixed getHidden(string $key, mixed $default = null)
 * @method static mixed pull(string $key, mixed $default = null)
 * @method static mixed pullHidden(string $key, mixed $default = null)
 * @method static array only(array $keys)
 * @method static array onlyHidden(array $keys)
 * @method static array except(array $keys)
 * @method static array exceptHidden(array $keys)
 * @method static \Illuminate\Log\Context\Repository add(string|array $key, mixed $value = null)
 * @method static \Illuminate\Log\Context\Repository addHidden(string|array $key, mixed $value = null)
 * @method static mixed remember(string $key, mixed $value)
 * @method static mixed rememberHidden(string $key, mixed $value)
 * @method static \Illuminate\Log\Context\Repository forget(string|array $key)
 * @method static \Illuminate\Log\Context\Repository forgetHidden(string|array $key)
 * @method static \Illuminate\Log\Context\Repository addIf(string $key, mixed $value)
 * @method static \Illuminate\Log\Context\Repository addHiddenIf(string $key, mixed $value)
 * @method static \Illuminate\Log\Context\Repository push(string $key, mixed ...$values)
 * @method static mixed pop(string $key)
 * @method static \Illuminate\Log\Context\Repository pushHidden(string $key, mixed ...$values)
 * @method static mixed popHidden(string $key)
 * @method static \Illuminate\Log\Context\Repository increment(string $key, int $amount = 1)
 * @method static \Illuminate\Log\Context\Repository decrement(string $key, int $amount = 1)
 * @method static bool stackContains(string $key, mixed $value, bool $strict = false)
 * @method static bool hiddenStackContains(string $key, mixed $value, bool $strict = false)
 * @method static mixed scope(callable $callback, array $data = [], array $hidden = [])
 * @method static bool isEmpty()
 * @method static \Illuminate\Log\Context\Repository dehydrating(callable $callback)
 * @method static \Illuminate\Log\Context\Repository hydrated(callable $callback)
 * @method static \Illuminate\Log\Context\Repository handleUnserializeExceptionsUsing(callable|null $callback)
 * @method static \Illuminate\Log\Context\Repository flush()
 * @method static \Illuminate\Log\Context\Repository|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Log\Context\Repository|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static \Illuminate\Database\Eloquent\Model restoreModel(\Illuminate\Contracts\Database\ModelIdentifier $value)
 *
 * @see \Illuminate\Log\Context\Repository
 */
class Context extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return \Illuminate\Log\Context\Repository::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static void defaultStringLength(int $length)
 * @method static void defaultTimePrecision(int|null $precision)
 * @method static void defaultMorphKeyType(string $type)
 * @method static void morphUsingUuids()
 * @method static void morphUsingUlids()
 * @method static bool createDatabase(string $name)
 * @method static bool dropDatabaseIfExists(string $name)
 * @method static array getSchemas()
 * @method static bool hasTable(string $table)
 * @method static bool hasView(string $view)
 * @method static array getTables(string|string[]|null $schema = null)
 * @method static array getTableListing(string|string[]|null $schema = null, bool $schemaQualified = true)
 * @method static array getViews(string|string[]|null $schema = null)
 * @method static array getTypes(string|string[]|null $schema = null)
 * @method static bool hasColumn(string $table, string $column)
 * @method static bool hasColumns(string $table, array $columns)
 * @method static void whenTableHasColumn(string $table, string $column, \Closure $callback)
 * @method static void whenTableDoesntHaveColumn(string $table, string $column, \Closure $callback)
 * @method static void whenTableHasIndex(string $table, string|array $index, \Closure $callback, string|null $type = null)
 * @method static void whenTableDoesntHaveIndex(string $table, string|array $index, \Closure $callback, string|null $type = null)
 * @method static string getColumnType(string $table, string $column, bool $fullDefinition = false)
 * @method static array getColumnListing(string $table)
 * @method static array getColumns(string $table)
 * @method static array getIndexes(string $table)
 * @method static array getIndexListing(string $table)
 * @method static bool hasIndex(string $table, string|array $index, string|null $type = null)
 * @method static array getForeignKeys(string $table)
 * @method static void table(string $table, \Closure $callback)
 * @method static void create(string $table, \Closure $callback)
 * @method static void drop(string $table)
 * @method static void dropIfExists(string $table)
 * @method static void dropColumns(string $table, string|array $columns)
 * @method static void dropAllTables()
 * @method static void dropAllViews()
 * @method static void dropAllTypes()
 * @method static void rename(string $from, string $to)
 * @method static bool enableForeignKeyConstraints()
 * @method static bool disableForeignKeyConstraints()
 * @method static mixed withoutForeignKeyConstraints(\Closure $callback)
 * @method static void ensureVectorExtensionExists(string|null $schema = null)
 * @method static void ensureExtensionExists(string $name, string|null $schema = null)
 * @method static string[]|null getCurrentSchemaListing()
 * @method static string|null getCurrentSchemaName()
 * @method static array parseSchemaAndTable(string $reference, string|bool|null $withDefaultSchema = null)
 * @method static \Illuminate\Database\Connection getConnection()
 * @method static void blueprintResolver(\Closure $resolver)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Database\Schema\Builder
 */
class Schema extends Facade
{
    /**
     * Indicates if the resolved facade should be cached.
     *
     * @var bool
     */
    protected static $cached = false;

    /**
     * Get a schema builder instance for a connection.
     *
     * @param  string|null  $name
     * @return \Illuminate\Database\Schema\Builder
     */
    public static function connection($name)
    {
        return static::$app['db']->connection($name)->getSchemaBuilder();
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'db.schema';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static array preloadedAssets()
 * @method static string|null cspNonce()
 * @method static string useCspNonce(string|null $nonce = null)
 * @method static \Illuminate\Foundation\Vite useIntegrityKey(string|false $key)
 * @method static \Illuminate\Foundation\Vite withEntryPoints(array $entryPoints)
 * @method static \Illuminate\Foundation\Vite mergeEntryPoints(array $entryPoints)
 * @method static \Illuminate\Foundation\Vite useManifestFilename(string $filename)
 * @method static \Illuminate\Foundation\Vite createAssetPathsUsing(callable|null $resolver)
 * @method static string hotFile()
 * @method static \Illuminate\Foundation\Vite useHotFile(string $path)
 * @method static \Illuminate\Foundation\Vite useBuildDirectory(string $path)
 * @method static \Illuminate\Foundation\Vite useScriptTagAttributes(callable|array $attributes)
 * @method static \Illuminate\Foundation\Vite useStyleTagAttributes(callable|array $attributes)
 * @method static \Illuminate\Foundation\Vite usePreloadTagAttributes(callable|array|false $attributes)
 * @method static \Illuminate\Foundation\Vite prefetch(int|null $concurrency = null, string $event = 'load')
 * @method static \Illuminate\Foundation\Vite useWaterfallPrefetching(int|null $concurrency = null)
 * @method static \Illuminate\Foundation\Vite useAggressivePrefetching()
 * @method static \Illuminate\Foundation\Vite usePrefetchStrategy(string|null $strategy, array $config = [])
 * @method static \Illuminate\Support\HtmlString|void reactRefresh()
 * @method static string asset(string $asset, string|null $buildDirectory = null)
 * @method static string content(string $asset, string|null $buildDirectory = null)
 * @method static string|null manifestHash(string|null $buildDirectory = null)
 * @method static \Illuminate\Support\HtmlString fonts(array|string|null $aliases = null)
 * @method static \Illuminate\Foundation\Vite useFontsManifestFilename(string $filename)
 * @method static bool isRunningHot()
 * @method static string toHtml()
 * @method static void flush()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Foundation\Vite
 */
class Vite extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return \Illuminate\Foundation\Vite::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract;

/**
 * @method static \Illuminate\Http\Response make(mixed $content = '', int $status = 200, array $headers = [])
 * @method static \Illuminate\Http\Response noContent(int $status = 204, array $headers = [])
 * @method static \Illuminate\Http\Response view(string|array $view, array $data = [], int $status = 200, array $headers = [])
 * @method static \Illuminate\Http\JsonResponse json(mixed $data = [], int $status = 200, array $headers = [], int $options = 0)
 * @method static \Illuminate\Http\JsonResponse jsonp(string $callback, mixed $data = [], int $status = 200, array $headers = [], int $options = 0)
 * @method static \Symfony\Component\HttpFoundation\StreamedResponse eventStream(\Closure $callback, array $headers = [], \Illuminate\Http\StreamedEvent|string|null $endStreamWith = '</stream>')
 * @method static \Symfony\Component\HttpFoundation\StreamedResponse stream(callable|null $callback, int $status = 200, array $headers = [])
 * @method static \Symfony\Component\HttpFoundation\StreamedJsonResponse streamJson(array $data, int $status = 200, array $headers = [], int $encodingOptions = 15)
 * @method static \Symfony\Component\HttpFoundation\StreamedResponse streamDownload(callable $callback, string|null $name = null, array $headers = [], string|null $disposition = 'attachment')
 * @method static \Symfony\Component\HttpFoundation\BinaryFileResponse download(\SplFileInfo|string $file, string|null $name = null, array $headers = [], string|null $disposition = 'attachment')
 * @method static \Symfony\Component\HttpFoundation\BinaryFileResponse file(\SplFileInfo|string $file, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse redirectTo(string $path, int $status = 302, array $headers = [], bool|null $secure = null)
 * @method static \Illuminate\Http\RedirectResponse redirectToRoute(\BackedEnum|string $route, mixed $parameters = [], int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse redirectToAction(array|string $action, mixed $parameters = [], int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse redirectGuest(string $path, int $status = 302, array $headers = [], bool|null $secure = null)
 * @method static \Illuminate\Http\RedirectResponse redirectToIntended(string $default = '/', int $status = 302, array $headers = [], bool|null $secure = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Routing\ResponseFactory
 */
class Response extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return ResponseFactoryContract::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Console\Scheduling\Schedule as ConsoleSchedule;

/**
 * @method static \Illuminate\Console\Scheduling\CallbackEvent call(string|callable $callback, array $parameters = [])
 * @method static \Illuminate\Console\Scheduling\Event command(\Symfony\Component\Console\Command\Command|string $command, array $parameters = [])
 * @method static \Illuminate\Console\Scheduling\CallbackEvent job(object|string $job, \UnitEnum|string|null $queue = null, \UnitEnum|string|null $connection = null)
 * @method static \Illuminate\Console\Scheduling\Event exec(string $command, array $parameters = [])
 * @method static void group(\Closure $events)
 * @method static string compileArrayInput(string|int $key, array $value)
 * @method static bool serverShouldRun(\Illuminate\Console\Scheduling\Event $event, \DateTimeInterface $time)
 * @method static \Illuminate\Support\Collection dueEvents(\Illuminate\Contracts\Foundation\Application $app)
 * @method static \Illuminate\Console\Scheduling\Event[] events()
 * @method static \Illuminate\Console\Scheduling\Event[] eventsForEnvironments(array $environments)
 * @method static \Illuminate\Console\Scheduling\Schedule useCache(\UnitEnum|string $store)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes withoutOverlapping(int $expiresAt = 1440, bool $releaseOnTerminationSignals = true)
 * @method static void mergeAttributes(\Illuminate\Console\Scheduling\Event $event)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes user(string $user)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes environments(mixed $environments)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes evenInMaintenanceMode()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes evenWhenPaused()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes onOneServer()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes runInBackground()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes when(\Closure|bool $callback)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes skip(\Closure|bool $callback)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes name(string $description)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes description(string $description)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes cron(string $expression)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes between(string $startTime, string $endTime)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes unlessBetween(string $startTime, string $endTime)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everySecond()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyTwoSeconds()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyFiveSeconds()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyTenSeconds()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyFifteenSeconds()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyTwentySeconds()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyThirtySeconds()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyMinute()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyTwoMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyThreeMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyFourMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyFiveMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyTenMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyFifteenMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyThirtyMinutes()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes hourly()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes hourlyAt(array|string|int|int[] $offset)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyOddHour(array|string|int $offset = 0)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyTwoHours(array|string|int $offset = 0)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyThreeHours(array|string|int $offset = 0)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everyFourHours(array|string|int $offset = 0)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes everySixHours(array|string|int $offset = 0)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes daily()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes at(string $time)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes dailyAt(string $time)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes twiceDaily(int $first = 1, int $second = 13)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes twiceDailyAt(int $first = 1, int $second = 13, int $offset = 0)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes weekdays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes weekends()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes mondays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes tuesdays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes wednesdays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes thursdays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes fridays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes saturdays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes sundays()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes weekly()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes weeklyOn(mixed $dayOfWeek, string $time = '0:0')
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes monthly()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes monthlyOn(int $dayOfMonth = 1, string $time = '0:0')
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes twiceMonthly(int $first = 1, int $second = 16, string $time = '0:0')
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes lastDayOfMonth(string $time = '0:0')
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes daysOfMonth(array|int ...$days)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes quarterly()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes quarterlyOn(int $dayOfQuarter = 1, string $time = '0:0')
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes yearly()
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes yearlyOn(int $month = 1, int|string $dayOfMonth = 1, string $time = '0:0')
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes days(mixed $days)
 * @method static \Illuminate\Console\Scheduling\PendingEventAttributes timezone(\UnitEnum|\DateTimeZone|string $timezone)
 *
 * @see \Illuminate\Console\Scheduling\Schedule
 */
class Schedule extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return ConsoleSchedule::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Pipeline\Pipeline send(mixed $passable)
 * @method static \Illuminate\Pipeline\Pipeline through(mixed $pipes)
 * @method static \Illuminate\Pipeline\Pipeline pipe(mixed $pipes)
 * @method static \Illuminate\Pipeline\Pipeline via(string $method)
 * @method static mixed then(\Closure $destination)
 * @method static mixed thenReturn()
 * @method static \Illuminate\Pipeline\Pipeline finally(\Closure $callback)
 * @method static \Illuminate\Pipeline\Pipeline withinTransaction(string|null|\UnitEnum|false $withinTransaction = null)
 * @method static \Illuminate\Pipeline\Pipeline setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static \Illuminate\Pipeline\Pipeline|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Pipeline\Pipeline|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Pipeline\Pipeline
 */
class Pipeline extends Facade
{
    /**
     * Indicates if the resolved instance should be cached.
     *
     * @var bool
     */
    protected static $cached = false;

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'pipeline';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Support\Testing\Fakes\MailFake;

/**
 * @method static \Illuminate\Contracts\Mail\Mailer mailer(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Mail\Mailer driver(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Mail\Mailer build(array $config)
 * @method static \Symfony\Component\Mailer\Transport\TransportInterface createSymfonyTransport(array $config)
 * @method static string getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static void purge(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Mail\MailManager extend(string $driver, \Closure $callback)
 * @method static \Illuminate\Contracts\Foundation\Application getApplication()
 * @method static \Illuminate\Mail\MailManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static \Illuminate\Mail\MailManager forgetMailers()
 * @method static void alwaysFrom(string $address, string|null $name = null)
 * @method static void alwaysReplyTo(string $address, string|null $name = null)
 * @method static void alwaysReturnPath(string $address)
 * @method static void alwaysTo(string $address, string|null $name = null)
 * @method static \Illuminate\Mail\PendingMail to(mixed $users, string|null $name = null)
 * @method static \Illuminate\Mail\PendingMail cc(mixed $users, string|null $name = null)
 * @method static \Illuminate\Mail\PendingMail bcc(mixed $users, string|null $name = null)
 * @method static \Illuminate\Mail\SentMessage|null html(string $html, mixed $callback)
 * @method static \Illuminate\Mail\SentMessage|null raw(string $text, mixed $callback)
 * @method static \Illuminate\Mail\SentMessage|null plain(string $view, array $data, mixed $callback)
 * @method static string render(string|array $view, array $data = [])
 * @method static \Illuminate\Mail\SentMessage|null send(\Illuminate\Contracts\Mail\Mailable|string|array $view, array $data = [], \Closure|string|null $callback = null)
 * @method static \Illuminate\Mail\SentMessage|null sendNow(\Illuminate\Contracts\Mail\Mailable|string|array $mailable, array $data = [], \Closure|string|null $callback = null)
 * @method static mixed queue(\Illuminate\Contracts\Mail\Mailable $view, \BackedEnum|string|null $queue = null)
 * @method static mixed onQueue(\BackedEnum|string|null $queue, \Illuminate\Contracts\Mail\Mailable $view)
 * @method static mixed queueOn(string $queue, \Illuminate\Contracts\Mail\Mailable $view)
 * @method static mixed later(\DateTimeInterface|\DateInterval|int $delay, \Illuminate\Contracts\Mail\Mailable $view, string|null $queue = null)
 * @method static mixed laterOn(string $queue, \DateTimeInterface|\DateInterval|int $delay, \Illuminate\Contracts\Mail\Mailable $view)
 * @method static \Symfony\Component\Mailer\Transport\TransportInterface getSymfonyTransport()
 * @method static \Illuminate\Contracts\View\Factory getViewFactory()
 * @method static void setSymfonyTransport(\Symfony\Component\Mailer\Transport\TransportInterface $transport)
 * @method static \Illuminate\Mail\Mailer setQueue(\Illuminate\Contracts\Queue\Factory $queue)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static void assertSent(string|\Closure $mailable, callable|array|string|int|null $callback = null)
 * @method static void assertSentTimes(string $mailable, int $times = 1)
 * @method static void assertNotOutgoing(string|\Closure $mailable, callable|null $callback = null)
 * @method static void assertNotSent(string|\Closure $mailable, callable|array|string|null $callback = null)
 * @method static void assertNothingOutgoing()
 * @method static void assertNothingSent()
 * @method static void assertQueued(string|\Closure $mailable, callable|array|string|int|null $callback = null)
 * @method static void assertNotQueued(string|\Closure $mailable, callable|array|string|null $callback = null)
 * @method static void assertNothingQueued()
 * @method static void assertSentCount(int $count)
 * @method static void assertQueuedCount(int $count)
 * @method static void assertOutgoingCount(int $count)
 * @method static \Illuminate\Support\Collection sent(string|\Closure $mailable, callable|null $callback = null)
 * @method static bool hasSent(string $mailable)
 * @method static \Illuminate\Support\Collection queued(string|\Closure $mailable, callable|null $callback = null)
 * @method static bool hasQueued(string $mailable)
 *
 * @see \Illuminate\Mail\MailManager
 * @see \Illuminate\Support\Testing\Fakes\MailFake
 */
class Mail extends Facade
{
    /**
     * Replace the bound instance with a fake.
     *
     * @return \Illuminate\Support\Testing\Fakes\MailFake
     */
    public static function fake()
    {
        $actualMailManager = static::isFake()
            ? static::getFacadeRoot()->manager
            : static::getFacadeRoot();

        return tap(new MailFake($actualMailManager), function ($fake) {
            static::swap($fake);
        });
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'mail.manager';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Mockery;

/**
 * @method static \Illuminate\Contracts\Cache\Repository store(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Contracts\Cache\Repository driver(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Contracts\Cache\Repository memo(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Contracts\Cache\Repository resolve(string $name)
 * @method static \Illuminate\Cache\Repository build(array $config)
 * @method static \Illuminate\Cache\Repository repository(\Illuminate\Contracts\Cache\Store $store, array $config = [])
 * @method static void refreshEventDispatcher()
 * @method static string getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static \Illuminate\Cache\CacheManager forgetDriver(array|\UnitEnum|string|null $name = null)
 * @method static void purge(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Cache\CacheManager extend(string $driver, \Closure $callback)
 * @method static \Illuminate\Cache\CacheManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static void handleUnserializableClassUsing(callable|null $callback)
 * @method static bool has(\UnitEnum|array|string $key)
 * @method static bool missing(\UnitEnum|string $key)
 * @method static mixed get(\UnitEnum|array|string $key, mixed $default = null)
 * @method static array many(array $keys)
 * @method static iterable getMultiple(iterable $keys, mixed $default = null)
 * @method static mixed pull(\UnitEnum|array|string $key, mixed $default = null)
 * @method static string string(\UnitEnum|string $key, \Closure|string|null $default = null)
 * @method static int integer(\UnitEnum|string $key, \Closure|int|null $default = null)
 * @method static float float(\UnitEnum|string $key, \Closure|float|null $default = null)
 * @method static bool boolean(\UnitEnum|string $key, \Closure|bool|null $default = null)
 * @method static array array(\UnitEnum|string $key, \Closure|array|null $default = null)
 * @method static bool put(\UnitEnum|array|string $key, mixed $value, \DateTimeInterface|\DateInterval|int|null $ttl = null)
 * @method static bool set(\UnitEnum|array|string $key, mixed $value, \DateTimeInterface|\DateInterval|int|null $ttl = null)
 * @method static bool putMany(array $values, \DateTimeInterface|\DateInterval|int|null $ttl = null)
 * @method static bool setMultiple(iterable $values, null|int|\DateInterval $ttl = null)
 * @method static bool add(\UnitEnum|array|string $key, mixed $value, \DateTimeInterface|\DateInterval|int|null $ttl = null)
 * @method static int|bool increment(\UnitEnum|string $key, mixed $value = 1)
 * @method static int|bool decrement(\UnitEnum|string $key, mixed $value = 1)
 * @method static bool forever(\UnitEnum|string $key, mixed $value)
 * @method static mixed remember(\UnitEnum|string $key, \Closure|\DateTimeInterface|\DateInterval|int|null $ttl, \Closure $callback)
 * @method static mixed sear(\UnitEnum|string $key, \Closure $callback)
 * @method static mixed rememberForever(\UnitEnum|string $key, \Closure $callback)
 * @method static mixed flexible(\UnitEnum|string $key, array $ttl, callable $callback, array|null $lock = null, bool $alwaysDefer = false)
 * @method static bool touch(\UnitEnum|string $key, \DateTimeInterface|\DateInterval|int $ttl)
 * @method static mixed withoutOverlapping(\UnitEnum|string $key, callable $callback, int $lockFor = 0, int $waitFor = 10, string|null $owner = null)
 * @method static \Illuminate\Cache\Limiters\ConcurrencyLimiterBuilder funnel(\UnitEnum|string $name)
 * @method static bool forget(\UnitEnum|array|string $key)
 * @method static bool delete(\UnitEnum|array|string $key)
 * @method static bool deleteMultiple(iterable $keys)
 * @method static bool clear()
 * @method static bool flushLocks()
 * @method static \Illuminate\Cache\TaggedCache tags(mixed $names)
 * @method static string|null getName()
 * @method static bool supportsTags()
 * @method static bool supportsFlushingLocks()
 * @method static int|null getDefaultCacheTime()
 * @method static \Illuminate\Cache\Repository setDefaultCacheTime(int|null $seconds)
 * @method static \Illuminate\Contracts\Cache\Store getStore()
 * @method static \Illuminate\Cache\Repository setStore(\Illuminate\Contracts\Cache\Store $store)
 * @method static \Illuminate\Contracts\Events\Dispatcher|null getEventDispatcher()
 * @method static void setEventDispatcher(\Illuminate\Contracts\Events\Dispatcher $events)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static bool flush()
 * @method static string getPrefix()
 * @method static \Illuminate\Contracts\Cache\Lock lock(string $name, int $seconds = 0, string|null $owner = null)
 * @method static \Illuminate\Contracts\Cache\Lock restoreLock(string $name, string $owner)
 *
 * @see \Illuminate\Cache\CacheManager
 * @see \Illuminate\Cache\Repository
 */
class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'cache';
    }

    /**
     * Convert the facade into a Mockery spy.
     *
     * @return \Mockery\MockInterface
     */
    public static function spy()
    {
        if (! static::isMock()) {
            $class = static::getMockableClass();
            $instance = static::getFacadeRoot();

            if ($class && $instance) {
                return tap(Mockery::spy($instance)->makePartial(), function ($spy) {
                    static::swap($spy);
                });
            }

            return tap($class ? Mockery::spy($class) : Mockery::spy(), function ($spy) {
                static::swap($spy);
            });
        }
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract;

/**
 * @method static int handle(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface|null $output = null)
 * @method static void terminate(\Symfony\Component\Console\Input\InputInterface $input, int $status)
 * @method static void whenCommandLifecycleIsLongerThan(\DateTimeInterface|\Carbon\CarbonInterval|float|int $threshold, callable $handler)
 * @method static \Illuminate\Support\Carbon|null commandStartedAt()
 * @method static \Illuminate\Console\Scheduling\Schedule resolveConsoleSchedule()
 * @method static \Illuminate\Foundation\Console\ClosureCommand command(string $signature, \Closure $callback)
 * @method static void registerCommand(\Symfony\Component\Console\Command\Command $command)
 * @method static int call(\Symfony\Component\Console\Command\Command|string $command, array $parameters = [], \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer = null)
 * @method static \Illuminate\Foundation\Bus\PendingDispatch queue(string $command, array $parameters = [])
 * @method static array all()
 * @method static string output()
 * @method static void bootstrap()
 * @method static void bootstrapWithoutBootingProviders()
 * @method static void setArtisan(\Illuminate\Console\Application|null $artisan)
 * @method static \Illuminate\Foundation\Console\Kernel addCommands(array $commands)
 * @method static \Illuminate\Foundation\Console\Kernel addCommandPaths(array $paths)
 * @method static \Illuminate\Foundation\Console\Kernel addCommandRoutePaths(array $paths)
 *
 * @see \Illuminate\Foundation\Console\Kernel
 */
class Artisan extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return ConsoleKernelContract::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Support\Arr;
use Illuminate\Support\Testing\Fakes\ExceptionHandlerFake;

/**
 * @method static void register()
 * @method static \Illuminate\Foundation\Exceptions\ReportableHandler reportable(callable $reportUsing)
 * @method static \Illuminate\Foundation\Exceptions\Handler renderable(callable $renderUsing)
 * @method static \Illuminate\Foundation\Exceptions\Handler map(\Closure|string $from, \Closure|string|null $to = null)
 * @method static \Illuminate\Foundation\Exceptions\Handler dontReport(array|string $exceptions)
 * @method static \Illuminate\Foundation\Exceptions\Handler dontReportWhen(callable $dontReportWhen)
 * @method static \Illuminate\Foundation\Exceptions\Handler ignore(array|string $exceptions)
 * @method static \Illuminate\Foundation\Exceptions\Handler dontFlash(array|string $attributes)
 * @method static \Illuminate\Foundation\Exceptions\Handler level(string $type, string $level)
 * @method static void report(\Throwable $e)
 * @method static bool isReporting(\Throwable $e)
 * @method static bool shouldReport(\Throwable $e)
 * @method static \Illuminate\Foundation\Exceptions\Handler throttleUsing(callable $throttleUsing)
 * @method static \Illuminate\Foundation\Exceptions\Handler stopIgnoring(array|string $exceptions)
 * @method static array buildContextForException(\Throwable $e)
 * @method static \Illuminate\Foundation\Exceptions\Handler buildContextUsing(\Closure $contextCallback)
 * @method static \Symfony\Component\HttpFoundation\Response render(\Illuminate\Http\Request $request, \Throwable $e)
 * @method static \Illuminate\Foundation\Exceptions\Handler respondUsing(callable $callback)
 * @method static \Illuminate\Foundation\Exceptions\Handler shouldRenderJsonWhen(callable $callback)
 * @method static \Illuminate\Foundation\Exceptions\Handler dontReportDuplicates()
 * @method static \Illuminate\Contracts\Debug\ExceptionHandler handler()
 * @method static void assertReported(\Closure|string $exception)
 * @method static void assertReportedCount(int $count)
 * @method static void assertNotReported(\Closure|string $exception)
 * @method static void assertNothingReported()
 * @method static void renderForConsole(\Symfony\Component\Console\Output\OutputInterface $output, \Throwable $e)
 * @method static \Illuminate\Support\Testing\Fakes\ExceptionHandlerFake throwOnReport()
 * @method static \Illuminate\Support\Testing\Fakes\ExceptionHandlerFake throwFirstReported()
 * @method static array reported()
 * @method static \Illuminate\Support\Testing\Fakes\ExceptionHandlerFake setHandler(\Illuminate\Contracts\Debug\ExceptionHandler $handler)
 *
 * @see \Illuminate\Foundation\Exceptions\Handler
 * @see \Illuminate\Support\Testing\Fakes\ExceptionHandlerFake
 */
class Exceptions extends Facade
{
    /**
     * Replace the bound instance with a fake.
     *
     * @param  array<int, class-string<\Throwable>>|class-string<\Throwable>  $exceptions
     * @return \Illuminate\Support\Testing\Fakes\ExceptionHandlerFake
     */
    public static function fake(array|string $exceptions = [])
    {
        $exceptionHandler = static::isFake()
            ? static::getFacadeRoot()->handler()
            : static::getFacadeRoot();

        return tap(new ExceptionHandlerFake($exceptionHandler, Arr::wrap($exceptions)), function ($fake) {
            static::swap($fake);
        });
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return ExceptionHandler::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Routing\Route get(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route post(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route put(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route patch(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route delete(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route options(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route any(string $uri, array|string|callable|null $action = null)
 * @method static \Illuminate\Routing\Route fallback(array|string|callable|null $action)
 * @method static \Illuminate\Routing\Route redirect(string $uri, string $destination, int $status = 302)
 * @method static \Illuminate\Routing\Route permanentRedirect(string $uri, string $destination)
 * @method static \Illuminate\Routing\Route view(string $uri, string $view, array $data = [], int|array $status = 200, array $headers = [])
 * @method static \Illuminate\Routing\Route match(array|string $methods, string $uri, array|string|callable|null $action = null)
 * @method static void resources(array $resources, array $options = [])
 * @method static void softDeletableResources(array $resources, array $options = [])
 * @method static \Illuminate\Routing\PendingResourceRegistration resource(string $name, string $controller, array $options = [])
 * @method static void apiResources(array $resources, array $options = [])
 * @method static \Illuminate\Routing\PendingResourceRegistration apiResource(string $name, string $controller, array $options = [])
 * @method static void singletons(array $singletons, array $options = [])
 * @method static \Illuminate\Routing\PendingSingletonResourceRegistration singleton(string $name, string $controller, array $options = [])
 * @method static void apiSingletons(array $singletons, array $options = [])
 * @method static \Illuminate\Routing\PendingSingletonResourceRegistration apiSingleton(string $name, string $controller, array $options = [])
 * @method static \Illuminate\Routing\Router group(array $attributes, \Closure|array|string $routes)
 * @method static array mergeWithLastGroup(array $new, bool $prependExistingPrefix = true)
 * @method static string getLastGroupPrefix()
 * @method static \Illuminate\Routing\Route addRoute(array|string $methods, string $uri, array|string|callable|null $action)
 * @method static \Illuminate\Routing\Route newRoute(array|string $methods, string $uri, mixed $action)
 * @method static \Symfony\Component\HttpFoundation\Response respondWithRoute(string $name)
 * @method static \Symfony\Component\HttpFoundation\Response dispatch(\Illuminate\Http\Request $request)
 * @method static \Symfony\Component\HttpFoundation\Response dispatchToRoute(\Illuminate\Http\Request $request)
 * @method static array gatherRouteMiddleware(\Illuminate\Routing\Route $route)
 * @method static array resolveMiddleware(array $middleware, array $excluded = [])
 * @method static \Symfony\Component\HttpFoundation\Response prepareResponse(\Symfony\Component\HttpFoundation\Request $request, mixed $response)
 * @method static \Symfony\Component\HttpFoundation\Response toResponse(\Symfony\Component\HttpFoundation\Request $request, mixed $response)
 * @method static \Illuminate\Routing\Route substituteBindings(\Illuminate\Routing\Route $route)
 * @method static void substituteImplicitBindings(\Illuminate\Routing\Route $route)
 * @method static \Illuminate\Routing\Router substituteImplicitBindingsUsing(callable $callback)
 * @method static void matched(string|callable $callback)
 * @method static array getMiddleware()
 * @method static \Illuminate\Routing\Router aliasMiddleware(string $name, string $class)
 * @method static bool hasMiddlewareGroup(string $name)
 * @method static array getMiddlewareGroups()
 * @method static \Illuminate\Routing\Router middlewareGroup(string $name, array $middleware)
 * @method static \Illuminate\Routing\Router prependMiddlewareToGroup(string $group, string $middleware)
 * @method static \Illuminate\Routing\Router pushMiddlewareToGroup(string $group, string $middleware)
 * @method static \Illuminate\Routing\Router removeMiddlewareFromGroup(string $group, string $middleware)
 * @method static \Illuminate\Routing\Router flushMiddlewareGroups()
 * @method static void bind(string $key, string|callable $binder)
 * @method static void model(string $key, string $class, \Closure|null $callback = null)
 * @method static \Closure|null getBindingCallback(string $key)
 * @method static array getPatterns()
 * @method static void pattern(string $key, string $pattern)
 * @method static void patterns(array $patterns)
 * @method static bool hasGroupStack()
 * @method static array getGroupStack()
 * @method static mixed input(string $key, string|null $default = null)
 * @method static \Illuminate\Http\Request getCurrentRequest()
 * @method static \Illuminate\Routing\Route|null getCurrentRoute()
 * @method static \Illuminate\Routing\Route|null current()
 * @method static bool has(string|array $name)
 * @method static string|null currentRouteName()
 * @method static bool is(mixed ...$patterns)
 * @method static bool currentRouteNamed(mixed ...$patterns)
 * @method static string|null currentRouteAction()
 * @method static bool uses(array|string ...$patterns)
 * @method static bool currentRouteUses(string $action)
 * @method static void singularResourceParameters(bool $singular = true)
 * @method static void resourceParameters(array $parameters = [])
 * @method static array|null resourceVerbs(array $verbs = [])
 * @method static \Illuminate\Routing\RouteCollectionInterface getRoutes()
 * @method static void setRoutes(\Illuminate\Routing\RouteCollection $routes)
 * @method static void setCompiledRoutes(array $routes)
 * @method static array uniqueMiddleware(array $middleware)
 * @method static \Illuminate\Routing\Router setContainer(\Illuminate\Container\Container $container)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static \Illuminate\Support\HigherOrderTapProxy|\Illuminate\Routing\Router tap(callable|null $callback = null)
 * @method static \Illuminate\Routing\RouteRegistrar attribute(string $key, mixed $value)
 * @method static \Illuminate\Routing\RouteRegistrar whereAlpha(array|string $parameters)
 * @method static \Illuminate\Routing\RouteRegistrar whereAlphaNumeric(array|string $parameters)
 * @method static \Illuminate\Routing\RouteRegistrar whereNumber(array|string $parameters)
 * @method static \Illuminate\Routing\RouteRegistrar whereUlid(array|string $parameters)
 * @method static \Illuminate\Routing\RouteRegistrar whereUuid(array|string $parameters)
 * @method static \Illuminate\Routing\RouteRegistrar whereIn(array|string $parameters, array $values)
 * @method static \Illuminate\Routing\RouteRegistrar as(string $value)
 * @method static \Illuminate\Routing\RouteRegistrar can(\UnitEnum|string $ability, array|string $models = [])
 * @method static \Illuminate\Routing\RouteRegistrar controller(string $controller)
 * @method static \Illuminate\Routing\RouteRegistrar domain(\BackedEnum|string $value)
 * @method static \Illuminate\Routing\RouteRegistrar middleware(array|string|null $middleware)
 * @method static \Illuminate\Routing\RouteRegistrar missing(\Closure $missing)
 * @method static \Illuminate\Routing\RouteRegistrar name(\BackedEnum|string $value)
 * @method static \Illuminate\Routing\RouteRegistrar namespace(string|null $value)
 * @method static \Illuminate\Routing\RouteRegistrar prefix(string $prefix)
 * @method static \Illuminate\Routing\RouteRegistrar scopeBindings()
 * @method static \Illuminate\Routing\RouteRegistrar where(array $where)
 * @method static \Illuminate\Routing\RouteRegistrar withoutMiddleware(array|string $middleware)
 * @method static \Illuminate\Routing\RouteRegistrar withoutScopedBindings()
 *
 * @see \Illuminate\Routing\Router
 */
class Route extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'router';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Database\Console\Migrations\FreshCommand;
use Illuminate\Database\Console\Migrations\RefreshCommand;
use Illuminate\Database\Console\Migrations\ResetCommand;
use Illuminate\Database\Console\Migrations\RollbackCommand;
use Illuminate\Database\Console\WipeCommand;

/**
 * @method static \Illuminate\Database\Connection connection(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Database\ConnectionInterface build(array $config)
 * @method static string calculateDynamicConnectionName(array $config)
 * @method static \Illuminate\Database\ConnectionInterface connectUsing(\UnitEnum|string $name, array $config, bool $force = false)
 * @method static void purge(\UnitEnum|string|null $name = null)
 * @method static void disconnect(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Database\Connection reconnect(\UnitEnum|string|null $name = null)
 * @method static mixed usingConnection(\UnitEnum|string $name, callable $callback)
 * @method static string getDefaultConnection()
 * @method static void setDefaultConnection(string $name)
 * @method static string[] supportedDrivers()
 * @method static string[] availableDrivers()
 * @method static void extend(string $name, callable $resolver)
 * @method static void forgetExtension(string $name)
 * @method static array getConnections()
 * @method static void setReconnector(callable $reconnector)
 * @method static \Illuminate\Database\DatabaseManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static void useDefaultQueryGrammar()
 * @method static void useDefaultSchemaGrammar()
 * @method static void useDefaultPostProcessor()
 * @method static \Illuminate\Database\Schema\Builder getSchemaBuilder()
 * @method static \Illuminate\Database\Query\Builder table(\Closure|\Illuminate\Database\Query\Builder|\Illuminate\Contracts\Database\Query\Expression|\UnitEnum|string $table, string|null $as = null)
 * @method static \Illuminate\Database\Query\Builder query()
 * @method static mixed selectOne(string $query, array $bindings = [], bool $useReadPdo = true)
 * @method static mixed scalar(string $query, array $bindings = [], bool $useReadPdo = true)
 * @method static array selectFromWriteConnection(string $query, array $bindings = [])
 * @method static array select(string $query, array $bindings = [], bool $useReadPdo = true, array $fetchUsing = [])
 * @method static array selectResultSets(string $query, array $bindings = [], bool $useReadPdo = true, array $fetchUsing = [])
 * @method static \Generator cursor(string $query, array $bindings = [], bool $useReadPdo = true, array $fetchUsing = [])
 * @method static bool insert(string $query, array $bindings = [])
 * @method static int update(string $query, array $bindings = [])
 * @method static int delete(string $query, array $bindings = [])
 * @method static bool statement(string $query, array $bindings = [])
 * @method static int affectingStatement(string $query, array $bindings = [])
 * @method static bool unprepared(mixed $query)
 * @method static int|null threadCount()
 * @method static array[] pretend(\Closure $callback)
 * @method static mixed withoutPretending(\Closure $callback)
 * @method static void bindValues(\PDOStatement $statement, array $bindings)
 * @method static array prepareBindings(array $bindings)
 * @method static void logQuery(string $query, array $bindings, float|null $time = null)
 * @method static void whenQueryingForLongerThan(\DateTimeInterface|\Carbon\CarbonInterval|float|int $threshold, callable $handler)
 * @method static void allowQueryDurationHandlersToRunAgain()
 * @method static float totalQueryDuration()
 * @method static void resetTotalQueryDuration()
 * @method static void reconnectIfMissingConnection()
 * @method static \Illuminate\Database\Connection beforeStartingTransaction(\Closure $callback)
 * @method static \Illuminate\Database\Connection beforeExecuting(\Closure $callback)
 * @method static void listen(\Closure $callback)
 * @method static \Illuminate\Contracts\Database\Query\Expression raw(mixed|int|float $value)
 * @method static string escape(string|float|int|bool|null $value, bool $binary = false)
 * @method static bool hasModifiedRecords()
 * @method static void recordsHaveBeenModified(bool $value = true)
 * @method static \Illuminate\Database\Connection setRecordModificationState(bool $value)
 * @method static void forgetRecordModificationState()
 * @method static \Illuminate\Database\Connection useWriteConnectionWhenReading(bool $value = true)
 * @method static \PDO getPdo()
 * @method static \PDO|\Closure|null getRawPdo()
 * @method static \PDO getReadPdo()
 * @method static \PDO|\Closure|null getRawReadPdo()
 * @method static \Illuminate\Database\Connection setPdo(\PDO|\Closure|null $pdo)
 * @method static \Illuminate\Database\Connection setReadPdo(\PDO|\Closure|null $pdo)
 * @method static \Illuminate\Database\Connection setReadPdoConfig(array $config)
 * @method static string|null getName()
 * @method static string|null getNameWithReadWriteType()
 * @method static mixed getConfig(string|null $option = null)
 * @method static string getDriverName()
 * @method static string getDriverTitle()
 * @method static \Illuminate\Database\Query\Grammars\Grammar getQueryGrammar()
 * @method static \Illuminate\Database\Connection setQueryGrammar(\Illuminate\Database\Query\Grammars\Grammar $grammar)
 * @method static \Illuminate\Database\Schema\Grammars\Grammar getSchemaGrammar()
 * @method static \Illuminate\Database\Connection setSchemaGrammar(\Illuminate\Database\Schema\Grammars\Grammar $grammar)
 * @method static \Illuminate\Database\Query\Processors\Processor getPostProcessor()
 * @method static \Illuminate\Database\Connection setPostProcessor(\Illuminate\Database\Query\Processors\Processor $processor)
 * @method static \Illuminate\Contracts\Events\Dispatcher|null getEventDispatcher()
 * @method static \Illuminate\Database\Connection setEventDispatcher(\Illuminate\Contracts\Events\Dispatcher $events)
 * @method static void unsetEventDispatcher()
 * @method static \Illuminate\Database\Connection setTransactionManager(\Illuminate\Database\DatabaseTransactionsManager $manager)
 * @method static void unsetTransactionManager()
 * @method static bool pretending()
 * @method static array[] getQueryLog()
 * @method static array getRawQueryLog()
 * @method static void flushQueryLog()
 * @method static void enableQueryLog()
 * @method static void disableQueryLog()
 * @method static bool logging()
 * @method static string getDatabaseName()
 * @method static \Illuminate\Database\Connection setDatabaseName(string $database)
 * @method static \Illuminate\Database\Connection setReadWriteType(string|null $readWriteType)
 * @method static string getTablePrefix()
 * @method static \Illuminate\Database\Connection setTablePrefix(string $prefix)
 * @method static mixed withoutTablePrefix(\Closure $callback)
 * @method static string getServerVersion()
 * @method static void resolverFor(string $driver, \Closure $callback)
 * @method static \Closure|null getResolver(string $driver)
 * @method static mixed transaction(\Closure $callback, int $attempts = 1)
 * @method static void beginTransaction()
 * @method static void commit()
 * @method static void rollBack(int|null $toLevel = null)
 * @method static int transactionLevel()
 * @method static void afterCommit(callable $callback)
 * @method static void afterRollBack(callable $callback)
 *
 * @see \Illuminate\Database\DatabaseManager
 */
class DB extends Facade
{
    /**
     * Indicate if destructive Artisan commands should be prohibited.
     *
     * Prohibits: db:wipe, migrate:fresh, migrate:refresh, migrate:reset, and migrate:rollback
     *
     * @param  bool  $prohibit
     * @return void
     */
    public static function prohibitDestructiveCommands(bool $prohibit = true)
    {
        FreshCommand::prohibit($prohibit);
        RefreshCommand::prohibit($prohibit);
        ResetCommand::prohibit($prohibit);
        RollbackCommand::prohibit($prohibit);
        WipeCommand::prohibit($prohibit);
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'db';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Laravel\Ui\UiServiceProvider;
use RuntimeException;

/**
 * @method static \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard guard(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Auth\SessionGuard createSessionDriver(string $name, array $config)
 * @method static \Illuminate\Auth\TokenGuard createTokenDriver(string $name, array $config)
 * @method static string getDefaultDriver()
 * @method static void shouldUse(\UnitEnum|string|null $name)
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static \Illuminate\Auth\AuthManager viaRequest(string $driver, callable $callback)
 * @method static \Closure userResolver()
 * @method static \Illuminate\Auth\AuthManager resolveUsersUsing(\Closure $userResolver)
 * @method static \Illuminate\Auth\AuthManager extend(string $driver, \Closure $callback)
 * @method static \Illuminate\Auth\AuthManager provider(string $name, \Closure $callback)
 * @method static bool hasResolvedGuards()
 * @method static \Illuminate\Auth\AuthManager forgetGuards()
 * @method static \Illuminate\Auth\AuthManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static \Illuminate\Contracts\Auth\UserProvider|null createUserProvider(string|null $provider = null)
 * @method static string getDefaultUserProvider()
 * @method static bool check()
 * @method static bool guest()
 * @method static \Illuminate\Contracts\Auth\Authenticatable|null user()
 * @method static int|string|null id()
 * @method static bool validate(array $credentials = [])
 * @method static bool hasUser()
 * @method static \Illuminate\Contracts\Auth\Guard setUser(\Illuminate\Contracts\Auth\Authenticatable $user)
 * @method static bool attempt(array $credentials = [], bool $remember = false)
 * @method static bool once(array $credentials = [])
 * @method static void login(\Illuminate\Contracts\Auth\Authenticatable $user, bool $remember = false)
 * @method static \Illuminate\Contracts\Auth\Authenticatable|false loginUsingId(mixed $id, bool $remember = false)
 * @method static \Illuminate\Contracts\Auth\Authenticatable|false onceUsingId(mixed $id)
 * @method static bool viaRemember()
 * @method static void logout()
 * @method static \Symfony\Component\HttpFoundation\Response|null basic(string $field = 'email', array $extraConditions = [])
 * @method static \Symfony\Component\HttpFoundation\Response|null onceBasic(string $field = 'email', array $extraConditions = [])
 * @method static bool attemptWhen(array $credentials = [], array|callable|null $callbacks = null, bool $remember = false)
 * @method static string hashPasswordForCookie(string $passwordHash)
 * @method static void logoutCurrentDevice()
 * @method static \Illuminate\Contracts\Auth\Authenticatable|null logoutOtherDevices(string $password)
 * @method static void attempting(mixed $callback)
 * @method static \Illuminate\Contracts\Auth\Authenticatable getLastAttempted()
 * @method static string getName()
 * @method static string getRecallerName()
 * @method static \Illuminate\Auth\SessionGuard setRememberDuration(int $minutes)
 * @method static \Illuminate\Contracts\Cookie\QueueingFactory getCookieJar()
 * @method static void setCookieJar(\Illuminate\Contracts\Cookie\QueueingFactory $cookie)
 * @method static \Illuminate\Contracts\Events\Dispatcher getDispatcher()
 * @method static void setDispatcher(\Illuminate\Contracts\Events\Dispatcher $events)
 * @method static \Illuminate\Contracts\Session\Session getSession()
 * @method static \Illuminate\Contracts\Auth\Authenticatable|null getUser()
 * @method static \Symfony\Component\HttpFoundation\Request getRequest()
 * @method static \Illuminate\Auth\SessionGuard setRequest(\Symfony\Component\HttpFoundation\Request $request)
 * @method static \Illuminate\Support\Timebox getTimebox()
 * @method static \Illuminate\Contracts\Auth\Authenticatable authenticate()
 * @method static \Illuminate\Auth\SessionGuard forgetUser()
 * @method static \Illuminate\Contracts\Auth\UserProvider getProvider()
 * @method static void setProvider(\Illuminate\Contracts\Auth\UserProvider $provider)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Auth\AuthManager
 * @see \Illuminate\Auth\SessionGuard
 */
class Auth extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'auth';
    }

    /**
     * Register the typical authentication routes for an application.
     *
     * @param  array  $options
     * @return void
     *
     * @throws \RuntimeException
     */
    public static function routes(array $options = [])
    {
        if (! static::$app->providerIsLoaded(UiServiceProvider::class)) {
            throw new RuntimeException('In order to use the Auth::routes() method, please install the laravel/ui package.');
        }

        static::$app->make('router')->auth($options);
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Queue\Worker;
use Illuminate\Support\Testing\Fakes\QueueFake;

/**
 * @method static void before(mixed $callback)
 * @method static void after(mixed $callback)
 * @method static void exceptionOccurred(mixed $callback)
 * @method static void looping(mixed $callback)
 * @method static void failing(mixed $callback)
 * @method static void starting(mixed $callback)
 * @method static void stopping(mixed $callback)
 * @method static void route(array|string $class, string|null $queue = null, string|null $connection = null)
 * @method static bool connected(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Contracts\Queue\Queue connection(\UnitEnum|string|null $name = null)
 * @method static void pause(string $connection, string $queue)
 * @method static void pauseFor(string $connection, string $queue, \DateTimeInterface|\DateInterval|int $ttl)
 * @method static void resume(string $connection, string $queue)
 * @method static bool isPaused(string $connection, string $queue)
 * @method static void withoutInterruptionPolling()
 * @method static void extend(string $driver, \Closure $resolver)
 * @method static void addConnector(string $driver, \Closure $resolver)
 * @method static string getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static string getName(string|null $connection = null)
 * @method static \Illuminate\Contracts\Foundation\Application getApplication()
 * @method static \Illuminate\Queue\QueueManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static string|null resolveConnectionFromQueueRoute(object $queueable)
 * @method static string|null resolveQueueFromQueueRoute(object $queueable)
 * @method static int size(string|null $queue = null)
 * @method static int pendingSize(string|null $queue = null)
 * @method static int delayedSize(string|null $queue = null)
 * @method static int reservedSize(string|null $queue = null)
 * @method static int|null creationTimeOfOldestPendingJob(string|null $queue = null)
 * @method static mixed push(string|object $job, mixed $data = '', string|null $queue = null)
 * @method static mixed pushOn(string $queue, string|object $job, mixed $data = '')
 * @method static mixed pushRaw(string $payload, string|null $queue = null, array $options = [])
 * @method static mixed later(\DateTimeInterface|\DateInterval|int $delay, string|object $job, mixed $data = '', string|null $queue = null)
 * @method static mixed laterOn(string $queue, \DateTimeInterface|\DateInterval|int $delay, string|object $job, mixed $data = '')
 * @method static mixed bulk(array $jobs, mixed $data = '', string|null $queue = null)
 * @method static \Illuminate\Contracts\Queue\Job|null pop(string|null $queue = null)
 * @method static string getConnectionName()
 * @method static \Illuminate\Contracts\Queue\Queue setConnectionName(string $name)
 * @method static mixed getJobTries(mixed $job)
 * @method static mixed getJobBackoff(mixed $job)
 * @method static mixed getJobExpiration(mixed $job)
 * @method static void createPayloadUsing(callable|null $callback)
 * @method static array getConfig()
 * @method static \Illuminate\Queue\Queue setConfig(array $config)
 * @method static \Illuminate\Container\Container getContainer()
 * @method static void setContainer(\Illuminate\Container\Container $container)
 * @method static \Illuminate\Support\Testing\Fakes\QueueFake except(array|string $jobsToBeQueued)
 * @method static void assertPushed(string|\Closure $job, callable|int|null $callback = null)
 * @method static void assertPushedTimes(string $job, int $times = 1)
 * @method static void assertPushedOn(\UnitEnum|string $queue, string|\Closure $job, callable|null $callback = null)
 * @method static void assertPushedWithChain(string $job, array $expectedChain = [], callable|null $callback = null)
 * @method static void assertPushedWithoutChain(string $job, callable|null $callback = null)
 * @method static void assertClosurePushed(callable|int|null $callback = null)
 * @method static void assertClosureNotPushed(callable|null $callback = null)
 * @method static void assertNotPushed(string|\Closure $job, callable|null $callback = null)
 * @method static void assertCount(int $expectedCount)
 * @method static void assertNothingPushed()
 * @method static \Illuminate\Support\Collection pushed(string $job, callable|null $callback = null)
 * @method static \Illuminate\Support\Collection pushedRaw(null|\Closure $callback = null)
 * @method static \Illuminate\Support\Collection listenersPushed(string $listenerClass, \Closure|null $callback = null)
 * @method static bool hasPushed(string $job)
 * @method static \Illuminate\Support\Collection pendingJobs(string|null $queue = null)
 * @method static \Illuminate\Support\Collection delayedJobs(string|null $queue = null)
 * @method static \Illuminate\Support\Collection reservedJobs(string|null $queue = null)
 * @method static \Illuminate\Support\Collection allPendingJobs()
 * @method static \Illuminate\Support\Collection allDelayedJobs()
 * @method static \Illuminate\Support\Collection allReservedJobs()
 * @method static bool shouldFakeJob(object $job)
 * @method static array pushedJobs()
 * @method static array rawPushes()
 * @method static \Illuminate\Support\Testing\Fakes\QueueFake serializeAndRestore(bool $serializeAndRestore = true)
 * @method static void releaseUniqueJobLocks()
 *
 * @see \Illuminate\Queue\QueueManager
 * @see \Illuminate\Queue\Queue
 * @see \Illuminate\Support\Testing\Fakes\QueueFake
 */
class Queue extends Facade
{
    /**
     * Register a callback to be executed to pick jobs.
     *
     * @param  string  $workerName
     * @param  callable  $callback
     * @return void
     */
    public static function popUsing($workerName, $callback)
    {
        Worker::popUsing($workerName, $callback);
    }

    /**
     * Replace the bound instance with a fake.
     *
     * @param  array|string  $jobsToFake
     * @return \Illuminate\Support\Testing\Fakes\QueueFake
     */
    public static function fake($jobsToFake = [])
    {
        $actualQueueManager = static::isFake()
            ? tap(static::getFacadeRoot(), fn ($fake) => $fake->releaseUniqueJobLocks())->queue
            : static::getFacadeRoot();

        return tap(new QueueFake(static::getFacadeApplication(), $jobsToFake, $actualQueueManager), function ($fake) {
            static::swap($fake);
        });
    }

    /**
     * Replace the bound instance with a fake that fakes all jobs except the given jobs.
     *
     * @param  string[]|string  $jobsToAllow
     * @return \Illuminate\Support\Testing\Fakes\QueueFake
     */
    public static function fakeExcept($jobsToAllow)
    {
        return static::fake()->except($jobsToAllow);
    }

    /**
     * Replace the bound instance with a fake during the given callable's execution.
     *
     * @param  callable  $callable
     * @param  array  $jobsToFake
     * @return mixed
     */
    public static function fakeFor(callable $callable, array $jobsToFake = [])
    {
        $originalQueueManager = static::getFacadeRoot();

        static::fake($jobsToFake);

        try {
            return $callable();
        } finally {
            static::swap($originalQueueManager);
        }
    }

    /**
     * Replace the bound instance with a fake during the given callable's execution.
     *
     * @param  callable  $callable
     * @param  array  $jobsToAllow
     * @return mixed
     */
    public static function fakeExceptFor(callable $callable, array $jobsToAllow = [])
    {
        $originalQueueManager = static::getFacadeRoot();

        static::fakeExcept($jobsToAllow);

        try {
            return $callable();
        } finally {
            static::swap($originalQueueManager);
        }
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'queue';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Foundation\MaintenanceModeManager;

/**
 * @method static string getDefaultDriver()
 * @method static mixed driver(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Foundation\MaintenanceModeManager extend(string $driver, \Closure $callback)
 * @method static array getDrivers()
 * @method static \Illuminate\Contracts\Container\Container getContainer()
 * @method static \Illuminate\Foundation\MaintenanceModeManager setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static \Illuminate\Foundation\MaintenanceModeManager forgetDrivers()
 *
 * @see \Illuminate\Foundation\MaintenanceModeManager
 */
class MaintenanceMode extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return MaintenanceModeManager::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Foundation\Configuration\ApplicationBuilder configure(string|null $basePath = null)
 * @method static string inferBasePath()
 * @method static string version()
 * @method static void bootstrapWith(string[] $bootstrappers)
 * @method static void afterLoadingEnvironment(\Closure $callback)
 * @method static void beforeBootstrapping(string $bootstrapper, \Closure $callback)
 * @method static void afterBootstrapping(string $bootstrapper, \Closure $callback)
 * @method static bool hasBeenBootstrapped()
 * @method static \Illuminate\Foundation\Application setBasePath(string $basePath)
 * @method static string path(string $path = '')
 * @method static \Illuminate\Foundation\Application useAppPath(string $path)
 * @method static string basePath(string $path = '')
 * @method static string bootstrapPath(string $path = '')
 * @method static string getBootstrapProvidersPath()
 * @method static \Illuminate\Foundation\Application useBootstrapPath(string $path)
 * @method static string configPath(string $path = '')
 * @method static \Illuminate\Foundation\Application useConfigPath(string $path)
 * @method static string databasePath(string $path = '')
 * @method static \Illuminate\Foundation\Application useDatabasePath(string $path)
 * @method static string langPath(string $path = '')
 * @method static \Illuminate\Foundation\Application useLangPath(string $path)
 * @method static string publicPath(string $path = '')
 * @method static \Illuminate\Foundation\Application usePublicPath(string $path)
 * @method static string storagePath(string $path = '')
 * @method static \Illuminate\Foundation\Application useStoragePath(string $path)
 * @method static string resourcePath(string $path = '')
 * @method static string viewPath(string $path = '')
 * @method static string joinPaths(string $basePath, string $path = '')
 * @method static string environmentPath()
 * @method static \Illuminate\Foundation\Application useEnvironmentPath(string $path)
 * @method static \Illuminate\Foundation\Application loadEnvironmentFrom(string $file)
 * @method static string environmentFile()
 * @method static string environmentFilePath()
 * @method static string|bool environment(string|array ...$environments)
 * @method static bool isLocal()
 * @method static bool isProduction()
 * @method static string detectEnvironment(\Closure $callback)
 * @method static bool runningInConsole()
 * @method static bool runningConsoleCommand(string|array ...$commands)
 * @method static bool runningUnitTests()
 * @method static bool hasDebugModeEnabled()
 * @method static void registered(callable $callback)
 * @method static void registerConfiguredProviders()
 * @method static \Illuminate\Support\ServiceProvider register(\Illuminate\Support\ServiceProvider|string $provider, bool $force = false)
 * @method static \Illuminate\Support\ServiceProvider|null getProvider(\Illuminate\Support\ServiceProvider|string $provider)
 * @method static array getProviders(\Illuminate\Support\ServiceProvider|string $provider)
 * @method static \Illuminate\Support\ServiceProvider resolveProvider(string $provider)
 * @method static void loadDeferredProviders()
 * @method static void loadDeferredProvider(string $service)
 * @method static void registerDeferredProvider(string $provider, string|null $service = null)
 * @method static object|mixed make(string $abstract, array $parameters = [])
 * @method static bool bound(string $abstract)
 * @method static bool isBooted()
 * @method static void boot()
 * @method static void booting(callable $callback)
 * @method static void booted(callable $callback)
 * @method static \Symfony\Component\HttpFoundation\Response handle(\Symfony\Component\HttpFoundation\Request $request, int $type = 1, bool $catch = true)
 * @method static void handleRequest(\Illuminate\Http\Request $request)
 * @method static int handleCommand(\Symfony\Component\Console\Input\InputInterface $input)
 * @method static bool shouldMergeFrameworkConfiguration()
 * @method static \Illuminate\Foundation\Application dontMergeFrameworkConfiguration()
 * @method static bool shouldSkipMiddleware()
 * @method static string getCachedServicesPath()
 * @method static string getCachedPackagesPath()
 * @method static bool configurationIsCached()
 * @method static string getCachedConfigPath()
 * @method static bool routesAreCached()
 * @method static string getCachedRoutesPath()
 * @method static bool eventsAreCached()
 * @method static string getCachedEventsPath()
 * @method static \Illuminate\Foundation\Application addAbsoluteCachePathPrefix(string $prefix)
 * @method static \Illuminate\Contracts\Foundation\MaintenanceMode maintenanceMode()
 * @method static bool isDownForMaintenance()
 * @method static never abort(int $code, string $message = '', array $headers = [])
 * @method static \Illuminate\Foundation\Application terminating(callable|string $callback)
 * @method static void terminate()
 * @method static array getLoadedProviders()
 * @method static bool providerIsLoaded(string $provider)
 * @method static array getDeferredServices()
 * @method static void setDeferredServices(array $services)
 * @method static bool isDeferredService(string $service)
 * @method static void addDeferredServices(array $services)
 * @method static void removeDeferredServices(array $services)
 * @method static void provideFacades(string $namespace)
 * @method static string getLocale()
 * @method static string currentLocale()
 * @method static string getFallbackLocale()
 * @method static void setLocale(string $locale)
 * @method static void setFallbackLocale(string $fallbackLocale)
 * @method static bool isLocale(string $locale)
 * @method static void registerCoreContainerAliases()
 * @method static void flush()
 * @method static string getNamespace()
 * @method static \Illuminate\Contracts\Container\ContextualBindingBuilder when(array|string $concrete)
 * @method static void whenHasAttribute(string $attribute, \Closure $handler)
 * @method static bool has(string $id)
 * @method static bool isShared(string $abstract)
 * @method static bool isAlias(string $name)
 * @method static void bind(\Closure|string $abstract, \Closure|string|null $concrete = null, bool $shared = false)
 * @method static bool hasMethodBinding(string $method)
 * @method static void bindMethod(array|string $method, \Closure $callback)
 * @method static mixed callMethodBinding(string $method, mixed $instance)
 * @method static void addContextualBinding(string $concrete, \Closure|string $abstract, \Closure|string $implementation)
 * @method static void bindIf(\Closure|string $abstract, \Closure|string|null $concrete = null, bool $shared = false)
 * @method static void singleton(\Closure|string $abstract, \Closure|string|null $concrete = null)
 * @method static void singletonIf(\Closure|string $abstract, \Closure|string|null $concrete = null)
 * @method static void scoped(\Closure|string $abstract, \Closure|string|null $concrete = null)
 * @method static void scopedIf(\Closure|string $abstract, \Closure|string|null $concrete = null)
 * @method static void extend(string $abstract, \Closure $closure)
 * @method static mixed instance(string $abstract, mixed $instance)
 * @method static void tag(array|string $abstracts, mixed $tags)
 * @method static iterable tagged(string $tag)
 * @method static void alias(string $abstract, string $alias)
 * @method static mixed rebinding(string $abstract, \Closure $callback)
 * @method static mixed refresh(string $abstract, mixed $target, string $method)
 * @method static \Closure wrap(\Closure $callback, array $parameters = [])
 * @method static mixed call(callable|string $callback, array $parameters = [], string|null $defaultMethod = null)
 * @method static \Closure|\Closure factory(string $abstract)
 * @method static object|mixed makeWith(string|callable $abstract, array $parameters = [])
 * @method static object|mixed get(string $id)
 * @method static object build(\Closure|string $concrete)
 * @method static mixed resolveFromAttribute(\ReflectionAttribute $attribute)
 * @method static void beforeResolving(\Closure|string $abstract, \Closure|null $callback = null)
 * @method static void resolving(\Closure|string $abstract, \Closure|null $callback = null)
 * @method static void afterResolving(\Closure|string $abstract, \Closure|null $callback = null)
 * @method static void afterResolvingAttribute(string $attribute, \Closure $callback)
 * @method static void fireAfterResolvingAttributeCallbacks(\ReflectionAttribute[] $attributes, mixed $object)
 * @method static string|null currentlyResolving()
 * @method static array getBindings()
 * @method static string getAlias(string $abstract)
 * @method static void forgetExtenders(string $abstract)
 * @method static void forgetInstance(string $abstract)
 * @method static void forgetInstances()
 * @method static void forgetScopedInstances()
 * @method static void resolveEnvironmentUsing(callable|string|null $callback)
 * @method static bool currentEnvironmentIs(array|string $environments)
 * @method static \Illuminate\Foundation\Application getInstance()
 * @method static \Illuminate\Contracts\Container\Container|\Illuminate\Foundation\Application setInstance(\Illuminate\Contracts\Container\Container|null $container = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Foundation\Application
 */
class App extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'app';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Support\DateFactory;

/**
 * @see https://carbon.nesbot.com/docs/
 * @see https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Factory.php
 *
 * @method static mixed use(mixed $handler)
 * @method static void useDefault()
 * @method static void useCallable(callable $callable)
 * @method static void useClass(string $dateClass)
 * @method static void useFactory(object $factory)
 * @method static bool canBeCreatedFromFormat(?string $date, string $format)
 * @method static \Illuminate\Support\Carbon|null create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null)
 * @method static \Illuminate\Support\Carbon createFromDate($year = null, $month = null, $day = null, $timezone = null)
 * @method static \Illuminate\Support\Carbon|null createFromFormat($format, $time, $timezone = null)
 * @method static \Illuminate\Support\Carbon|null createFromIsoFormat(string $format, string $time, $timezone = null, ?string $locale = 'en', ?\Symfony\Contracts\Translation\TranslatorInterface $translator = null)
 * @method static \Illuminate\Support\Carbon|null createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null)
 * @method static \Illuminate\Support\Carbon|null createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null)
 * @method static \Illuminate\Support\Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null)
 * @method static \Illuminate\Support\Carbon createFromTimeString(string $time, \DateTimeZone|string|int|null $timezone = null)
 * @method static \Illuminate\Support\Carbon createFromTimestamp(string|int|float $timestamp, \DateTimeZone|string|int|null $timezone = null)
 * @method static \Illuminate\Support\Carbon createFromTimestampMs(string|int|float $timestamp, \DateTimeZone|string|int|null $timezone = null)
 * @method static \Illuminate\Support\Carbon createFromTimestampMsUTC($timestamp)
 * @method static \Illuminate\Support\Carbon createFromTimestampUTC(string|int|float $timestamp)
 * @method static \Illuminate\Support\Carbon createMidnightDate($year = null, $month = null, $day = null, $timezone = null)
 * @method static \Illuminate\Support\Carbon|null createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null)
 * @method static \Illuminate\Support\Carbon createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null)
 * @method static void disableHumanDiffOption($humanDiffOption)
 * @method static void enableHumanDiffOption($humanDiffOption)
 * @method static mixed executeWithLocale(string $locale, callable $func)
 * @method static \Illuminate\Support\Carbon fromSerialized($value)
 * @method static array getAvailableLocales()
 * @method static array getAvailableLocalesInfo()
 * @method static array getDays()
 * @method static ?string getFallbackLocale()
 * @method static array getFormatsToIsoReplacements()
 * @method static int getHumanDiffOptions()
 * @method static array getIsoUnits()
 * @method static array|false getLastErrors()
 * @method static string getLocale()
 * @method static int getMidDayAt()
 * @method static string getTimeFormatByPrecision(string $unitPrecision)
 * @method static string|\Closure|null getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)
 * @method static \Illuminate\Support\Carbon|null getTestNow()
 * @method static \Symfony\Contracts\Translation\TranslatorInterface getTranslator()
 * @method static int getWeekEndsAt(?string $locale = null)
 * @method static int getWeekStartsAt(?string $locale = null)
 * @method static array getWeekendDays()
 * @method static bool hasFormat(string $date, string $format)
 * @method static bool hasFormatWithModifiers(string $date, string $format)
 * @method static bool hasMacro($name)
 * @method static bool hasRelativeKeywords(?string $time)
 * @method static bool hasTestNow()
 * @method static \Illuminate\Support\Carbon instance(\DateTimeInterface $date)
 * @method static bool isImmutable()
 * @method static bool isModifiableUnit($unit)
 * @method static bool isMutable()
 * @method static bool isStrictModeEnabled()
 * @method static bool localeHasDiffOneDayWords(string $locale)
 * @method static bool localeHasDiffSyntax(string $locale)
 * @method static bool localeHasDiffTwoDayWords(string $locale)
 * @method static bool localeHasPeriodSyntax($locale)
 * @method static bool localeHasShortUnits(string $locale)
 * @method static void macro(string $name, ?callable $macro)
 * @method static \Illuminate\Support\Carbon|null make($var, \DateTimeZone|string|null $timezone = null)
 * @method static void mixin(object|string $mixin)
 * @method static \Illuminate\Support\Carbon now(\DateTimeZone|string|int|null $timezone = null)
 * @method static \Illuminate\Support\Carbon parse(\DateTimeInterface|\Carbon\WeekDay|\Carbon\Month|string|int|float|null $time, \DateTimeZone|string|int|null $timezone = null)
 * @method static \Illuminate\Support\Carbon parseFromLocale(string $time, ?string $locale = null, \DateTimeZone|string|int|null $timezone = null)
 * @method static string pluralUnit(string $unit)
 * @method static \Illuminate\Support\Carbon|null rawCreateFromFormat(string $format, string $time, $timezone = null)
 * @method static \Illuminate\Support\Carbon rawParse(\DateTimeInterface|\Carbon\WeekDay|\Carbon\Month|string|int|float|null $time, \DateTimeZone|string|int|null $timezone = null)
 * @method static void resetMonthsOverflow()
 * @method static void resetToStringFormat()
 * @method static void resetYearsOverflow()
 * @method static void serializeUsing($callback)
 * @method static void setFallbackLocale(string $locale)
 * @method static void setHumanDiffOptions($humanDiffOptions)
 * @method static void setLocale(string $locale)
 * @method static void setMidDayAt($hour)
 * @method static void setTestNow(mixed $testNow = null)
 * @method static void setTestNowAndTimezone(mixed $testNow = null, $timezone = null)
 * @method static void setToStringFormat(string|\Closure|null $format)
 * @method static void setTranslator(\Symfony\Contracts\Translation\TranslatorInterface $translator)
 * @method static void setWeekEndsAt($day)
 * @method static void setWeekStartsAt($day)
 * @method static void setWeekendDays($days)
 * @method static bool shouldOverflowMonths()
 * @method static bool shouldOverflowYears()
 * @method static string singularUnit(string $unit)
 * @method static void sleep(int|float $seconds)
 * @method static \Illuminate\Support\Carbon today(\DateTimeZone|string|int|null $timezone = null)
 * @method static \Illuminate\Support\Carbon tomorrow(\DateTimeZone|string|int|null $timezone = null)
 * @method static string translateTimeString(string $timeString, ?string $from = null, ?string $to = null, int $mode = \Carbon\CarbonInterface::TRANSLATE_ALL)
 * @method static string translateWith(\Symfony\Contracts\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null)
 * @method static void useMonthsOverflow($monthsOverflow = true)
 * @method static void useStrictMode($strictModeEnabled = true)
 * @method static void useYearsOverflow($yearsOverflow = true)
 * @method static mixed withTestNow(mixed $testNow, callable $callback)
 * @method static static withTimeZone(\DateTimeZone|string|int|null $timezone)
 * @method static \Illuminate\Support\Carbon yesterday(\DateTimeZone|string|int|null $timezone = null)
 *
 * @see \Illuminate\Support\DateFactory
 */
class Date extends Facade
{
    const DEFAULT_FACADE = DateFactory::class;

    /**
     * Get the registered name of the component.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    protected static function getFacadeAccessor()
    {
        return 'date';
    }

    /**
     * Resolve the facade root instance from the container.
     *
     * @param  string  $name
     * @return mixed
     */
    protected static function resolveFacadeInstance($name)
    {
        if (! isset(static::$resolvedInstance[$name]) && ! isset(static::$app, static::$app[$name])) {
            $class = static::DEFAULT_FACADE;

            static::swap(new $class);
        }

        return parent::resolveFacadeInstance($name);
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static bool hasForLocale(string $key, string|null $locale = null)
 * @method static bool has(string $key, string|null $locale = null, bool $fallback = true)
 * @method static string|array get(string $key, array $replace = [], string|null $locale = null, bool $fallback = true)
 * @method static string choice(string $key, \Countable|int|float|array $number, array $replace = [], string|null $locale = null)
 * @method static void addLines(array $lines, string $locale, string $namespace = '*')
 * @method static void load(string $namespace, string $group, string $locale)
 * @method static \Illuminate\Translation\Translator handleMissingKeysUsing(callable|null $callback)
 * @method static void addNamespace(string $namespace, string $hint)
 * @method static void addPath(string $path)
 * @method static void addJsonPath(string $path)
 * @method static array parseKey(string $key)
 * @method static void determineLocalesUsing(callable $callback)
 * @method static \Illuminate\Translation\MessageSelector getSelector()
 * @method static void setSelector(\Illuminate\Translation\MessageSelector $selector)
 * @method static \Illuminate\Contracts\Translation\Loader getLoader()
 * @method static string locale()
 * @method static string getLocale()
 * @method static void setLocale(string $locale)
 * @method static string getFallback()
 * @method static void setFallback(string $fallback)
 * @method static void setLoaded(array $loaded)
 * @method static void stringable(callable|string $class, callable|null $handler = null)
 * @method static void setParsedKey(string $key, array $parsed)
 * @method static void flushParsedKeys()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Translation\Translator
 */
class Lang extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'translator';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Notifications\ChannelManager;
use Illuminate\Support\Testing\Fakes\NotificationFake;

/**
 * @method static void send(\Illuminate\Support\Collection|mixed $notifiables, mixed $notification)
 * @method static void sendNow(\Illuminate\Support\Collection|mixed $notifiables, mixed $notification, array|null $channels = null)
 * @method static mixed channel(\UnitEnum|string|null $name = null)
 * @method static mixed driver(\UnitEnum|string|null $driver = null)
 * @method static string getDefaultDriver()
 * @method static string deliversVia()
 * @method static void deliverVia(string $channel)
 * @method static \Illuminate\Notifications\ChannelManager locale(string $locale)
 * @method static \Illuminate\Notifications\ChannelManager extend(string $driver, \Closure $callback)
 * @method static array getDrivers()
 * @method static \Illuminate\Contracts\Container\Container getContainer()
 * @method static \Illuminate\Notifications\ChannelManager setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static \Illuminate\Notifications\ChannelManager forgetDrivers()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static string|null resolveConnectionFromQueueRoute(object $queueable)
 * @method static string|null resolveQueueFromQueueRoute(object $queueable)
 * @method static void assertSentOnDemand(string|\Closure $notification, callable|null $callback = null)
 * @method static void assertSentTo(mixed $notifiable, string|\Closure $notification, callable|null $callback = null)
 * @method static void assertSentOnDemandTimes(string $notification, int $times = 1)
 * @method static void assertSentToTimes(mixed $notifiable, string $notification, int $times = 1)
 * @method static void assertNotSentTo(mixed $notifiable, string|\Closure $notification, callable|null $callback = null)
 * @method static void assertNothingSent()
 * @method static void assertNothingSentTo(mixed $notifiable)
 * @method static void assertSentTimes(string $notification, int $expectedCount)
 * @method static void assertCount(int $expectedCount)
 * @method static \Illuminate\Support\Collection sent(mixed $notifiable, string $notification, callable|null $callback = null)
 * @method static bool hasSent(mixed $notifiable, string $notification)
 * @method static \Illuminate\Support\Testing\Fakes\NotificationFake serializeAndRestore(bool $serializeAndRestore = true)
 * @method static array sentNotifications()
 *
 * @see \Illuminate\Notifications\ChannelManager
 * @see \Illuminate\Support\Testing\Fakes\NotificationFake
 */
class Notification extends Facade
{
    /**
     * Replace the bound instance with a fake.
     *
     * @return \Illuminate\Support\Testing\Fakes\NotificationFake
     */
    public static function fake()
    {
        return tap(new NotificationFake, function ($fake) {
            static::swap($fake);
        });
    }

    /**
     * Begin sending a notification to an anonymous notifiable on the given channels.
     *
     * @param  array  $channels
     * @return \Illuminate\Notifications\AnonymousNotifiable
     */
    public static function routes(array $channels)
    {
        $notifiable = new AnonymousNotifiable;

        foreach ($channels as $channel => $route) {
            $notifiable->route($channel, $route);
        }

        return $notifiable;
    }

    /**
     * Begin sending a notification to an anonymous notifiable.
     *
     * @param  string  $channel
     * @param  mixed  $route
     * @return \Illuminate\Notifications\AnonymousNotifiable
     */
    public static function route($channel, $route)
    {
        return (new AnonymousNotifiable)->route($channel, $route);
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return ChannelManager::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Filesystem\Filesystem;

use function Illuminate\Support\enum_value;

/**
 * @method static \Illuminate\Contracts\Filesystem\Filesystem drive(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Contracts\Filesystem\Filesystem disk(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Contracts\Filesystem\Cloud cloud()
 * @method static \Illuminate\Contracts\Filesystem\Filesystem build(string|array $config)
 * @method static \Illuminate\Contracts\Filesystem\Filesystem createLocalDriver(array $config, string $name = 'local')
 * @method static \Illuminate\Contracts\Filesystem\Filesystem createFtpDriver(array $config)
 * @method static \Illuminate\Contracts\Filesystem\Filesystem createSftpDriver(array $config)
 * @method static \Illuminate\Contracts\Filesystem\Cloud createS3Driver(array $config)
 * @method static \Illuminate\Contracts\Filesystem\Filesystem createScopedDriver(array $config)
 * @method static \Illuminate\Filesystem\FilesystemManager set(string $name, mixed $disk)
 * @method static string getDefaultDriver()
 * @method static string getDefaultCloudDriver()
 * @method static \Illuminate\Filesystem\FilesystemManager forgetDisk(array|string $disk)
 * @method static void purge(string|null $name = null)
 * @method static \Illuminate\Filesystem\FilesystemManager extend(string $driver, \Closure $callback)
 * @method static \Illuminate\Filesystem\FilesystemManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static string path(string $path)
 * @method static bool exists(string $path)
 * @method static string|null get(string $path)
 * @method static resource|null readStream(string $path)
 * @method static bool put(string $path, \Psr\Http\Message\StreamInterface|\Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|resource $contents, mixed $options = [])
 * @method static string|false putFile(\Illuminate\Http\File|\Illuminate\Http\UploadedFile|string $path, \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|array|null $file = null, mixed $options = [])
 * @method static string|false putFileAs(\Illuminate\Http\File|\Illuminate\Http\UploadedFile|string $path, \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|array|null $file, string|array|null $name = null, mixed $options = [])
 * @method static bool writeStream(string $path, resource $resource, array $options = [])
 * @method static string getVisibility(string $path)
 * @method static bool setVisibility(string $path, string $visibility)
 * @method static bool prepend(string $path, string $data)
 * @method static bool append(string $path, string $data)
 * @method static bool delete(string|array $paths)
 * @method static bool copy(string $from, string $to)
 * @method static bool move(string $from, string $to)
 * @method static int size(string $path)
 * @method static int lastModified(string $path)
 * @method static array files(string|null $directory = null, bool $recursive = false)
 * @method static array allFiles(string|null $directory = null)
 * @method static array directories(string|null $directory = null, bool $recursive = false)
 * @method static array allDirectories(string|null $directory = null)
 * @method static bool makeDirectory(string $path)
 * @method static bool deleteDirectory(string $directory)
 * @method static \Illuminate\Filesystem\FilesystemAdapter assertExists(string|array $path, string|null $content = null)
 * @method static \Illuminate\Filesystem\FilesystemAdapter assertCount(string $path, int $count, bool $recursive = false)
 * @method static \Illuminate\Filesystem\FilesystemAdapter assertMissing(string|array $path)
 * @method static \Illuminate\Filesystem\FilesystemAdapter assertDirectoryEmpty(string $path)
 * @method static bool missing(string $path)
 * @method static bool fileExists(string $path)
 * @method static bool fileMissing(string $path)
 * @method static bool directoryExists(string $path)
 * @method static bool directoryMissing(string $path)
 * @method static array|null json(string $path, int $flags = 0)
 * @method static \Symfony\Component\HttpFoundation\StreamedResponse response(string $path, string|null $name = null, array $headers = [], string|null $disposition = 'inline')
 * @method static \Symfony\Component\HttpFoundation\StreamedResponse serve(\Illuminate\Http\Request $request, string $path, string|null $name = null, array $headers = [])
 * @method static \Symfony\Component\HttpFoundation\StreamedResponse download(string $path, string|null $name = null, array $headers = [])
 * @method static string|false checksum(string $path, array $options = [])
 * @method static string|false mimeType(string $path)
 * @method static string url(string $path)
 * @method static bool providesTemporaryUrls()
 * @method static bool providesTemporaryUploadUrls()
 * @method static string temporaryUrl(string $path, \DateTimeInterface $expiration, array $options = [])
 * @method static array temporaryUploadUrl(string $path, \DateTimeInterface $expiration, array $options = [])
 * @method static \League\Flysystem\FilesystemOperator getDriver()
 * @method static \League\Flysystem\FilesystemAdapter getAdapter()
 * @method static array getConfig()
 * @method static void serveUsing(\Closure $callback)
 * @method static void buildTemporaryUrlsUsing(\Closure $callback)
 * @method static void buildTemporaryUploadUrlsUsing(\Closure $callback)
 * @method static \Illuminate\Filesystem\FilesystemAdapter|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Filesystem\FilesystemAdapter|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static bool has(string $location)
 * @method static string read(string $location)
 * @method static \League\Flysystem\DirectoryListing listContents(string $location, bool $deep = false)
 * @method static int fileSize(string $path)
 * @method static string visibility(string $path)
 * @method static void write(string $location, string $contents, array $config = [])
 * @method static void createDirectory(string $location, array $config = [])
 *
 * @see \Illuminate\Filesystem\FilesystemManager
 */
class Storage extends Facade
{
    /**
     * Replace the given disk with a local testing disk.
     *
     * @param  \UnitEnum|string|null  $disk
     * @param  array  $config
     * @return \Illuminate\Filesystem\LocalFilesystemAdapter
     */
    public static function fake($disk = null, array $config = [])
    {
        $root = self::getRootPath($disk = enum_value($disk) ?: static::$app['config']->get('filesystems.default'));

        if ($token = ParallelTesting::token()) {
            $root = "{$root}_test_{$token}";
        }

        (new Filesystem)->cleanDirectory($root);

        static::set($disk, $fake = static::createLocalDriver(
            self::buildDiskConfiguration($disk, $config, root: $root)
        ));

        return tap($fake, function ($fake) {
            $fake->buildTemporaryUrlsUsing(function ($path, $expiration) {
                return URL::to($path.'?expiration='.$expiration->getTimestamp());
            });

            $fake->buildTemporaryUploadUrlsUsing(function ($path, $expiration) {
                return ['url' => URL::to($path.'?expiration='.$expiration->getTimestamp()), 'headers' => []];
            });
        });
    }

    /**
     * Replace the given disk with a persistent local testing disk.
     *
     * @param  \UnitEnum|string|null  $disk
     * @param  array  $config
     * @return \Illuminate\Filesystem\LocalFilesystemAdapter
     */
    public static function persistentFake($disk = null, array $config = [])
    {
        $disk = enum_value($disk) ?: static::$app['config']->get('filesystems.default');

        static::set($disk, $fake = static::createLocalDriver(
            self::buildDiskConfiguration($disk, $config, root: self::getRootPath($disk))
        ));

        return $fake;
    }

    /**
     * Get the root path of the given disk.
     *
     * @param  string  $disk
     * @return string
     */
    protected static function getRootPath(string $disk): string
    {
        return storage_path('framework/testing/disks/'.$disk);
    }

    /**
     * Assemble the configuration of the given disk.
     *
     * @param  string  $disk
     * @param  array  $config
     * @param  string  $root
     * @return array
     */
    protected static function buildDiskConfiguration(string $disk, array $config, string $root): array
    {
        $originalConfig = static::$app['config']["filesystems.disks.{$disk}"] ?? [];

        return array_merge([
            'throw' => $originalConfig['throw'] ?? false],
            $config,
            ['root' => $root]
        );
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'filesystem';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static bool has(string $key)
 * @method static mixed get(array|string $key, mixed $default = null)
 * @method static array getMany(array $keys)
 * @method static string string(string $key, \Closure|string|null $default = null)
 * @method static int integer(string $key, \Closure|int|null $default = null)
 * @method static float float(string $key, \Closure|float|null $default = null)
 * @method static bool boolean(string $key, \Closure|bool|null $default = null)
 * @method static array array(string $key, \Closure|array|null $default = null)
 * @method static \Illuminate\Support\Collection collection(string $key, \Closure|array|null $default = null)
 * @method static void set(array|string $key, mixed $value = null)
 * @method static void prepend(string $key, mixed $value)
 * @method static void push(string $key, mixed $value)
 * @method static array all()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Config\Repository
 */
class Config extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'config';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;

/**
 * @method static bool has(\UnitEnum|array|string $ability)
 * @method static \Illuminate\Auth\Access\Response allowIf(\Illuminate\Auth\Access\Response|\Closure|bool $condition, string|null $message = null, string|null $code = null)
 * @method static \Illuminate\Auth\Access\Response denyIf(\Illuminate\Auth\Access\Response|\Closure|bool $condition, string|null $message = null, string|null $code = null)
 * @method static \Illuminate\Auth\Access\Gate define(\UnitEnum|string $ability, callable|array|string $callback)
 * @method static \Illuminate\Auth\Access\Gate resource(string $name, string $class, array|null $abilities = null)
 * @method static \Illuminate\Auth\Access\Gate policy(string $class, string $policy)
 * @method static \Illuminate\Auth\Access\Gate before(callable $callback)
 * @method static \Illuminate\Auth\Access\Gate after(callable $callback)
 * @method static bool allows(iterable|\UnitEnum|string $ability, mixed $arguments = [])
 * @method static bool denies(iterable|\UnitEnum|string $ability, mixed $arguments = [])
 * @method static bool check(iterable|\UnitEnum|string $abilities, mixed $arguments = [])
 * @method static bool any(iterable|\UnitEnum|string $abilities, mixed $arguments = [])
 * @method static bool none(iterable|\UnitEnum|string $abilities, mixed $arguments = [])
 * @method static \Illuminate\Auth\Access\Response authorize(\UnitEnum|string $ability, mixed $arguments = [])
 * @method static \Illuminate\Auth\Access\Response inspect(\UnitEnum|string $ability, mixed $arguments = [])
 * @method static mixed raw(string $ability, mixed $arguments = [])
 * @method static mixed getPolicyFor(object|string $class)
 * @method static \Illuminate\Auth\Access\Gate guessPolicyNamesUsing(callable $callback)
 * @method static mixed resolvePolicy(object|string $class)
 * @method static \Illuminate\Auth\Access\Gate forUser(\Illuminate\Contracts\Auth\Authenticatable|mixed $user)
 * @method static array abilities()
 * @method static array policies()
 * @method static \Illuminate\Auth\Access\Gate defaultDenialResponse(\Illuminate\Auth\Access\Response $response)
 * @method static \Illuminate\Auth\Access\Gate setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static \Illuminate\Auth\Access\Response denyWithStatus(int $status, string|null $message = null, int|null $code = null)
 * @method static \Illuminate\Auth\Access\Response denyAsNotFound(string|null $message = null, int|null $code = null)
 *
 * @see \Illuminate\Auth\Access\Gate
 */
class Gate extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return GateContract::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Bus\BatchRepository;
use Illuminate\Contracts\Bus\Dispatcher as BusDispatcherContract;
use Illuminate\Foundation\Bus\PendingChain;
use Illuminate\Support\Testing\Fakes\BusFake;

/**
 * @method static mixed dispatch(mixed $command)
 * @method static mixed dispatchSync(mixed $command, mixed $handler = null)
 * @method static mixed dispatchNow(mixed $command, mixed $handler = null)
 * @method static \Illuminate\Bus\Batch|null findBatch(string $batchId)
 * @method static \Illuminate\Bus\PendingBatch batch(\Illuminate\Support\Collection|mixed $jobs)
 * @method static \Illuminate\Foundation\Bus\PendingChain chain(\Illuminate\Support\Collection|array|null $jobs = null)
 * @method static bool hasCommandHandler(mixed $command)
 * @method static mixed getCommandHandler(mixed $command)
 * @method static mixed dispatchToQueue(mixed $command)
 * @method static void dispatchAfterResponse(mixed $command, mixed $handler = null)
 * @method static \Illuminate\Bus\Dispatcher pipeThrough(array $pipes)
 * @method static \Illuminate\Bus\Dispatcher map(array $map)
 * @method static \Illuminate\Bus\Dispatcher withDispatchingAfterResponses()
 * @method static \Illuminate\Bus\Dispatcher withoutDispatchingAfterResponses()
 * @method static string|null resolveConnectionFromQueueRoute(object $queueable)
 * @method static string|null resolveQueueFromQueueRoute(object $queueable)
 * @method static \Illuminate\Support\Testing\Fakes\BusFake except(array|string $jobsToDispatch)
 * @method static void assertDispatched(string|\Closure $command, callable|int|null $callback = null)
 * @method static void assertDispatchedOnce(string|\Closure $command)
 * @method static void assertDispatchedTimes(string|\Closure $command, int $times = 1)
 * @method static void assertNotDispatched(string|\Closure $command, callable|null $callback = null)
 * @method static void assertNothingDispatched()
 * @method static void assertDispatchedSync(string|\Closure $command, callable|int|null $callback = null)
 * @method static void assertDispatchedSyncTimes(string|\Closure $command, int $times = 1)
 * @method static void assertNotDispatchedSync(string|\Closure $command, callable|null $callback = null)
 * @method static void assertDispatchedAfterResponse(string|\Closure $command, callable|int|null $callback = null)
 * @method static void assertDispatchedAfterResponseTimes(string|\Closure $command, int $times = 1)
 * @method static void assertNotDispatchedAfterResponse(string|\Closure $command, callable|null $callback = null)
 * @method static void assertChained(array $expectedChain)
 * @method static void assertNothingChained()
 * @method static void assertDispatchedWithoutChain(string|\Closure $command, callable|null $callback = null)
 * @method static \Illuminate\Support\Testing\Fakes\ChainedBatchTruthTest chainedBatch(\Closure $callback)
 * @method static void assertBatched(array|callable $callback)
 * @method static void assertBatchCount(int $count)
 * @method static void assertNothingBatched()
 * @method static void assertNothingPlaced()
 * @method static \Illuminate\Support\Collection dispatched(string $command, callable|null $callback = null)
 * @method static \Illuminate\Support\Collection dispatchedSync(string $command, callable|null $callback = null)
 * @method static \Illuminate\Support\Collection dispatchedAfterResponse(string $command, callable|null $callback = null)
 * @method static \Illuminate\Support\Collection batched(callable $callback)
 * @method static bool hasDispatched(string $command)
 * @method static bool hasDispatchedSync(string $command)
 * @method static bool hasDispatchedAfterResponse(string $command)
 * @method static \Illuminate\Bus\Batch dispatchFakeBatch(string $name = '')
 * @method static \Illuminate\Bus\Batch recordPendingBatch(\Illuminate\Bus\PendingBatch $pendingBatch)
 * @method static \Illuminate\Support\Testing\Fakes\BusFake serializeAndRestore(bool $serializeAndRestore = true)
 * @method static array dispatchedBatches()
 *
 * @see \Illuminate\Bus\Dispatcher
 * @see \Illuminate\Support\Testing\Fakes\BusFake
 */
class Bus extends Facade
{
    /**
     * Replace the bound instance with a fake.
     *
     * @param  array|string  $jobsToFake
     * @param  \Illuminate\Bus\BatchRepository|null  $batchRepository
     * @return \Illuminate\Support\Testing\Fakes\BusFake
     */
    public static function fake($jobsToFake = [], ?BatchRepository $batchRepository = null)
    {
        $actualDispatcher = static::isFake()
            ? static::getFacadeRoot()->dispatcher
            : static::getFacadeRoot();

        return tap(new BusFake($actualDispatcher, $jobsToFake, $batchRepository), function ($fake) {
            static::swap($fake);
        });
    }

    /**
     * Dispatch the given chain of jobs.
     *
     * @param  mixed  $jobs
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public static function dispatchChain($jobs)
    {
        $jobs = is_array($jobs) ? $jobs : func_get_args();

        return (new PendingChain(array_shift($jobs), $jobs))
            ->dispatch();
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return BusDispatcherContract::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Contracts\Auth\PasswordBroker;

/**
 * @method static \Illuminate\Contracts\Auth\PasswordBroker broker(\UnitEnum|string|null $name = null)
 * @method static string getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static string sendResetLink(array $credentials, \Closure|null $callback = null)
 * @method static mixed reset(array $credentials, \Closure $callback)
 * @method static \Illuminate\Contracts\Auth\CanResetPassword|null getUser(array $credentials)
 * @method static string createToken(\Illuminate\Contracts\Auth\CanResetPassword $user)
 * @method static void deleteToken(\Illuminate\Contracts\Auth\CanResetPassword $user)
 * @method static bool tokenExists(\Illuminate\Contracts\Auth\CanResetPassword $user, string $token)
 * @method static \Illuminate\Auth\Passwords\TokenRepositoryInterface getRepository()
 * @method static \Illuminate\Support\Timebox getTimebox()
 *
 * @see \Illuminate\Auth\Passwords\PasswordBrokerManager
 * @see \Illuminate\Auth\Passwords\PasswordBroker
 */
class Password extends Facade
{
    /**
     * Constant representing a successfully sent password reset email.
     *
     * @var string
     */
    const ResetLinkSent = PasswordBroker::RESET_LINK_SENT;

    /**
     * Constant representing a successfully reset password.
     *
     * @var string
     */
    const PasswordReset = PasswordBroker::PASSWORD_RESET;

    /**
     * Constant indicating the user could not be found when attempting a password reset.
     *
     * @var string
     */
    const InvalidUser = PasswordBroker::INVALID_USER;

    /**
     * Constant representing an invalid password reset token.
     *
     * @var string
     */
    const InvalidToken = PasswordBroker::INVALID_TOKEN;

    /**
     * Constant representing a throttled password reset attempt.
     *
     * @var string
     */
    const ResetThrottled = PasswordBroker::RESET_THROTTLED;

    const RESET_LINK_SENT = PasswordBroker::RESET_LINK_SENT;
    const PASSWORD_RESET = PasswordBroker::PASSWORD_RESET;
    const INVALID_USER = PasswordBroker::INVALID_USER;
    const INVALID_TOKEN = PasswordBroker::INVALID_TOKEN;
    const RESET_THROTTLED = PasswordBroker::RESET_THROTTLED;

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'auth.password';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Contracts\View\View file(string $path, \Illuminate\Contracts\Support\Arrayable|array $data = [], array $mergeData = [])
 * @method static \Illuminate\Contracts\View\View make(string $view, \Illuminate\Contracts\Support\Arrayable|array $data = [], array $mergeData = [])
 * @method static \Illuminate\Contracts\View\View first(array $views, \Illuminate\Contracts\Support\Arrayable|array $data = [], array $mergeData = [])
 * @method static string renderWhen(bool $condition, string $view, \Illuminate\Contracts\Support\Arrayable|array $data = [], array $mergeData = [])
 * @method static string renderUnless(bool $condition, string $view, \Illuminate\Contracts\Support\Arrayable|array $data = [], array $mergeData = [])
 * @method static string renderEach(string $view, array $data, string $iterator, string $empty = 'raw|')
 * @method static bool exists(string $view)
 * @method static \Illuminate\Contracts\View\Engine getEngineFromPath(string $path)
 * @method static mixed share(array|string $key, mixed $value = null)
 * @method static void incrementRender()
 * @method static void decrementRender()
 * @method static bool doneRendering()
 * @method static bool hasRenderedOnce(string $id)
 * @method static void markAsRenderedOnce(string $id)
 * @method static void addLocation(string $location)
 * @method static void prependLocation(string $location)
 * @method static \Illuminate\View\Factory addNamespace(string $namespace, string|array $hints)
 * @method static \Illuminate\View\Factory prependNamespace(string $namespace, string|array $hints)
 * @method static \Illuminate\View\Factory replaceNamespace(string $namespace, string|array $hints)
 * @method static void addExtension(string $extension, string $engine, \Closure|null $resolver = null)
 * @method static void flushState()
 * @method static void flushStateIfDoneRendering()
 * @method static array getExtensions()
 * @method static \Illuminate\View\Engines\EngineResolver getEngineResolver()
 * @method static \Illuminate\View\ViewFinderInterface getFinder()
 * @method static void setFinder(\Illuminate\View\ViewFinderInterface $finder)
 * @method static void flushFinderCache()
 * @method static \Illuminate\Contracts\Events\Dispatcher getDispatcher()
 * @method static void setDispatcher(\Illuminate\Contracts\Events\Dispatcher $events)
 * @method static \Illuminate\Contracts\Container\Container getContainer()
 * @method static void setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static mixed shared(string $key, mixed $default = null)
 * @method static array getShared()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static void startComponent(\Illuminate\Contracts\View\View|\Illuminate\Contracts\Support\Htmlable|\Closure|string $view, array $data = [])
 * @method static void startComponentFirst(array $names, array $data = [])
 * @method static string renderComponent()
 * @method static mixed getConsumableComponentData(string $key, mixed $default = null)
 * @method static void slot(string $name, string|null $content = null, array $attributes = [])
 * @method static void endSlot()
 * @method static array creator(array|string $views, \Closure|string $callback)
 * @method static array composers(array $composers)
 * @method static array composer(array|string $views, \Closure|string $callback)
 * @method static void callComposer(\Illuminate\Contracts\View\View $view)
 * @method static void callCreator(\Illuminate\Contracts\View\View $view)
 * @method static void startFragment(string $fragment)
 * @method static string stopFragment()
 * @method static mixed getFragment(string $name, string|null $default = null)
 * @method static array getFragments()
 * @method static void flushFragments()
 * @method static void startSection(string $section, string|null $content = null)
 * @method static void inject(string $section, string $content)
 * @method static string yieldSection()
 * @method static string stopSection(bool $overwrite = false)
 * @method static string appendSection()
 * @method static string yieldContent(string $section, string $default = '')
 * @method static string parentPlaceholder(string $section = '')
 * @method static bool hasSection(string $name)
 * @method static bool sectionMissing(string $name)
 * @method static mixed getSection(string $name, string|null $default = null)
 * @method static array getSections()
 * @method static void flushSections()
 * @method static void addLoop(\Countable|array $data)
 * @method static void incrementLoopIndices()
 * @method static void popLoop()
 * @method static \stdClass|null getLastLoop()
 * @method static array getLoopStack()
 * @method static void startPush(string $section, string $content = '')
 * @method static string stopPush()
 * @method static void startPrepend(string $section, string $content = '')
 * @method static string stopPrepend()
 * @method static string yieldPushContent(string $section, string $default = '')
 * @method static bool isStackEmpty(string $section)
 * @method static void flushStacks()
 * @method static void startTranslation(array $replacements = [])
 * @method static string renderTranslation()
 *
 * @see \Illuminate\View\Factory
 */
class View extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'view';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Symfony\Component\HttpFoundation\Cookie make(string $name, string $value, int $minutes = 0, string|null $path = null, string|null $domain = null, bool|null $secure = null, bool $httpOnly = true, bool $raw = false, string|null $sameSite = null)
 * @method static \Symfony\Component\HttpFoundation\Cookie forever(string $name, string $value, string|null $path = null, string|null $domain = null, bool|null $secure = null, bool $httpOnly = true, bool $raw = false, string|null $sameSite = null)
 * @method static \Symfony\Component\HttpFoundation\Cookie forget(string $name, string|null $path = null, string|null $domain = null)
 * @method static bool hasQueued(string $key, string|null $path = null)
 * @method static \Symfony\Component\HttpFoundation\Cookie|null queued(string $key, mixed $default = null, string|null $path = null)
 * @method static void queue(mixed ...$parameters)
 * @method static void expire(string $name, string|null $path = null, string|null $domain = null)
 * @method static void unqueue(string $name, string|null $path = null)
 * @method static \Illuminate\Cookie\CookieJar setDefaultPathAndDomain(string $path, string|null $domain, bool|null $secure = false, string|null $sameSite = null)
 * @method static \Symfony\Component\HttpFoundation\Cookie[] getQueuedCookies()
 * @method static \Illuminate\Cookie\CookieJar flushQueuedCookies()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Cookie\CookieJar
 */
class Cookie extends Facade
{
    /**
     * Determine if a cookie exists on the request.
     *
     * @param  string  $key
     * @return bool
     */
    public static function has($key)
    {
        return ! is_null(static::$app['request']->cookie($key, null));
    }

    /**
     * Retrieve a cookie from the request.
     *
     * @param  string|null  $key
     * @param  mixed  $default
     * @return string|array|null
     */
    public static function get($key = null, $default = null)
    {
        return static::$app['request']->cookie($key, $default);
    }

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'cookie';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static void compile(string|null $path = null)
 * @method static string getPath()
 * @method static void setPath(string $path)
 * @method static string compileString(string $value)
 * @method static string render(string $string, array $data = [], bool $deleteCachedView = false)
 * @method static string renderComponent(\Illuminate\View\Component $component)
 * @method static string stripParentheses(string $expression)
 * @method static void extend(callable $compiler)
 * @method static array getExtensions()
 * @method static void if(string $name, callable $callback)
 * @method static bool check(string $name, mixed ...$parameters)
 * @method static void component(string $class, string|null $alias = null, string $prefix = '')
 * @method static void components(array $components, string $prefix = '')
 * @method static array getClassComponentAliases()
 * @method static void anonymousComponentPath(string $path, string|null $prefix = null)
 * @method static void anonymousComponentNamespace(string $directory, string|null $prefix = null)
 * @method static void componentNamespace(string $namespace, string $prefix)
 * @method static array getAnonymousComponentPaths()
 * @method static array getAnonymousComponentNamespaces()
 * @method static array getClassComponentNamespaces()
 * @method static void aliasComponent(string $path, string|null $alias = null)
 * @method static void include(string $path, string|null $alias = null)
 * @method static void aliasInclude(string $path, string|null $alias = null)
 * @method static void bindDirective(string $name, callable $handler)
 * @method static void directive(string $name, \Closure|callable $handler, bool $bind = false)
 * @method static array getCustomDirectives()
 * @method static \Illuminate\View\Compilers\BladeCompiler prepareStringsForCompilationUsing(callable $callback)
 * @method static void precompiler(callable $precompiler)
 * @method static string usingEchoFormat(string $format, callable $callback)
 * @method static void setEchoFormat(string $format)
 * @method static void withDoubleEncoding()
 * @method static void withoutDoubleEncoding()
 * @method static void withoutComponentTags()
 * @method static string getCompiledPath(string $path)
 * @method static bool isExpired(string $path)
 * @method static string newComponentHash(string $component)
 * @method static string compileClassComponentOpening(string $component, string $alias, string $data, string $hash)
 * @method static string compileEndComponentClass()
 * @method static mixed sanitizeComponentAttribute(mixed $value)
 * @method static string compileEndOnce()
 * @method static void stringable(string|callable $class, callable|null $handler = null)
 * @method static string compileEchos(string $value)
 * @method static string applyEchoHandler(string $value)
 *
 * @see \Illuminate\View\Compilers\BladeCompiler
 */
class Blade extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'blade.compiler';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static string full()
 * @method static string current()
 * @method static string previous(mixed $fallback = false)
 * @method static string previousPath(mixed $fallback = false)
 * @method static string to(string $path, mixed $extra = [], bool|null $secure = null)
 * @method static string query(string $path, array $query = [], mixed $extra = [], bool|null $secure = null)
 * @method static string secure(string $path, array $parameters = [])
 * @method static string asset(string $path, bool|null $secure = null)
 * @method static string secureAsset(string $path)
 * @method static string assetFrom(string $root, string $path, bool|null $secure = null)
 * @method static string formatScheme(bool|null $secure = null)
 * @method static string signedRoute(\BackedEnum|string $name, mixed $parameters = [], \DateTimeInterface|\DateInterval|int|null $expiration = null, bool $absolute = true)
 * @method static string temporarySignedRoute(\BackedEnum|string $name, \DateTimeInterface|\DateInterval|int $expiration, array $parameters = [], bool $absolute = true)
 * @method static bool hasValidSignature(\Illuminate\Http\Request $request, bool $absolute = true, \Closure|array $ignoreQuery = [])
 * @method static bool hasValidRelativeSignature(\Illuminate\Http\Request $request, \Closure|array $ignoreQuery = [])
 * @method static bool hasCorrectSignature(\Illuminate\Http\Request $request, bool $absolute = true, \Closure|array $ignoreQuery = [])
 * @method static bool signatureHasNotExpired(\Illuminate\Http\Request $request)
 * @method static string route(\BackedEnum|string $name, mixed $parameters = [], bool $absolute = true)
 * @method static string toRoute(\Illuminate\Routing\Route $route, mixed $parameters, bool $absolute)
 * @method static string action(string|array $action, mixed $parameters = [], bool $absolute = true)
 * @method static array formatParameters(mixed $parameters)
 * @method static string formatRoot(string $scheme, string|null $root = null)
 * @method static string format(string $root, string $path, \Illuminate\Routing\Route|null $route = null)
 * @method static bool isValidUrl(string $path)
 * @method static void defaults(array $defaults)
 * @method static array getDefaultParameters()
 * @method static void forceScheme(string|null $scheme)
 * @method static void forceHttps(bool $force = true)
 * @method static void useOrigin(string|null $root)
 * @method static void useAssetOrigin(string|null $root)
 * @method static \Illuminate\Routing\UrlGenerator formatHostUsing(\Closure $callback)
 * @method static \Illuminate\Routing\UrlGenerator formatPathUsing(\Closure $callback)
 * @method static \Closure pathFormatter()
 * @method static \Illuminate\Http\Request getRequest()
 * @method static void setRequest(\Illuminate\Http\Request $request)
 * @method static \Illuminate\Routing\UrlGenerator setRoutes(\Illuminate\Routing\RouteCollectionInterface $routes)
 * @method static \Illuminate\Routing\UrlGenerator setSessionResolver(callable $sessionResolver)
 * @method static \Illuminate\Routing\UrlGenerator setKeyResolver(callable $keyResolver)
 * @method static \Illuminate\Routing\UrlGenerator withKeyResolver(callable $keyResolver)
 * @method static \Illuminate\Routing\UrlGenerator resolveMissingNamedRoutesUsing(callable $missingNamedRouteResolver)
 * @method static string getRootControllerNamespace()
 * @method static \Illuminate\Routing\UrlGenerator setRootControllerNamespace(string $rootNamespace)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Routing\UrlGenerator
 */
class URL extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'url';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Http\RedirectResponse back(int $status = 302, array $headers = [], mixed $fallback = false)
 * @method static \Illuminate\Http\RedirectResponse refresh(int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse guest(string $path, int $status = 302, array $headers = [], bool|null $secure = null)
 * @method static \Illuminate\Http\RedirectResponse intended(mixed $default = '/', int $status = 302, array $headers = [], bool|null $secure = null)
 * @method static \Illuminate\Http\RedirectResponse to(string $path, int $status = 302, array $headers = [], bool|null $secure = null)
 * @method static \Illuminate\Http\RedirectResponse away(string $path, int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse secure(string $path, int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse route(\BackedEnum|string $route, mixed $parameters = [], int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse signedRoute(\BackedEnum|string $route, mixed $parameters = [], \DateTimeInterface|\DateInterval|int|null $expiration = null, int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse temporarySignedRoute(\BackedEnum|string $route, \DateTimeInterface|\DateInterval|int|null $expiration, mixed $parameters = [], int $status = 302, array $headers = [])
 * @method static \Illuminate\Http\RedirectResponse action(string|array $action, mixed $parameters = [], int $status = 302, array $headers = [])
 * @method static \Illuminate\Routing\UrlGenerator getUrlGenerator()
 * @method static void setSession(\Illuminate\Session\Store $session)
 * @method static string|null getIntendedUrl()
 * @method static \Illuminate\Routing\Redirector setIntendedUrl(string $url)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Routing\Redirector
 */
class Redirect extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'redirect';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static bool exists(string $path)
 * @method static bool missing(string $path)
 * @method static string get(string $path, bool $lock = false)
 * @method static array json(string $path, int $flags = 0, bool $lock = false)
 * @method static string sharedGet(string $path)
 * @method static mixed getRequire(string $path, array $data = [])
 * @method static mixed requireOnce(string $path, array $data = [])
 * @method static \Illuminate\Support\LazyCollection lines(string $path)
 * @method static string|false hash(string $path, string $algorithm = 'md5')
 * @method static int|bool put(string $path, string $contents, bool $lock = false)
 * @method static void replace(string $path, string $content, int|null $mode = null)
 * @method static void replaceInFile(array|string $search, array|string $replace, string $path)
 * @method static int prepend(string $path, string $data)
 * @method static int append(string $path, string $data, bool $lock = false)
 * @method static mixed chmod(string $path, int|null $mode = null)
 * @method static bool delete(string|array $paths)
 * @method static bool move(string $path, string $target)
 * @method static bool copy(string $path, string $target)
 * @method static bool|null link(string $target, string $link)
 * @method static void relativeLink(string $target, string $link)
 * @method static string name(string $path)
 * @method static string basename(string $path)
 * @method static string dirname(string $path)
 * @method static string extension(string $path)
 * @method static string|null guessExtension(string $path)
 * @method static string|false type(string $path)
 * @method static string|false mimeType(string $path)
 * @method static int size(string $path)
 * @method static int lastModified(string $path)
 * @method static bool isDirectory(string $directory)
 * @method static bool isEmptyDirectory(string $directory, bool $ignoreDotFiles = false)
 * @method static bool isReadable(string $path)
 * @method static bool isWritable(string $path)
 * @method static bool hasSameHash(string $firstFile, string $secondFile)
 * @method static bool isFile(string $file)
 * @method static array glob(string $pattern, int $flags = 0)
 * @method static \Symfony\Component\Finder\SplFileInfo[] files(string $directory, bool $hidden = false, array|string|int $depth = 0)
 * @method static \Symfony\Component\Finder\SplFileInfo[] allFiles(string $directory, bool $hidden = false)
 * @method static array directories(string $directory, array|string|int $depth = 0)
 * @method static array allDirectories(string $directory)
 * @method static void ensureDirectoryExists(string $path, int $mode = 0755, bool $recursive = true)
 * @method static bool makeDirectory(string $path, int $mode = 0755, bool $recursive = false, bool $force = false)
 * @method static bool moveDirectory(string $from, string $to, bool $overwrite = false)
 * @method static bool copyDirectory(string $directory, string $destination, int|null $options = null)
 * @method static bool deleteDirectory(string $directory, bool $preserve = false)
 * @method static bool deleteDirectories(string $directory)
 * @method static bool cleanDirectory(string $directory)
 * @method static \Illuminate\Filesystem\Filesystem|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Filesystem\Filesystem|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Filesystem\Filesystem
 */
class File extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'files';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Cache\RateLimiter for(\UnitEnum|string $name, \Closure $callback)
 * @method static \Closure|null limiter(\UnitEnum|string $name)
 * @method static mixed attempt(string $key, int $maxAttempts, \Closure $callback, \DateTimeInterface|\DateInterval|int $decaySeconds = 60)
 * @method static bool tooManyAttempts(string $key, int $maxAttempts)
 * @method static int hit(string $key, \DateTimeInterface|\DateInterval|int $decaySeconds = 60)
 * @method static int increment(string $key, \DateTimeInterface|\DateInterval|int $decaySeconds = 60, int $amount = 1)
 * @method static int decrement(string $key, \DateTimeInterface|\DateInterval|int $decaySeconds = 60, int $amount = 1)
 * @method static mixed attempts(string $key)
 * @method static bool resetAttempts(string $key)
 * @method static int remaining(string $key, int $maxAttempts)
 * @method static int retriesLeft(string $key, int $maxAttempts)
 * @method static void clear(string $key)
 * @method static int availableIn(string $key)
 * @method static string cleanRateLimiterKey(string $key)
 *
 * @see \Illuminate\Cache\RateLimiter
 */
class RateLimiter extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return \Illuminate\Cache\RateLimiter::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Hashing\BcryptHasher createBcryptDriver()
 * @method static \Illuminate\Hashing\ArgonHasher createArgonDriver()
 * @method static \Illuminate\Hashing\Argon2IdHasher createArgon2idDriver()
 * @method static array info(string $hashedValue)
 * @method static string make(string $value, array $options = [])
 * @method static bool check(string $value, string $hashedValue, array $options = [])
 * @method static bool needsRehash(string $hashedValue, array $options = [])
 * @method static bool isHashed(string $value)
 * @method static string getDefaultDriver()
 * @method static mixed driver(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Hashing\HashManager extend(string $driver, \Closure $callback)
 * @method static array getDrivers()
 * @method static \Illuminate\Contracts\Container\Container getContainer()
 * @method static \Illuminate\Hashing\HashManager setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static \Illuminate\Hashing\HashManager forgetDrivers()
 *
 * @see \Illuminate\Hashing\HashManager
 * @see \Illuminate\Hashing\AbstractHasher
 */
class Hash extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'hash';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Contracts\Broadcasting\Factory as BroadcastingFactoryContract;

/**
 * @method static void routes(array|null $attributes = null)
 * @method static void userRoutes(array|null $attributes = null)
 * @method static void channelRoutes(array|null $attributes = null)
 * @method static string|null socket(\Illuminate\Http\Request|null $request = null)
 * @method static \Illuminate\Broadcasting\AnonymousEvent on(\Illuminate\Broadcasting\Channel|array|string $channels)
 * @method static \Illuminate\Broadcasting\AnonymousEvent private(string $channel)
 * @method static \Illuminate\Broadcasting\AnonymousEvent presence(string $channel)
 * @method static \Illuminate\Broadcasting\PendingBroadcast event(mixed $event = null)
 * @method static void queue(mixed $event)
 * @method static mixed connection(\UnitEnum|string|null $name = null)
 * @method static mixed driver(\UnitEnum|string|null $name = null)
 * @method static \Pusher\Pusher pusher(array $config)
 * @method static \Ably\AblyRest ably(array $config)
 * @method static string getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static void purge(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Broadcasting\BroadcastManager extend(string $driver, \Closure $callback)
 * @method static \Illuminate\Contracts\Foundation\Application getApplication()
 * @method static \Illuminate\Broadcasting\BroadcastManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static \Illuminate\Broadcasting\BroadcastManager forgetDrivers()
 * @method static string|null resolveConnectionFromQueueRoute(object $queueable)
 * @method static string|null resolveQueueFromQueueRoute(object $queueable)
 * @method static mixed auth(\Illuminate\Http\Request $request)
 * @method static mixed validAuthenticationResponse(\Illuminate\Http\Request $request, mixed $result)
 * @method static void broadcast(array $channels, string $event, array $payload = [])
 * @method static array|null resolveAuthenticatedUser(\Illuminate\Http\Request $request)
 * @method static void resolveAuthenticatedUserUsing(\Closure $callback)
 * @method static \Illuminate\Broadcasting\Broadcasters\Broadcaster channel(\Illuminate\Contracts\Broadcasting\HasBroadcastChannel|string $channel, callable|string $callback, array $options = [])
 * @method static \Illuminate\Support\Collection getChannels()
 *
 * @see \Illuminate\Broadcasting\BroadcastManager
 * @see \Illuminate\Broadcasting\Broadcasters\Broadcaster
 */
class Broadcast extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return BroadcastingFactoryContract::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Http\Client\Factory;

/**
 * @method static \Illuminate\Http\Client\Factory globalMiddleware(callable $middleware)
 * @method static \Illuminate\Http\Client\Factory globalRequestMiddleware(callable $middleware)
 * @method static \Illuminate\Http\Client\Factory globalResponseMiddleware(callable $middleware)
 * @method static \Illuminate\Http\Client\Factory globalOptions(\Closure|array $options)
 * @method static \GuzzleHttp\Promise\PromiseInterface response(array|string|null $body = null, int $status = 200, array $headers = [])
 * @method static \GuzzleHttp\Psr7\Response psr7Response(array|string|null $body = null, int $status = 200, array $headers = [])
 * @method static \Illuminate\Http\Client\RequestException failedRequest(array|string|null $body = null, int $status = 200, array $headers = [])
 * @method static \Closure failedConnection(string|null $message = null)
 * @method static \Illuminate\Http\Client\ResponseSequence sequence(array $responses = [])
 * @method static bool preventingStrayRequests()
 * @method static \Illuminate\Http\Client\Factory allowStrayRequests(array|null $only = null)
 * @method static \Illuminate\Http\Client\Factory record()
 * @method static void recordRequestResponsePair(\Illuminate\Http\Client\Request $request, \Illuminate\Http\Client\Response|null $response)
 * @method static void assertSent(callable|\Closure $callback)
 * @method static void assertSentInOrder(array $callbacks)
 * @method static void assertNotSent(callable|\Closure $callback)
 * @method static void assertNothingSent()
 * @method static void assertSentCount(int $count)
 * @method static void assertSequencesAreEmpty()
 * @method static \Illuminate\Support\Collection recorded(\Closure|callable $callback = null)
 * @method static \Illuminate\Http\Client\PendingRequest createPendingRequest()
 * @method static \Illuminate\Contracts\Events\Dispatcher|null getDispatcher()
 * @method static array getGlobalMiddleware()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static \Illuminate\Http\Client\PendingRequest baseUrl(string $url)
 * @method static \Illuminate\Http\Client\PendingRequest withBody(\Psr\Http\Message\StreamInterface|string $content, string $contentType = 'application/json')
 * @method static \Illuminate\Http\Client\PendingRequest asJson()
 * @method static \Illuminate\Http\Client\PendingRequest asForm()
 * @method static \Illuminate\Http\Client\PendingRequest attach(string|array $name, string|resource $contents = '', string|null $filename = null, array $headers = [])
 * @method static \Illuminate\Http\Client\PendingRequest asMultipart()
 * @method static \Illuminate\Http\Client\PendingRequest bodyFormat(string $format)
 * @method static \Illuminate\Http\Client\PendingRequest withQueryParameters(array $parameters)
 * @method static \Illuminate\Http\Client\PendingRequest contentType(string $contentType)
 * @method static \Illuminate\Http\Client\PendingRequest acceptJson()
 * @method static \Illuminate\Http\Client\PendingRequest accept(string $contentType)
 * @method static \Illuminate\Http\Client\PendingRequest withHeaders(array $headers)
 * @method static \Illuminate\Http\Client\PendingRequest withHeader(string $name, mixed $value)
 * @method static \Illuminate\Http\Client\PendingRequest replaceHeaders(array $headers)
 * @method static \Illuminate\Http\Client\PendingRequest withBasicAuth(string $username, string $password)
 * @method static \Illuminate\Http\Client\PendingRequest withDigestAuth(string $username, string $password)
 * @method static \Illuminate\Http\Client\PendingRequest withNtlmAuth(string $username, string $password)
 * @method static \Illuminate\Http\Client\PendingRequest withToken(string $token, string $type = 'Bearer')
 * @method static \Illuminate\Http\Client\PendingRequest withUserAgent(string|bool $userAgent)
 * @method static \Illuminate\Http\Client\PendingRequest withUrlParameters(array $parameters = [])
 * @method static \Illuminate\Http\Client\PendingRequest withCookies(array $cookies, string $domain)
 * @method static \Illuminate\Http\Client\PendingRequest maxRedirects(int $max)
 * @method static \Illuminate\Http\Client\PendingRequest withoutRedirecting()
 * @method static \Illuminate\Http\Client\PendingRequest withoutVerifying()
 * @method static \Illuminate\Http\Client\PendingRequest sink(string|resource $to)
 * @method static \Illuminate\Http\Client\PendingRequest timeout(int|float $seconds)
 * @method static \Illuminate\Http\Client\PendingRequest connectTimeout(int|float $seconds)
 * @method static \Illuminate\Http\Client\PendingRequest retry(array|int $times, \Closure|int $sleepMilliseconds = 0, callable|null $when = null, bool $throw = true)
 * @method static \Illuminate\Http\Client\PendingRequest withOptions(array $options)
 * @method static \Illuminate\Http\Client\PendingRequest withMiddleware(callable $middleware)
 * @method static \Illuminate\Http\Client\PendingRequest withRequestMiddleware(callable $middleware)
 * @method static \Illuminate\Http\Client\PendingRequest withResponseMiddleware(callable $middleware)
 * @method static \Illuminate\Http\Client\PendingRequest withAttributes(array $attributes)
 * @method static \Illuminate\Http\Client\PendingRequest beforeSending(callable $callback)
 * @method static \Illuminate\Http\Client\PendingRequest afterResponse(callable|null $callback)
 * @method static \Illuminate\Http\Client\PendingRequest throw(callable|null $callback = null)
 * @method static \Illuminate\Http\Client\PendingRequest throwIf(callable|bool $condition)
 * @method static \Illuminate\Http\Client\PendingRequest throwUnless(callable|bool $condition)
 * @method static \Illuminate\Http\Client\PendingRequest dump()
 * @method static \Illuminate\Http\Client\PendingRequest dd()
 * @method static \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface get(string $url, array|string|null $query = null)
 * @method static \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface head(string $url, array|string|null $query = null)
 * @method static \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface post(string $url, array|\JsonSerializable|\Illuminate\Contracts\Support\Arrayable $data = [])
 * @method static \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface patch(string $url, array|\JsonSerializable|\Illuminate\Contracts\Support\Arrayable $data = [])
 * @method static \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface put(string $url, array|\JsonSerializable|\Illuminate\Contracts\Support\Arrayable $data = [])
 * @method static \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface delete(string $url, array|\JsonSerializable|\Illuminate\Contracts\Support\Arrayable $data = [])
 * @method static array pool(callable $callback, int|null $concurrency = 0)
 * @method static \Illuminate\Http\Client\Batch batch(callable $callback)
 * @method static \Illuminate\Http\Client\Response|\Illuminate\Http\Client\Promises\LazyPromise send(string $method, string $url, array $options = [])
 * @method static \GuzzleHttp\Client buildClient()
 * @method static \GuzzleHttp\Client createClient(\GuzzleHttp\HandlerStack $handlerStack)
 * @method static \GuzzleHttp\HandlerStack buildHandlerStack()
 * @method static \GuzzleHttp\HandlerStack pushHandlers(\GuzzleHttp\HandlerStack $handlerStack)
 * @method static \Closure buildBeforeSendingHandler()
 * @method static \Closure buildRecorderHandler()
 * @method static \Closure buildStubHandler()
 * @method static \Psr\Http\Message\RequestInterface runBeforeSendingCallbacks(\Psr\Http\Message\RequestInterface $request, array $options)
 * @method static array mergeOptions(array ...$options)
 * @method static \Illuminate\Http\Client\PendingRequest stub(callable $callback)
 * @method static bool isAllowedRequestUrl(string $url)
 * @method static \Illuminate\Http\Client\PendingRequest async(bool $async = true)
 * @method static \GuzzleHttp\Promise\PromiseInterface|null getPromise()
 * @method static \Illuminate\Http\Client\PendingRequest truncateExceptionsAt(int $length)
 * @method static \Illuminate\Http\Client\PendingRequest dontTruncateExceptions()
 * @method static \Illuminate\Http\Client\PendingRequest setClient(\GuzzleHttp\Client $client)
 * @method static \Illuminate\Http\Client\PendingRequest setHandler(callable $handler)
 * @method static array getOptions()
 * @method static \Illuminate\Http\Client\PendingRequest|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Http\Client\PendingRequest|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 *
 * @see \Illuminate\Http\Client\Factory
 */
class Http extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return Factory::class;
    }

    /**
     * Register a stub callable that will intercept requests and be able to return stub responses.
     *
     * @param  \Closure|array|null  $callback
     * @return \Illuminate\Http\Client\Factory
     */
    public static function fake($callback = null)
    {
        return tap(static::getFacadeRoot(), function ($fake) use ($callback) {
            static::swap($fake->fake($callback));
        });
    }

    /**
     * Register a response sequence for the given URL pattern.
     *
     * @param  string  $urlPattern
     * @return \Illuminate\Http\Client\ResponseSequence
     */
    public static function fakeSequence(string $urlPattern = '*')
    {
        $fake = tap(static::getFacadeRoot(), function ($fake) {
            static::swap($fake);
        });

        return $fake->fakeSequence($urlPattern);
    }

    /**
     * Indicate that an exception should be thrown if any request is not faked.
     *
     * @param  bool  $prevent
     * @return \Illuminate\Http\Client\Factory
     */
    public static function preventStrayRequests($prevent = true)
    {
        return tap(static::getFacadeRoot(), function ($fake) use ($prevent) {
            static::swap($fake->preventStrayRequests($prevent));
        });
    }

    /**
     * Stub the given URL using the given callback.
     *
     * @param  string  $url
     * @param  \Illuminate\Http\Client\Response|\GuzzleHttp\Promise\PromiseInterface|callable  $callback
     * @return \Illuminate\Http\Client\Factory
     */
    public static function stubUrl($url, $callback)
    {
        return tap(static::getFacadeRoot(), function ($fake) use ($url, $callback) {
            static::swap($fake->stubUrl($url, $callback));
        });
    }
}
<?php

namespace Illuminate\Support\Facades;

use Closure;
use Illuminate\Process\Factory;

/**
 * @method static \Illuminate\Process\PendingProcess command(array|string $command)
 * @method static \Illuminate\Process\PendingProcess path(string $path)
 * @method static \Illuminate\Process\PendingProcess timeout(\Carbon\CarbonInterval|int $timeout)
 * @method static \Illuminate\Process\PendingProcess idleTimeout(\Carbon\CarbonInterval|int $timeout)
 * @method static \Illuminate\Process\PendingProcess forever()
 * @method static \Illuminate\Process\PendingProcess env(array $environment)
 * @method static \Illuminate\Process\PendingProcess input(\Traversable|resource|string|int|float|bool|null $input)
 * @method static \Illuminate\Process\PendingProcess quietly()
 * @method static \Illuminate\Process\PendingProcess tty(bool $tty = true)
 * @method static \Illuminate\Process\PendingProcess options(array $options)
 * @method static \Illuminate\Contracts\Process\ProcessResult run(array|string|null $command = null, callable|null $output = null)
 * @method static \Illuminate\Process\InvokedProcess start(array|string|null $command = null, callable|null $output = null)
 * @method static bool supportsTty()
 * @method static \Illuminate\Process\PendingProcess withFakeHandlers(array $fakeHandlers)
 * @method static \Illuminate\Process\PendingProcess|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Process\PendingProcess|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Process\FakeProcessResult result(array|string $output = '', array|string $errorOutput = '', int $exitCode = 0)
 * @method static \Illuminate\Process\FakeProcessDescription describe()
 * @method static \Illuminate\Process\FakeProcessSequence sequence(array $processes = [])
 * @method static bool isRecording()
 * @method static \Illuminate\Process\Factory recordIfRecording(\Illuminate\Process\PendingProcess $process, \Illuminate\Contracts\Process\ProcessResult $result)
 * @method static \Illuminate\Process\Factory record(\Illuminate\Process\PendingProcess $process, \Illuminate\Contracts\Process\ProcessResult $result)
 * @method static \Illuminate\Process\Factory preventStrayProcesses(bool $prevent = true)
 * @method static bool preventingStrayProcesses()
 * @method static \Illuminate\Process\Factory assertRan(\Closure|string $callback)
 * @method static \Illuminate\Process\Factory assertRanTimes(\Closure|string $callback, int $times = 1)
 * @method static \Illuminate\Process\Factory assertNotRan(\Closure|string $callback)
 * @method static \Illuminate\Process\Factory assertDidntRun(\Closure|string $callback)
 * @method static \Illuminate\Process\Factory assertNothingRan()
 * @method static \Illuminate\Process\Pool pool(callable $callback)
 * @method static \Illuminate\Contracts\Process\ProcessResult pipe(callable|array $callback, callable|null $output = null)
 * @method static \Illuminate\Process\ProcessPoolResults concurrently(callable $callback, callable|null $output = null)
 * @method static \Illuminate\Process\PendingProcess newPendingProcess()
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 *
 * @see \Illuminate\Process\PendingProcess
 * @see \Illuminate\Process\Factory
 */
class Process extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return Factory::class;
    }

    /**
     * Indicate that the process factory should fake processes.
     *
     * @param  \Closure|array|null  $callback
     * @return \Illuminate\Process\Factory
     */
    public static function fake(Closure|array|null $callback = null)
    {
        return tap(static::getFacadeRoot(), function ($fake) use ($callback) {
            static::swap($fake->fake($callback));
        });
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Redis\Connections\Connection connection(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Redis\Connections\Connection resolve(string|null $name = null)
 * @method static array connections()
 * @method static void enableEvents()
 * @method static void disableEvents()
 * @method static void setDriver(string $driver)
 * @method static void purge(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Redis\RedisManager extend(string $driver, \Closure $callback)
 * @method static void createSubscription(array|string $channels, \Closure $callback, string $method = 'subscribe')
 * @method static \Illuminate\Redis\Limiters\ConcurrencyLimiterBuilder funnel(string $name)
 * @method static \Illuminate\Redis\Limiters\DurationLimiterBuilder throttle(string $name)
 * @method static mixed client()
 * @method static void subscribe(array|string $channels, \Closure $callback)
 * @method static void psubscribe(array|string $channels, \Closure $callback)
 * @method static mixed command(string $method, array $parameters = [])
 * @method static void listen(\Closure $callback)
 * @method static void listenForFailures(\Closure $callback)
 * @method static bool isCluster()
 * @method static string|null getName()
 * @method static \Illuminate\Redis\Connections\Connection setName(string $name)
 * @method static \Illuminate\Contracts\Events\Dispatcher|null getEventDispatcher()
 * @method static void setEventDispatcher(\Illuminate\Contracts\Events\Dispatcher $events)
 * @method static void unsetEventDispatcher()
 * @method static bool hasHashTag(string $key)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 * @method static mixed macroCall(string $method, array $parameters)
 * @method static string _compress(string $value)
 * @method static string _uncompress(string $value)
 * @method static string _prefix(string $key)
 * @method static string _serialize(mixed $value)
 * @method static mixed _unserialize(string $value)
 * @method static string _pack(mixed $value)
 * @method static mixed _unpack(string $value)
 * @method static mixed acl(string $subcmd, string ...$args)
 * @method static \Redis|int|false append(string $key, mixed $value)
 * @method static \Redis|bool auth(mixed $credentials)
 * @method static \Redis|bool bgSave()
 * @method static \Redis|bool bgrewriteaof()
 * @method static \Redis|array|false waitaof(int $numlocal, int $numreplicas, int $timeout)
 * @method static \Redis|int|false bitcount(string $key, int $start = 0, int $end = -1, bool $bybit = false)
 * @method static \Redis|int|false bitop(string $operation, string $deskey, string $srckey, string ...$other_keys)
 * @method static \Redis|int|false bitpos(string $key, bool $bit, int $start = 0, int $end = -1, bool $bybit = false)
 * @method static \Redis|array|false|null blPop(array|string $key_or_keys, string|int|float $timeout_or_key, mixed ...$extra_args)
 * @method static \Redis|array|false|null brPop(array|string $key_or_keys, string|int|float $timeout_or_key, mixed ...$extra_args)
 * @method static \Redis|string|false brpoplpush(string $src, string $dst, int|float $timeout)
 * @method static \Redis|array|false bzPopMax(array|string $key, string|int $timeout_or_key, mixed ...$extra_args)
 * @method static \Redis|array|false bzPopMin(array|string $key, string|int $timeout_or_key, mixed ...$extra_args)
 * @method static \Redis|array|false|null bzmpop(float $timeout, array $keys, string $from, int $count = 1)
 * @method static \Redis|array|false|null zmpop(array $keys, string $from, int $count = 1)
 * @method static \Redis|array|false|null blmpop(float $timeout, array $keys, string $from, int $count = 1)
 * @method static \Redis|array|false|null lmpop(array $keys, string $from, int $count = 1)
 * @method static bool clearLastError()
 * @method static bool close()
 * @method static mixed config(string $operation, array|string|null $key_or_settings = null, string|null $value = null)
 * @method static bool connect(string $host, int $port = 6379, float $timeout = 0, string|null $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, array|null $context = null)
 * @method static \Redis|bool copy(string $src, string $dst, array|null $options = null)
 * @method static \Redis|int|false dbSize()
 * @method static \Redis|string debug(string $key)
 * @method static \Redis|int|false decr(string $key, int $by = 1)
 * @method static \Redis|int|false decrBy(string $key, int $value)
 * @method static \Redis|int|false del(array|string $key, string ...$other_keys)
 * @method static \Redis|int|false delifeq(string $key, mixed $value)
 * @method static \Redis|bool discard()
 * @method static \Redis|string|false dump(string $key)
 * @method static \Redis|string|false echo(string $str)
 * @method static mixed eval(string $script, array $args = [], int $num_keys = 0)
 * @method static mixed eval_ro(string $script_sha, array $args = [], int $num_keys = 0)
 * @method static mixed evalsha(string $sha1, array $args = [], int $num_keys = 0)
 * @method static mixed evalsha_ro(string $sha1, array $args = [], int $num_keys = 0)
 * @method static \Redis|array|false exec()
 * @method static \Redis|int|bool exists(mixed $key, mixed ...$other_keys)
 * @method static \Redis|bool expire(string $key, int $timeout, string|null $mode = null)
 * @method static \Redis|bool expireAt(string $key, int $timestamp, string|null $mode = null)
 * @method static \Redis|bool failover(array|null $to = null, bool $abort = false, int $timeout = 0)
 * @method static \Redis|int|false expiretime(string $key)
 * @method static \Redis|int|false pexpiretime(string $key)
 * @method static mixed fcall(string $fn, array $keys = [], array $args = [])
 * @method static mixed fcall_ro(string $fn, array $keys = [], array $args = [])
 * @method static \Redis|bool flushAll(bool|null $sync = null)
 * @method static \Redis|bool flushDB(bool|null $sync = null)
 * @method static \Redis|array|string|bool function(string $operation, mixed ...$args)
 * @method static \Redis|int|false geoadd(string $key, float $lng, float $lat, string $member, mixed ...$other_triples_and_options)
 * @method static \Redis|float|false geodist(string $key, string $src, string $dst, string|null $unit = null)
 * @method static \Redis|array|false geohash(string $key, string $member, string ...$other_members)
 * @method static \Redis|array|false geopos(string $key, string $member, string ...$other_members)
 * @method static mixed georadius(string $key, float $lng, float $lat, float $radius, string $unit, array $options = [])
 * @method static mixed georadius_ro(string $key, float $lng, float $lat, float $radius, string $unit, array $options = [])
 * @method static mixed georadiusbymember(string $key, string $member, float $radius, string $unit, array $options = [])
 * @method static mixed georadiusbymember_ro(string $key, string $member, float $radius, string $unit, array $options = [])
 * @method static array geosearch(string $key, array|string $position, array|int|float $shape, string $unit, array $options = [])
 * @method static \Redis|array|int|false geosearchstore(string $dst, string $src, array|string $position, array|int|float $shape, string $unit, array $options = [])
 * @method static mixed get(string $key)
 * @method static \Redis|array|false getWithMeta(string $key)
 * @method static mixed getAuth()
 * @method static \Redis|int|false getBit(string $key, int $idx)
 * @method static \Redis|string|bool getEx(string $key, array $options = [])
 * @method static int getDBNum()
 * @method static \Redis|string|bool getDel(string $key)
 * @method static string getHost()
 * @method static string|null getLastError()
 * @method static int getMode()
 * @method static mixed getOption(int $option)
 * @method static string|null getPersistentID()
 * @method static int getPort()
 * @method static string|false serverName()
 * @method static string|false serverVersion()
 * @method static \Redis|string|false getRange(string $key, int $start, int $end)
 * @method static \Redis|array|string|int|false lcs(string $key1, string $key2, array|null $options = null)
 * @method static float getReadTimeout()
 * @method static \Redis|string|false getset(string $key, mixed $value)
 * @method static float|false getTimeout()
 * @method static array getTransferredBytes()
 * @method static void clearTransferredBytes()
 * @method static \Redis|int|false hDel(string $key, string $field, string ...$other_fields)
 * @method static \Redis|bool hExists(string $key, string $field)
 * @method static mixed hGet(string $key, string $member)
 * @method static \Redis|array|false hGetAll(string $key)
 * @method static mixed hGetWithMeta(string $key, string $member)
 * @method static \Redis|int|false hIncrBy(string $key, string $field, int $value)
 * @method static \Redis|float|false hIncrByFloat(string $key, string $field, float $value)
 * @method static \Redis|array|false hKeys(string $key)
 * @method static \Redis|int|false hLen(string $key)
 * @method static \Redis|array|false hMget(string $key, array $fields)
 * @method static \Redis|array|false hgetex(string $key, array $fields, array|string|null $expiry = null)
 * @method static \Redis|int|false hsetex(string $key, array $fields, array|null $expiry = null)
 * @method static \Redis|array|false hgetdel(string $key, array $fields)
 * @method static \Redis|bool hMset(string $key, array $fieldvals)
 * @method static \Redis|array|string|false hRandField(string $key, array|null $options = null)
 * @method static \Redis|int|false hSet(string $key, mixed ...$fields_and_vals)
 * @method static \Redis|bool hSetNx(string $key, string $field, mixed $value)
 * @method static \Redis|int|false hStrLen(string $key, string $field)
 * @method static \Redis|array|false hVals(string $key)
 * @method static \Redis|array|false hexpire(string $key, int $ttl, array $fields, string|null $mode = null)
 * @method static \Redis|array|false hpexpire(string $key, int $ttl, array $fields, string|null $mode = null)
 * @method static \Redis|array|false hexpireat(string $key, int $time, array $fields, string|null $mode = null)
 * @method static \Redis|array|false hpexpireat(string $key, int $mstime, array $fields, string|null $mode = null)
 * @method static \Redis|array|false httl(string $key, array $fields)
 * @method static \Redis|array|false hpttl(string $key, array $fields)
 * @method static \Redis|array|false hexpiretime(string $key, array $fields)
 * @method static \Redis|array|false hpexpiretime(string $key, array $fields)
 * @method static \Redis|array|false hpersist(string $key, array $fields)
 * @method static \Redis|array|bool hscan(string $key, string|int|null $iterator, string|null $pattern = null, int $count = 0)
 * @method static \Redis|int|false expiremember(string $key, string $field, int $ttl, string|null $unit = null)
 * @method static \Redis|int|false expirememberat(string $key, string $field, int $timestamp)
 * @method static \Redis|int|false incr(string $key, int $by = 1)
 * @method static \Redis|int|false incrBy(string $key, int $value)
 * @method static \Redis|float|false incrByFloat(string $key, float $value)
 * @method static \Redis|array|false info(string ...$sections)
 * @method static bool isConnected()
 * @method static void keys(string $pattern)
 * @method static void lInsert(string $key, string $pos, mixed $pivot, mixed $value)
 * @method static \Redis|int|false lLen(string $key)
 * @method static \Redis|string|false lMove(string $src, string $dst, string $wherefrom, string $whereto)
 * @method static \Redis|string|false blmove(string $src, string $dst, string $wherefrom, string $whereto, float $timeout)
 * @method static \Redis|array|string|bool lPop(string $key, int $count = 0)
 * @method static \Redis|array|int|bool|null lPos(string $key, mixed $value, array|null $options = null)
 * @method static \Redis|int|false lPush(string $key, mixed ...$elements)
 * @method static \Redis|int|false rPush(string $key, mixed ...$elements)
 * @method static \Redis|int|false lPushx(string $key, mixed $value)
 * @method static \Redis|int|false rPushx(string $key, mixed $value)
 * @method static \Redis|bool lSet(string $key, int $index, mixed $value)
 * @method static int lastSave()
 * @method static mixed lindex(string $key, int $index)
 * @method static \Redis|array|false lrange(string $key, int $start, int $end)
 * @method static \Redis|int|false lrem(string $key, mixed $value, int $count = 0)
 * @method static \Redis|bool ltrim(string $key, int $start, int $end)
 * @method static \Redis|array|false mget(array $keys)
 * @method static \Redis|bool migrate(string $host, int $port, array|string $key, int $dstdb, int $timeout, bool $copy = false, bool $replace = false, mixed $credentials = null)
 * @method static \Redis|bool move(string $key, int $index)
 * @method static \Redis|bool mset(array $key_values)
 * @method static \Redis|bool msetnx(array $key_values)
 * @method static \Redis|bool multi(int $value = 1)
 * @method static \Redis|string|int|false object(string $subcommand, string $key)
 * @method static bool pconnect(string $host, int $port = 6379, float $timeout = 0, string|null $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, array|null $context = null)
 * @method static \Redis|bool persist(string $key)
 * @method static bool pexpire(string $key, int $timeout, string|null $mode = null)
 * @method static \Redis|bool pexpireAt(string $key, int $timestamp, string|null $mode = null)
 * @method static \Redis|int pfadd(string $key, array $elements)
 * @method static \Redis|int|false pfcount(array|string $key_or_keys)
 * @method static \Redis|bool pfmerge(string $dst, array $srckeys)
 * @method static \Redis|string|bool ping(string|null $message = null)
 * @method static \Redis|bool pipeline()
 * @method static \Redis|bool psetex(string $key, int $expire, mixed $value)
 * @method static \Redis|int|false pttl(string $key)
 * @method static \Redis|int|false publish(string $channel, string $message)
 * @method static mixed pubsub(string $command, mixed $arg = null)
 * @method static \Redis|array|bool punsubscribe(array $patterns)
 * @method static \Redis|array|string|bool rPop(string $key, int $count = 0)
 * @method static \Redis|string|false randomKey()
 * @method static mixed rawcommand(string $command, mixed ...$args)
 * @method static \Redis|bool rename(string $old_name, string $new_name)
 * @method static \Redis|bool renameNx(string $key_src, string $key_dst)
 * @method static \Redis|bool reset()
 * @method static \Redis|bool restore(string $key, int $ttl, string $value, array|null $options = null)
 * @method static mixed role()
 * @method static \Redis|string|false rpoplpush(string $srckey, string $dstkey)
 * @method static \Redis|int|false sAdd(string $key, mixed $value, mixed ...$other_values)
 * @method static int sAddArray(string $key, array $values)
 * @method static \Redis|array|false sDiff(string $key, string ...$other_keys)
 * @method static \Redis|int|false sDiffStore(string $dst, string $key, string ...$other_keys)
 * @method static \Redis|array|false sInter(array|string $key, string ...$other_keys)
 * @method static \Redis|int|false sintercard(array $keys, int $limit = -1)
 * @method static \Redis|int|false sInterStore(array|string $key, string ...$other_keys)
 * @method static \Redis|array|false sMembers(string $key)
 * @method static \Redis|array|false sMisMember(string $key, string $member, string ...$other_members)
 * @method static \Redis|bool sMove(string $src, string $dst, mixed $value)
 * @method static \Redis|array|string|false sPop(string $key, int $count = 0)
 * @method static mixed sRandMember(string $key, int $count = 0)
 * @method static \Redis|array|false sUnion(string $key, string ...$other_keys)
 * @method static \Redis|int|false sUnionStore(string $dst, string $key, string ...$other_keys)
 * @method static \Redis|bool save()
 * @method static array|false scan(string|int|null $iterator, string|null $pattern = null, int $count = 0, string|null $type = null)
 * @method static \Redis|int|false scard(string $key)
 * @method static mixed script(string $command, mixed ...$args)
 * @method static \Redis|bool select(int $db)
 * @method static \Redis|string|bool set(string $key, mixed $value, mixed $options = null)
 * @method static \Redis|int|false setBit(string $key, int $idx, bool $value)
 * @method static \Redis|int|false setRange(string $key, int $index, string $value)
 * @method static bool setOption(int $option, mixed $value)
 * @method static void setex(string $key, int $expire, mixed $value)
 * @method static \Redis|bool setnx(string $key, mixed $value)
 * @method static \Redis|bool sismember(string $key, mixed $value)
 * @method static \Redis|bool replicaof(string|null $host = null, int $port = 6379)
 * @method static \Redis|int|false touch(array|string $key_or_array, string ...$more_keys)
 * @method static mixed slowlog(string $operation, int $length = 0)
 * @method static mixed sort(string $key, array|null $options = null)
 * @method static mixed sort_ro(string $key, array|null $options = null)
 * @method static \Redis|int|false srem(string $key, mixed $value, mixed ...$other_values)
 * @method static array|false sscan(string $key, string|int|null $iterator, string|null $pattern = null, int $count = 0)
 * @method static bool ssubscribe(array $channels, callable $cb)
 * @method static \Redis|int|false strlen(string $key)
 * @method static \Redis|array|bool sunsubscribe(array $channels)
 * @method static \Redis|bool swapdb(int $src, int $dst)
 * @method static \Redis|array time()
 * @method static \Redis|int|false ttl(string $key)
 * @method static \Redis|int|false type(string $key)
 * @method static \Redis|int|false unlink(array|string $key, string ...$other_keys)
 * @method static \Redis|array|bool unsubscribe(array $channels)
 * @method static \Redis|bool unwatch()
 * @method static \Redis|bool watch(array|string $key, string ...$other_keys)
 * @method static int|false wait(int $numreplicas, int $timeout)
 * @method static int|false xack(string $key, string $group, array $ids)
 * @method static \Redis|string|false xadd(string $key, string $id, array $values, int $maxlen = 0, bool $approx = false, bool $nomkstream = false)
 * @method static \Redis|array|bool xautoclaim(string $key, string $group, string $consumer, int $min_idle, string $start, int $count = -1, bool $justid = false)
 * @method static \Redis|array|bool xclaim(string $key, string $group, string $consumer, int $min_idle, array $ids, array $options)
 * @method static \Redis|int|false xdel(string $key, array $ids)
 * @method static mixed xgroup(string $operation, string|null $key = null, string|null $group = null, string|null $id_or_consumer = null, bool $mkstream = false, int $entries_read = -2)
 * @method static mixed xinfo(string $operation, string|null $arg1 = null, string|null $arg2 = null, int $count = -1)
 * @method static \Redis|int|false xlen(string $key)
 * @method static \Redis|array|false xpending(string $key, string $group, string|null $start = null, string|null $end = null, int $count = -1, string|null $consumer = null)
 * @method static \Redis|array|bool xrange(string $key, string $start, string $end, int $count = -1)
 * @method static \Redis|array|bool xread(array $streams, int $count = -1, int $block = -1)
 * @method static \Redis|array|bool xreadgroup(string $group, string $consumer, array $streams, int $count = 1, int $block = 1)
 * @method static \Redis|array|bool xrevrange(string $key, string $end, string $start, int $count = -1)
 * @method static \Redis|int|false vadd(string $key, array $values, mixed $element, array|null $options = null)
 * @method static \Redis|array|false vsim(string $key, mixed $member, array|null $options = null)
 * @method static \Redis|int|false vcard(string $key)
 * @method static \Redis|int|false vdim(string $key)
 * @method static \Redis|array|false vinfo(string $key)
 * @method static \Redis|bool vismember(string $key, mixed $member)
 * @method static \Redis|array|false vemb(string $key, mixed $member, bool $raw = false)
 * @method static \Redis|array|string|false vrandmember(string $key, int $count = 0)
 * @method static \Redis|array|false vrange(string $key, string $min, string $max, int $count = -1)
 * @method static \Redis|int|false vrem(string $key, mixed $member)
 * @method static \Redis|int|false vsetattr(string $key, mixed $member, array|string $attributes)
 * @method static \Redis|array|string|false vgetattr(string $key, mixed $member, bool $decode = true)
 * @method static \Redis|array|false vlinks(string $key, mixed $member, bool $withscores = false)
 * @method static \Redis|int|false xtrim(string $key, string $threshold, bool $approx = false, bool $minid = false, int $limit = -1)
 * @method static \Redis|int|float|false zAdd(string $key, array|float $score_or_options, mixed ...$more_scores_and_mems)
 * @method static \Redis|int|false zCard(string $key)
 * @method static \Redis|int|false zCount(string $key, string|int $start, string|int $end)
 * @method static \Redis|float|false zIncrBy(string $key, float $value, mixed $member)
 * @method static \Redis|int|false zLexCount(string $key, string $min, string $max)
 * @method static \Redis|array|false zMscore(string $key, mixed $member, mixed ...$other_members)
 * @method static \Redis|array|false zPopMax(string $key, int|null $count = null)
 * @method static \Redis|array|false zPopMin(string $key, int|null $count = null)
 * @method static \Redis|array|false zRange(string $key, string|int $start, string|int $end, array|bool|null $options = null)
 * @method static \Redis|array|false zRangeByLex(string $key, string $min, string $max, int $offset = -1, int $count = -1)
 * @method static \Redis|array|false zRangeByScore(string $key, string $start, string $end, array $options = [])
 * @method static \Redis|int|false zrangestore(string $dstkey, string $srckey, string $start, string $end, array|bool|null $options = null)
 * @method static \Redis|array|string zRandMember(string $key, array|null $options = null)
 * @method static \Redis|int|false zRank(string $key, mixed $member)
 * @method static \Redis|int|false zRem(mixed $key, mixed $member, mixed ...$other_members)
 * @method static \Redis|int|false zRemRangeByLex(string $key, string $min, string $max)
 * @method static \Redis|int|false zRemRangeByRank(string $key, int $start, int $end)
 * @method static \Redis|int|false zRemRangeByScore(string $key, string $start, string $end)
 * @method static \Redis|array|false zRevRange(string $key, int $start, int $end, mixed $scores = null)
 * @method static \Redis|array|false zRevRangeByLex(string $key, string $max, string $min, int $offset = -1, int $count = -1)
 * @method static \Redis|array|false zRevRangeByScore(string $key, string $max, string $min, array|bool $options = [])
 * @method static \Redis|int|false zRevRank(string $key, mixed $member)
 * @method static \Redis|float|false zScore(string $key, mixed $member)
 * @method static \Redis|array|false zdiff(array $keys, array|null $options = null)
 * @method static \Redis|int|false zdiffstore(string $dst, array $keys)
 * @method static \Redis|array|false zinter(array $keys, array|null $weights = null, array|null $options = null)
 * @method static \Redis|int|false zintercard(array $keys, int $limit = -1)
 * @method static \Redis|int|false zinterstore(string $dst, array $keys, array|null $weights = null, string|null $aggregate = null)
 * @method static \Redis|array|false zscan(string $key, string|int|null $iterator, string|null $pattern = null, int $count = 0)
 * @method static \Redis|array|false zunion(array $keys, array|null $weights = null, array|null $options = null)
 * @method static \Redis|int|false zunionstore(string $dst, array $keys, array|null $weights = null, string|null $aggregate = null)
 *
 * @see \Illuminate\Redis\RedisManager
 */
class Redis extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'redis';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static bool supported(string $key, string $cipher)
 * @method static string generateKey(string $cipher)
 * @method static string encrypt(mixed $value, bool $serialize = true)
 * @method static string encryptString(string $value)
 * @method static mixed decrypt(string $payload, bool $unserialize = true)
 * @method static string decryptString(string $payload)
 * @method static bool appearsEncrypted(mixed $value)
 * @method static string getKey()
 * @method static array getAllKeys()
 * @method static array getPreviousKeys()
 * @method static \Illuminate\Encryption\Encrypter previousKeys(array $keys)
 *
 * @see \Illuminate\Encryption\Encrypter
 */
class Crypt extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'encrypter';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Psr\Log\LoggerInterface build(array $config)
 * @method static \Psr\Log\LoggerInterface stack(array $channels, string|null $channel = null)
 * @method static \Psr\Log\LoggerInterface channel(\UnitEnum|string|null $channel = null)
 * @method static \Psr\Log\LoggerInterface driver(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Log\LogManager shareContext(array $context)
 * @method static array sharedContext()
 * @method static \Illuminate\Log\LogManager withoutContext(string[]|null $keys = null)
 * @method static \Illuminate\Log\LogManager flushSharedContext()
 * @method static string|null getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static \Illuminate\Log\LogManager extend(string $driver, \Closure $callback)
 * @method static void forgetChannel(string|null $driver = null)
 * @method static array getChannels()
 * @method static void emergency(string|\Stringable $message, array $context = [])
 * @method static void alert(string|\Stringable $message, array $context = [])
 * @method static void critical(string|\Stringable $message, array $context = [])
 * @method static void error(string|\Stringable $message, array $context = [])
 * @method static void warning(string|\Stringable $message, array $context = [])
 * @method static void notice(string|\Stringable $message, array $context = [])
 * @method static void info(string|\Stringable $message, array $context = [])
 * @method static void debug(string|\Stringable $message, array $context = [])
 * @method static void log(mixed $level, string|\Stringable $message, array $context = [])
 * @method static \Illuminate\Log\LogManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static void write(string $level, \Illuminate\Contracts\Support\Arrayable|\Illuminate\Contracts\Support\Jsonable|\Illuminate\Support\Stringable|array|string $message, array $context = [])
 * @method static \Illuminate\Log\Logger withContext(array $context = [])
 * @method static void listen(\Closure $callback)
 * @method static \Psr\Log\LoggerInterface getLogger()
 * @method static \Illuminate\Contracts\Events\Dispatcher|null getEventDispatcher()
 * @method static void setEventDispatcher(\Illuminate\Contracts\Events\Dispatcher $dispatcher)
 * @method static \Illuminate\Log\Logger|mixed when(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 * @method static \Illuminate\Log\Logger|mixed unless(\Closure|mixed|null $value = null, callable|null $callback = null, callable|null $default = null)
 *
 * @see \Illuminate\Log\LogManager
 */
class Log extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'log';
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static bool shouldBlock()
 * @method static string|null blockDriver()
 * @method static int defaultRouteBlockLockSeconds()
 * @method static int defaultRouteBlockWaitSeconds()
 * @method static array getSessionConfig()
 * @method static string|null getDefaultDriver()
 * @method static void setDefaultDriver(\UnitEnum|string $name)
 * @method static mixed driver(\UnitEnum|string|null $driver = null)
 * @method static \Illuminate\Session\SessionManager extend(string $driver, \Closure $callback)
 * @method static array getDrivers()
 * @method static \Illuminate\Contracts\Container\Container getContainer()
 * @method static \Illuminate\Session\SessionManager setContainer(\Illuminate\Contracts\Container\Container $container)
 * @method static \Illuminate\Session\SessionManager forgetDrivers()
 * @method static bool start()
 * @method static void save()
 * @method static void ageFlashData()
 * @method static array all()
 * @method static array only(array $keys)
 * @method static array except(array $keys)
 * @method static bool exists(\UnitEnum|string|array $key)
 * @method static bool missing(\UnitEnum|string|array $key)
 * @method static bool has(\UnitEnum|string|array $key)
 * @method static bool hasAny(\UnitEnum|string|array $key)
 * @method static mixed get(\UnitEnum|string $key, mixed $default = null)
 * @method static mixed pull(\UnitEnum|string $key, mixed $default = null)
 * @method static bool hasOldInput(string|null $key = null)
 * @method static mixed getOldInput(string|null $key = null, mixed $default = null)
 * @method static void replace(array $attributes)
 * @method static void put(\UnitEnum|string|array $key, mixed $value = null)
 * @method static mixed remember(\UnitEnum|string $key, \Closure $callback)
 * @method static void push(\UnitEnum|string $key, mixed $value)
 * @method static mixed increment(\UnitEnum|string $key, int $amount = 1)
 * @method static int decrement(\UnitEnum|string $key, int $amount = 1)
 * @method static void flash(\UnitEnum|string $key, mixed $value = true)
 * @method static void now(\UnitEnum|string $key, mixed $value)
 * @method static void reflash()
 * @method static void keep(mixed $keys = null)
 * @method static void flashInput(array $value)
 * @method static \Illuminate\Contracts\Cache\Repository cache()
 * @method static mixed remove(\UnitEnum|string $key)
 * @method static void forget(\UnitEnum|string|array $keys)
 * @method static void flush()
 * @method static bool invalidate()
 * @method static bool regenerate(bool $destroy = false)
 * @method static bool migrate(bool $destroy = false)
 * @method static bool isStarted()
 * @method static string getName()
 * @method static void setName(string $name)
 * @method static string id()
 * @method static string getId()
 * @method static void setId(string|null $id)
 * @method static bool isValidId(string|null $id)
 * @method static void setExists(bool $value)
 * @method static string token()
 * @method static void regenerateToken()
 * @method static bool hasPreviousUri()
 * @method static \Illuminate\Support\Uri previousUri()
 * @method static string|null previousUrl()
 * @method static void setPreviousUrl(string $url)
 * @method static string|null previousRoute()
 * @method static void setPreviousRoute(string|null $route)
 * @method static void passwordConfirmed()
 * @method static \SessionHandlerInterface getHandler()
 * @method static \SessionHandlerInterface setHandler(\SessionHandlerInterface $handler)
 * @method static bool handlerNeedsRequest()
 * @method static void setRequestOnHandler(\Illuminate\Http\Request $request)
 * @method static void macro(string $name, object|callable $macro)
 * @method static void mixin(object $mixin, bool $replace = true)
 * @method static bool hasMacro(string $name)
 * @method static void flushMacros()
 *
 * @see \Illuminate\Session\SessionManager
 */
class Session extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'session';
    }
}
<?php

namespace Illuminate\Support\Facades;

use Illuminate\Concurrency\ConcurrencyManager;

/**
 * @method static mixed driver(\UnitEnum|string|null $name = null)
 * @method static \Illuminate\Concurrency\ProcessDriver createProcessDriver()
 * @method static \Illuminate\Concurrency\ForkDriver createForkDriver()
 * @method static \Illuminate\Concurrency\SyncDriver createSyncDriver()
 * @method static string getDefaultInstance()
 * @method static void setDefaultInstance(string $name)
 * @method static array getInstanceConfig(string $name)
 * @method static mixed instance(string|null $name = null)
 * @method static \Illuminate\Concurrency\ConcurrencyManager forgetInstance(array|string|null $name = null)
 * @method static void purge(string|null $name = null)
 * @method static \Illuminate\Concurrency\ConcurrencyManager extend(string $name, \Closure $callback)
 * @method static \Illuminate\Concurrency\ConcurrencyManager setApplication(\Illuminate\Contracts\Foundation\Application $app)
 * @method static array run(\Closure|array $tasks)
 * @method static \Illuminate\Support\Defer\DeferredCallback defer(\Closure|array $tasks)
 *
 * @see \Illuminate\Concurrency\ConcurrencyManager
 */
class Concurrency extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return ConcurrencyManager::class;
    }
}
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static void resolveOptionsUsing(\Closure|null $resolver)
 * @method static void resolveTokenUsing(\Closure|null $resolver)
 * @method static void setUpProcess(callable $callback)
 * @method static void setUpTestCase(callable $callback)
 * @method static void setUpTestDatabaseBeforeMigrating(callable $callback)
 * @method static void setUpTestDatabase(callable $callback)
 * @method static void tearDownProcess(callable $callback)
 * @method static void tearDownTestCase(callable $callback)
 * @method static void callSetUpProcessCallbacks()
 * @method static void callSetUpTestCaseCallbacks(\Illuminate\Foundation\Testing\TestCase $testCase)
 * @method static void callSetUpTestDatabaseBeforeMigratingCallbacks(string $database)
 * @method static void callSetUpTestDatabaseCallbacks(string $database)
 * @method static void callTearDownProcessCallbacks()
 * @method static void callTearDownTestCaseCallbacks(\Illuminate\Foundation\Testing\TestCase $testCase)
 * @method static mixed option(string $option)
 * @method static string|false token()
 *
 * @see \Illuminate\Testing\ParallelTesting
 */
class ParallelTesting extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return \Illuminate\Testing\ParallelTesting::class;
    }
}
<?php

namespace Illuminate\Support;

class AggregateServiceProvider extends ServiceProvider
{
    /**
     * The provider class names.
     *
     * @var array<int, class-string<\Illuminate\Support\ServiceProvider>>
     */
    protected $providers = [];

    /**
     * An array of the service provider instances.
     *
     * @var array<int, \Illuminate\Support\ServiceProvider>
     */
    protected $instances = [];

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->instances = [];

        foreach ($this->providers as $provider) {
            $this->instances[] = $this->app->register($provider);
        }
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array<int, string>
     */
    public function provides()
    {
        $provides = [];

        foreach ($this->providers as $provider) {
            $instance = $this->app->resolveProvider($provider);

            $provides = array_merge($provides, $instance->provides());
        }

        return $provides;
    }
}
<?php

namespace Illuminate\Support;

use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Illuminate\Support\Defer\DeferredCallback;
use Illuminate\Support\Defer\DeferredCallbackCollection;
use Illuminate\Support\Facades\Date;
use Symfony\Component\Process\PhpExecutableFinder;

if (! function_exists('Illuminate\Support\defer')) {
    /**
     * Defer execution of the given callback.
     *
     * @param  callable|null  $callback
     * @param  string|null  $name
     * @param  bool  $always
     * @return ($callback is null ? \Illuminate\Support\Defer\DeferredCallbackCollection : \Illuminate\Support\Defer\DeferredCallback)
     */
    function defer(?callable $callback = null, ?string $name = null, bool $always = false): DeferredCallback|DeferredCallbackCollection
    {
        if ($callback === null) {
            return app(DeferredCallbackCollection::class);
        }

        return tap(
            new DeferredCallback($callback, $name, $always),
            fn ($deferred) => app(DeferredCallbackCollection::class)[] = $deferred
        );
    }
}

if (! function_exists('Illuminate\Support\php_binary')) {
    /**
     * Determine the PHP Binary.
     */
    function php_binary(): string
    {
        return (new PhpExecutableFinder)->find(false) ?: 'php';
    }
}

if (! function_exists('Illuminate\Support\artisan_binary')) {
    /**
     * Determine the proper Artisan executable.
     */
    function artisan_binary(): string
    {
        return defined('ARTISAN_BINARY') ? ARTISAN_BINARY : 'artisan';
    }
}

// Time functions...

if (! function_exists('Illuminate\Support\now')) {
    /**
     * Create a new Carbon instance for the current time.
     *
     * @param  \DateTimeZone|\UnitEnum|string|null  $tz
     * @return \Illuminate\Support\Carbon
     */
    function now($tz = null): CarbonInterface
    {
        return Date::now(enum_value($tz));
    }
}

if (! function_exists('Illuminate\Support\microseconds')) {
    /**
     * Get the current date / time plus the given number of microseconds.
     */
    function microseconds(int|float $microseconds): CarbonInterval
    {
        return CarbonInterval::microseconds($microseconds);
    }
}

if (! function_exists('Illuminate\Support\milliseconds')) {
    /**
     * Get the current date / time plus the given number of milliseconds.
     */
    function milliseconds(int|float $milliseconds): CarbonInterval
    {
        return CarbonInterval::milliseconds($milliseconds);
    }
}

if (! function_exists('Illuminate\Support\seconds')) {
    /**
     * Get the current date / time plus the given number of seconds.
     */
    function seconds(int|float $seconds): CarbonInterval
    {
        return CarbonInterval::seconds($seconds);
    }
}

if (! function_exists('Illuminate\Support\minutes')) {
    /**
     * Get the current date / time plus the given number of minutes.
     */
    function minutes(int|float $minutes): CarbonInterval
    {
        return CarbonInterval::minutes($minutes);
    }
}

if (! function_exists('Illuminate\Support\hours')) {
    /**
     * Get the current date / time plus the given number of hours.
     */
    function hours(int|float $hours): CarbonInterval
    {
        return CarbonInterval::hours($hours);
    }
}

if (! function_exists('Illuminate\Support\days')) {
    /**
     * Get the current date / time plus the given number of days.
     */
    function days(int|float $days): CarbonInterval
    {
        return CarbonInterval::days($days);
    }
}

if (! function_exists('Illuminate\Support\weeks')) {
    /**
     * Get the current date / time plus the given number of weeks.
     */
    function weeks(int $weeks): CarbonInterval
    {
        return CarbonInterval::weeks($weeks);
    }
}

if (! function_exists('Illuminate\Support\months')) {
    /**
     * Get the current date / time plus the given number of months.
     */
    function months(int $months): CarbonInterval
    {
        return CarbonInterval::months($months);
    }
}

if (! function_exists('Illuminate\Support\years')) {
    /**
     * Get the current date / time plus the given number of years.
     */
    function years(int $years): CarbonInterval
    {
        return CarbonInterval::years($years);
    }
}
<?php

namespace Illuminate\Support;

class DefaultProviders
{
    /**
     * The current providers.
     *
     * @var array<class-string>
     */
    protected $providers;

    /**
     * Create a new default provider collection.
     *
     * @param  array<class-string>|null  $providers
     */
    public function __construct(?array $providers = null)
    {
        $this->providers = $providers ?: [
            \Illuminate\Auth\AuthServiceProvider::class,
            \Illuminate\Broadcasting\BroadcastServiceProvider::class,
            \Illuminate\Bus\BusServiceProvider::class,
            \Illuminate\Cache\CacheServiceProvider::class,
            \Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
            \Illuminate\Concurrency\ConcurrencyServiceProvider::class,
            \Illuminate\Cookie\CookieServiceProvider::class,
            \Illuminate\Database\DatabaseServiceProvider::class,
            \Illuminate\Encryption\EncryptionServiceProvider::class,
            \Illuminate\Filesystem\FilesystemServiceProvider::class,
            \Illuminate\Foundation\Providers\FoundationServiceProvider::class,
            \Illuminate\Hashing\HashServiceProvider::class,
            \Illuminate\Mail\MailServiceProvider::class,
            \Illuminate\Notifications\NotificationServiceProvider::class,
            \Illuminate\Pagination\PaginationServiceProvider::class,
            \Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
            \Illuminate\Pipeline\PipelineServiceProvider::class,
            \Illuminate\Queue\QueueServiceProvider::class,
            \Illuminate\Redis\RedisServiceProvider::class,
            \Illuminate\Session\SessionServiceProvider::class,
            \Illuminate\Translation\TranslationServiceProvider::class,
            \Illuminate\Validation\ValidationServiceProvider::class,
            \Illuminate\View\ViewServiceProvider::class,
        ];
    }

    /**
     * Merge the given providers into the provider collection.
     *
     * @param  array<class-string>  $providers
     * @return static
     */
    public function merge(array $providers)
    {
        $this->providers = array_merge($this->providers, $providers);

        return new static($this->providers);
    }

    /**
     * Replace the given providers with other providers.
     *
     * @param  array<class-string, class-string>  $replacements
     * @return static
     */
    public function replace(array $replacements)
    {
        $current = new Collection($this->providers);

        foreach ($replacements as $from => $to) {
            $key = $current->search($from);

            $current = is_int($key) ? $current->replace([$key => $to]) : $current;
        }

        return new static($current->values()->toArray());
    }

    /**
     * Disable the given providers.
     *
     * @param  array<class-string>  $providers
     * @return static
     */
    public function except(array $providers)
    {
        return new static((new Collection($this->providers))
            ->reject(fn ($p) => in_array($p, $providers))
            ->values()
            ->toArray());
    }

    /**
     * Convert the provider collection to an array.
     *
     * @return array<class-string>
     */
    public function toArray()
    {
        return $this->providers;
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Dumpable;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Support\Traits\Tappable;
use JsonSerializable;
use League\Uri\Contracts\UriInterface;
use League\Uri\Uri as LeagueUri;
use SensitiveParameter;
use Stringable;

class Uri implements Htmlable, JsonSerializable, Responsable, Stringable
{
    use Conditionable, Dumpable, Macroable, Tappable;

    /**
     * The URI instance.
     */
    protected UriInterface $uri;

    /**
     * The URL generator resolver.
     */
    protected static ?Closure $urlGeneratorResolver = null;

    /**
     * Create a new parsed URI instance.
     */
    public function __construct(UriInterface|Stringable|string $uri = '')
    {
        $this->uri = $uri instanceof UriInterface ? $uri : LeagueUri::new((string) $uri);
    }

    /**
     * Create a new URI instance.
     */
    public static function of(UriInterface|Stringable|string $uri = ''): static
    {
        return new static($uri);
    }

    /**
     * Get a URI instance of an absolute URL for the given path.
     */
    public static function to(string $path): static
    {
        return new static(call_user_func(static::$urlGeneratorResolver)->to($path));
    }

    /**
     * Get a URI instance for a named route.
     *
     * @param  \BackedEnum|string  $name
     * @param  mixed  $parameters
     * @param  bool  $absolute
     * @return static
     *
     * @throws \Symfony\Component\Routing\Exception\RouteNotFoundException|\InvalidArgumentException
     */
    public static function route($name, $parameters = [], $absolute = true): static
    {
        return new static(call_user_func(static::$urlGeneratorResolver)->route($name, $parameters, $absolute));
    }

    /**
     * Create a signed route URI instance for a named route.
     *
     * @param  \BackedEnum|string  $name
     * @param  mixed  $parameters
     * @param  \DateTimeInterface|\DateInterval|int|null  $expiration
     * @param  bool  $absolute
     * @return static
     *
     * @throws \InvalidArgumentException
     */
    public static function signedRoute($name, $parameters = [], $expiration = null, $absolute = true): static
    {
        return new static(call_user_func(static::$urlGeneratorResolver)->signedRoute($name, $parameters, $expiration, $absolute));
    }

    /**
     * Create a temporary signed route URI instance for a named route.
     *
     * @param  \BackedEnum|string  $name
     * @param  \DateTimeInterface|\DateInterval|int  $expiration
     * @param  array  $parameters
     * @param  bool  $absolute
     * @return static
     */
    public static function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true): static
    {
        return static::signedRoute($name, $parameters, $expiration, $absolute);
    }

    /**
     * Get a URI instance for a controller action.
     *
     * @param  string|array  $action
     * @param  mixed  $parameters
     * @param  bool  $absolute
     * @return static
     *
     * @throws \InvalidArgumentException
     */
    public static function action($action, $parameters = [], $absolute = true): static
    {
        return new static(call_user_func(static::$urlGeneratorResolver)->action($action, $parameters, $absolute));
    }

    /**
     * Get the URI's authority.
     */
    public function authority(): ?string
    {
        return $this->uri->getAuthority();
    }

    /**
     * Get the URI's scheme.
     */
    public function scheme(): ?string
    {
        return $this->uri->getScheme();
    }

    /**
     * Get the user from the URI.
     */
    public function user(bool $withPassword = false): ?string
    {
        return $withPassword
            ? $this->uri->getUserInfo()
            : $this->uri->getUsername();
    }

    /**
     * Get the password from the URI.
     */
    public function password(): ?string
    {
        return $this->uri->getPassword();
    }

    /**
     * Get the URI's host.
     */
    public function host(): ?string
    {
        return $this->uri->getHost();
    }

    /**
     * Get the URI's port.
     */
    public function port(): ?int
    {
        return $this->uri->getPort();
    }

    /**
     * Get the URI's path.
     *
     * Empty or missing paths are returned as a single "/".
     *
     * @return non-empty-string
     */
    public function path(): string
    {
        $path = trim((string) $this->uri->getPath(), '/');

        return $path === '' ? '/' : $path;
    }

    /**
     * Get the URI's path segments.
     *
     * Empty or missing paths are returned as an empty collection.
     */
    public function pathSegments(): Collection
    {
        $path = $this->path();

        return $path === '/' ? new Collection : new Collection(explode('/', $path));
    }

    /**
     * Get the URI's query string.
     */
    public function query(): UriQueryString
    {
        return new UriQueryString($this);
    }

    /**
     * Get the URI's fragment.
     */
    public function fragment(): ?string
    {
        return $this->uri->getFragment();
    }

    /**
     * Specify the scheme of the URI.
     */
    public function withScheme(Stringable|string $scheme): static
    {
        return new static($this->uri->withScheme($scheme));
    }

    /**
     * Specify the user and password for the URI.
     */
    public function withUser(Stringable|string|null $user, #[SensitiveParameter] Stringable|string|null $password = null): static
    {
        return new static($this->uri->withUserInfo($user, $password));
    }

    /**
     * Specify the host of the URI.
     */
    public function withHost(Stringable|string $host): static
    {
        return new static($this->uri->withHost($host));
    }

    /**
     * Specify the port of the URI.
     */
    public function withPort(?int $port): static
    {
        return new static($this->uri->withPort($port));
    }

    /**
     * Specify the path of the URI.
     */
    public function withPath(Stringable|string $path): static
    {
        return new static($this->uri->withPath(Str::start((string) $path, '/')));
    }

    /**
     * Merge new query parameters into the URI.
     */
    public function withQuery(array $query, bool $merge = true): static
    {
        foreach ($query as $key => $value) {
            if ($value instanceof UrlRoutable) {
                $query[$key] = $value->getRouteKey();
            }
        }

        if ($merge) {
            $mergedQuery = $this->query()->all();

            foreach ($query as $key => $value) {
                data_set($mergedQuery, $key, $value);
            }

            $newQuery = $mergedQuery;
        } else {
            $newQuery = [];

            foreach ($query as $key => $value) {
                data_set($newQuery, $key, $value);
            }
        }

        return new static($this->uri->withQuery(Arr::query($newQuery) ?: null));
    }

    /**
     * Merge new query parameters into the URI if they are not already in the query string.
     */
    public function withQueryIfMissing(array $query): static
    {
        $currentQuery = $this->query();

        foreach ($query as $key => $value) {
            if (! $currentQuery->missing($key)) {
                Arr::forget($query, $key);
            }
        }

        return $this->withQuery($query);
    }

    /**
     * Push a value onto the end of a query string parameter that is a list.
     */
    public function pushOntoQuery(string $key, mixed $value): static
    {
        $currentValue = data_get($this->query()->all(), $key);

        $values = Arr::wrap($value);

        return $this->withQuery([$key => match (true) {
            is_array($currentValue) && array_is_list($currentValue) => array_values(array_unique([...$currentValue, ...$values])),
            is_array($currentValue) => [...$currentValue, ...$values],
            ! is_null($currentValue) => [$currentValue, ...$values],
            default => $values,
        }]);
    }

    /**
     * Remove the given query parameters from the URI.
     */
    public function withoutQuery(array|string $keys): static
    {
        return $this->replaceQuery(Arr::except($this->query()->all(), $keys));
    }

    /**
     * Specify new query parameters for the URI.
     */
    public function replaceQuery(array $query): static
    {
        return $this->withQuery($query, merge: false);
    }

    /**
     * Specify the fragment of the URI.
     */
    public function withFragment(string $fragment): static
    {
        return new static($this->uri->withFragment($fragment));
    }

    /**
     * Remove the fragment from the URI.
     */
    public function withoutFragment(): static
    {
        return new static($this->uri->withFragment(null));
    }

    /**
     * Create a redirect HTTP response for the given URI.
     */
    public function redirect(int $status = 302, array $headers = []): RedirectResponse
    {
        return new RedirectResponse($this->value(), $status, $headers);
    }

    /**
     * Get the URI as a Stringable instance.
     *
     * @return \Illuminate\Support\Stringable
     */
    public function toStringable()
    {
        return Str::of($this->value());
    }

    /**
     * Create an HTTP response that represents the URI object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        return new RedirectResponse($this->value());
    }

    /**
     * Get the URI as a string of HTML.
     *
     * @return string
     */
    public function toHtml()
    {
        return $this->value();
    }

    /**
     * Get the decoded string representation of the URI.
     */
    public function decode(): string
    {
        if (empty($this->query()->toArray())) {
            return $this->value();
        }

        return Str::replace($this->query()->value(), $this->query()->decode(), $this->value());
    }

    /**
     * Get the string representation of the URI.
     */
    public function value(): string
    {
        return $this->toString();
    }

    /**
     * Get the string representation of the URI.
     */
    public function toString(): string
    {
        return $this->uri->toString();
    }

    /**
     * Determine if the URI is currently an empty string.
     */
    public function isEmpty(): bool
    {
        return trim($this->value()) === '';
    }

    /**
     * Determine if the URI is not an empty string.
     */
    public function isNotEmpty(): bool
    {
        return ! $this->isEmpty();
    }

    /**
     * Dump the string representation of the URI.
     *
     * @param  mixed  ...$args
     * @return $this
     */
    public function dump(...$args)
    {
        dump($this->value(), ...$args);

        return $this;
    }

    /**
     * Set the URL generator resolver.
     */
    public static function setUrlGeneratorResolver(Closure $urlGeneratorResolver): void
    {
        static::$urlGeneratorResolver = $urlGeneratorResolver;
    }

    /**
     * Get the underlying URI instance.
     */
    public function getUri(): UriInterface
    {
        return $this->uri;
    }

    /**
     * Convert the object into a value that is JSON serializable.
     *
     * @return string
     */
    public function jsonSerialize(): string
    {
        return $this->value();
    }

    /**
     * Get the string representation of the URI.
     */
    public function __toString(): string
    {
        return $this->toString();
    }
}
<?php

declare(strict_types=1);

namespace Illuminate\Support;

use Closure;
use ReflectionFunction;

trait RebindsCallbacksToSelf
{
    /**
     * Binds the provided callback to the class instance.
     *
     * @throws \ReflectionException
     */
    protected function bindCallbackToSelf(Closure $callback): ?Closure
    {
        $reflector = new ReflectionFunction($callback);

        // We only want to rebind anonymous functions.
        if ($reflector->isAnonymous()) {
            if ($reflector->isStatic()) {
                // Static functions are bound without $this.
                $callback = $callback->bindTo(null, static::class);
            } else {
                // Non-static functions are bound to $this.
                $callback = $callback->bindTo($this, static::class);
            }
        }

        return $callback;
    }
}
<?php

namespace Illuminate\Support;

use Throwable;

class Timebox
{
    /**
     * Indicates if the timebox is allowed to return early.
     *
     * @var bool
     */
    public $earlyReturn = false;

    /**
     * Invoke the given callback within the specified timebox minimum.
     *
     * @template TCallReturnType
     *
     * @param  (callable($this): TCallReturnType)  $callback
     * @param  int  $microseconds
     * @return TCallReturnType
     *
     * @throws \Throwable
     */
    public function call(callable $callback, int $microseconds)
    {
        $exception = null;

        $start = microtime(true);

        try {
            $result = $callback($this);
        } catch (Throwable $caught) {
            $exception = $caught;
        }

        $remainder = (int) ($microseconds - ((microtime(true) - $start) * 1_000_000));

        if (! $this->earlyReturn && $remainder > 0) {
            $this->usleep($remainder);
        }

        if ($exception) {
            throw $exception;
        }

        return $result;
    }

    /**
     * Indicate that the timebox can return early.
     *
     * @return $this
     */
    public function returnEarly()
    {
        $this->earlyReturn = true;

        return $this;
    }

    /**
     * Indicate that the timebox cannot return early.
     *
     * @return $this
     */
    public function dontReturnEarly()
    {
        $this->earlyReturn = false;

        return $this;
    }

    /**
     * Sleep for the specified number of microseconds.
     *
     * @param  int  $microseconds
     * @return void
     */
    protected function usleep(int $microseconds)
    {
        Sleep::usleep($microseconds);
    }
}
<?php

namespace Illuminate\Support;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\MessageBag as MessageBagContract;
use Illuminate\Contracts\Support\MessageProvider;
use JsonSerializable;
use Stringable;

class MessageBag implements Jsonable, JsonSerializable, MessageBagContract, MessageProvider, Stringable
{
    /**
     * All of the registered messages.
     *
     * @var array<string, array<string>>
     */
    protected $messages = [];

    /**
     * Default format for message output.
     *
     * @var string
     */
    protected $format = ':message';

    /**
     * Create a new message bag instance.
     *
     * @param  array<string, Arrayable|string|array<string>>  $messages
     */
    public function __construct(array $messages = [])
    {
        foreach ($messages as $key => $value) {
            $value = $value instanceof Arrayable ? $value->toArray() : (array) $value;

            $this->messages[$key] = array_unique($value);
        }
    }

    /**
     * Get the keys present in the message bag.
     *
     * @return array<string>
     */
    public function keys()
    {
        return array_keys($this->messages);
    }

    /**
     * Add a message to the message bag.
     *
     * @param  string  $key
     * @param  string  $message
     * @return $this
     */
    public function add($key, $message)
    {
        if ($this->isUnique($key, $message)) {
            $this->messages[$key][] = $message;
        }

        return $this;
    }

    /**
     * Add a message to the message bag if the given conditional is "true".
     *
     * @param  bool  $boolean
     * @param  string  $key
     * @param  string  $message
     * @return $this
     */
    public function addIf($boolean, $key, $message)
    {
        return $boolean ? $this->add($key, $message) : $this;
    }

    /**
     * Determine if a key and message combination already exists.
     *
     * @param  string  $key
     * @param  string  $message
     * @return bool
     */
    protected function isUnique($key, $message)
    {
        $messages = (array) $this->messages;

        return ! isset($messages[$key]) || ! in_array($message, $messages[$key]);
    }

    /**
     * Merge a new array of messages into the message bag.
     *
     * @param  \Illuminate\Contracts\Support\MessageProvider|array<string, array<string>>  $messages
     * @return $this
     */
    public function merge($messages)
    {
        if ($messages instanceof MessageProvider) {
            $messages = $messages->getMessageBag()->getMessages();
        }

        $this->messages = array_merge_recursive($this->messages, $messages);

        return $this;
    }

    /**
     * Determine if messages exist for all of the given keys.
     *
     * @param  array<string>|string|null  $key
     * @return bool
     */
    public function has($key)
    {
        if ($this->isEmpty()) {
            return false;
        }

        if (is_null($key)) {
            return $this->any();
        }

        $keys = is_array($key) ? $key : func_get_args();

        foreach ($keys as $key) {
            if ($this->first($key) === '') {
                return false;
            }
        }

        return true;
    }

    /**
     * Determine if messages exist for any of the given keys.
     *
     * @param  array<string>|string|null  $keys
     * @return bool
     */
    public function hasAny($keys = [])
    {
        if ($this->isEmpty()) {
            return false;
        }

        $keys = is_array($keys) ? $keys : func_get_args();

        foreach ($keys as $key) {
            if ($this->has($key)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if messages don't exist for all of the given keys.
     *
     * @param  array<string>|string|null  $key
     * @return bool
     */
    public function missing($key)
    {
        $keys = is_array($key) ? $key : func_get_args();

        return ! $this->hasAny($keys);
    }

    /**
     * Get the first message from the message bag for a given key.
     *
     * @param  string|null  $key
     * @param  string|null  $format
     * @return string
     */
    public function first($key = null, $format = null)
    {
        $messages = is_null($key) ? $this->all($format) : $this->get($key, $format);

        $firstMessage = Arr::first($messages, null, '');

        return is_array($firstMessage) ? Arr::first($firstMessage) : $firstMessage;
    }

    /**
     * Get all of the messages from the message bag for a given key.
     *
     * @param  string  $key
     * @param  string|null  $format
     * @return array<string>|array<string, array<string>>
     */
    public function get($key, $format = null)
    {
        // If the message exists in the message bag, we will transform it and return
        // the message. Otherwise, we will check if the key is implicit & collect
        // all the messages that match the given key and output it as an array.
        if (array_key_exists($key, $this->messages)) {
            return $this->transform(
                $this->messages[$key], $this->checkFormat($format), $key
            );
        }

        if (str_contains($key, '*')) {
            return $this->getMessagesForWildcardKey($key, $format);
        }

        return [];
    }

    /**
     * Get the messages for a wildcard key.
     *
     * @param  string  $key
     * @param  string|null  $format
     * @return array<string, array<string>>
     */
    protected function getMessagesForWildcardKey($key, $format)
    {
        return (new Collection($this->messages))
            ->filter(fn ($messages, $messageKey) => Str::is($key, $messageKey))
            ->map(function ($messages, $messageKey) use ($format) {
                return $this->transform($messages, $this->checkFormat($format), $messageKey);
            })
            ->all();
    }

    /**
     * Get all of the messages for every key in the message bag.
     *
     * @param  string|null  $format
     * @return array<string>
     */
    public function all($format = null)
    {
        $format = $this->checkFormat($format);

        $all = [];

        foreach ($this->messages as $key => $messages) {
            array_push($all, ...$this->transform($messages, $format, $key));
        }

        return $all;
    }

    /**
     * Get all of the unique messages for every key in the message bag.
     *
     * @param  string|null  $format
     * @return array<string>
     */
    public function unique($format = null)
    {
        return array_unique($this->all($format));
    }

    /**
     * Remove a message from the message bag.
     *
     * @param  string  $key
     * @return $this
     */
    public function forget($key)
    {
        unset($this->messages[$key]);

        return $this;
    }

    /**
     * Format an array of messages.
     *
     * @param  array<string>  $messages
     * @param  string  $format
     * @param  string  $messageKey
     * @return array<string>
     */
    protected function transform($messages, $format, $messageKey)
    {
        if ($format == ':message') {
            return (array) $messages;
        }

        return (new Collection((array) $messages))
            ->map(function ($message) use ($format, $messageKey) {
                // We will simply spin through the given messages and transform each one
                // replacing the :message place holder with the real message allowing
                // the messages to be easily formatted to each developer's desires.
                return str_replace([':message', ':key'], [$message, $messageKey], $format);
            })->all();
    }

    /**
     * Get the appropriate format based on the given format.
     *
     * @param  string  $format
     * @return string
     */
    protected function checkFormat($format)
    {
        return $format ?: $this->format;
    }

    /**
     * Get the raw messages in the message bag.
     *
     * @return array<string, array<string>>
     */
    public function messages()
    {
        return $this->messages;
    }

    /**
     * Get the raw messages in the message bag.
     *
     * @return array<string, array<string>>
     */
    public function getMessages()
    {
        return $this->messages();
    }

    /**
     * Get the messages for the instance.
     *
     * @return \Illuminate\Support\MessageBag
     */
    public function getMessageBag()
    {
        return $this;
    }

    /**
     * Get the default message format.
     *
     * @return string
     */
    public function getFormat()
    {
        return $this->format;
    }

    /**
     * Set the default message format.
     *
     * @param  string  $format
     * @return \Illuminate\Support\MessageBag
     */
    public function setFormat($format = ':message')
    {
        $this->format = $format;

        return $this;
    }

    /**
     * Determine if the message bag has any messages.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return ! $this->any();
    }

    /**
     * Determine if the message bag has any messages.
     *
     * @return bool
     */
    public function isNotEmpty()
    {
        return $this->any();
    }

    /**
     * Determine if the message bag has any messages.
     *
     * @return bool
     */
    public function any()
    {
        return $this->count() > 0;
    }

    /**
     * Get the number of messages in the message bag.
     *
     * @return int
     */
    public function count(): int
    {
        return count($this->messages, COUNT_RECURSIVE) - count($this->messages);
    }

    /**
     * Get the instance as an array.
     *
     * @return array<string, array<string>>
     */
    public function toArray()
    {
        return $this->getMessages();
    }

    /**
     * Convert the object into something JSON serializable.
     *
     * @return array<string, array<string>>
     */
    public function jsonSerialize(): array
    {
        return $this->toArray();
    }

    /**
     * Convert the object to its JSON representation.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0)
    {
        return json_encode($this->jsonSerialize(), $options);
    }

    /**
     * Convert the object to pretty print formatted JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toPrettyJson(int $options = 0)
    {
        return $this->toJson(JSON_PRETTY_PRINT | $options);
    }

    /**
     * Convert the message bag to its string representation.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }
}
<?php

namespace Illuminate\Support;

use ArrayAccess;
use ArrayIterator;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\InteractsWithData;
use Illuminate\Support\Traits\Macroable;
use IteratorAggregate;
use JsonSerializable;
use Traversable;

/**
 * @template TKey of array-key
 * @template TValue
 *
 * @implements \Illuminate\Contracts\Support\Arrayable<TKey, TValue>
 * @implements \ArrayAccess<TKey, TValue>
 */
class Fluent implements Arrayable, ArrayAccess, IteratorAggregate, Jsonable, JsonSerializable
{
    use Conditionable, InteractsWithData, Macroable {
        __call as macroCall;
    }

    /**
     * All of the attributes set on the fluent instance.
     *
     * @var array<TKey, TValue>
     */
    protected $attributes = [];

    /**
     * Create a new fluent instance.
     *
     * @param  iterable<TKey, TValue>  $attributes
     */
    public function __construct($attributes = [])
    {
        $this->fill($attributes);
    }

    /**
     * Create a new fluent instance.
     *
     * @param  iterable<TKey, TValue>  $attributes
     * @return static
     */
    public static function make($attributes = [])
    {
        return new static($attributes);
    }

    /**
     * Get an attribute from the fluent instance using "dot" notation.
     *
     * @template TGetDefault
     *
     * @param  TKey  $key
     * @param  TGetDefault|(\Closure(): TGetDefault)  $default
     * @return TValue|TGetDefault
     */
    public function get($key, $default = null)
    {
        return data_get($this->attributes, $key, $default);
    }

    /**
     * Set an attribute on the fluent instance using "dot" notation.
     *
     * @param  TKey  $key
     * @param  TValue  $value
     * @return $this
     */
    public function set($key, $value)
    {
        data_set($this->attributes, $key, $value);

        return $this;
    }

    /**
     * Fill the fluent instance with an array of attributes.
     *
     * @param  iterable<TKey, TValue>  $attributes
     * @return $this
     */
    public function fill($attributes)
    {
        foreach ($attributes as $key => $value) {
            $this->attributes[$key] = $value;
        }

        return $this;
    }

    /**
     * Get an attribute from the fluent instance.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return mixed
     */
    public function value($key, $default = null)
    {
        if (array_key_exists($key, $this->attributes)) {
            return $this->attributes[$key];
        }

        return value($default);
    }

    /**
     * Get the value of the given key as a new Fluent instance.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return static
     */
    public function scope($key, $default = null)
    {
        return new static(
            (array) $this->get($key, $default)
        );
    }

    /**
     * Get all of the attributes from the fluent instance.
     *
     * @param  mixed  $keys
     * @return array<TKey, TValue>
     */
    public function all($keys = null)
    {
        $data = $this->data();

        if (! $keys) {
            return $data;
        }

        $results = [];

        foreach (is_array($keys) ? $keys : func_get_args() as $key) {
            Arr::set($results, $key, Arr::get($data, $key));
        }

        return $results;
    }

    /**
     * Get data from the fluent instance.
     *
     * @param  string|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    protected function data($key = null, $default = null)
    {
        return $this->get($key, $default);
    }

    /**
     * Get the attributes from the fluent instance.
     *
     * @return array<TKey, TValue>
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * Convert the fluent instance to an array.
     *
     * @return array<TKey, TValue>
     */
    public function toArray()
    {
        return $this->attributes;
    }

    /**
     * Convert the object into something JSON serializable.
     *
     * @return array<TKey, TValue>
     */
    public function jsonSerialize(): array
    {
        return $this->toArray();
    }

    /**
     * Convert the fluent instance to JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0)
    {
        return json_encode($this->jsonSerialize(), $options);
    }

    /**
     * Convert the fluent instance to pretty print formatted JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toPrettyJson(int $options = 0)
    {
        return $this->toJson(JSON_PRETTY_PRINT | $options);
    }

    /**
     * Determine if the fluent instance is empty.
     *
     * @return bool
     */
    public function isEmpty(): bool
    {
        return empty($this->attributes);
    }

    /**
     * Determine if the fluent instance is not empty.
     *
     * @return bool
     */
    public function isNotEmpty(): bool
    {
        return ! $this->isEmpty();
    }

    /**
     * Determine if the given offset exists.
     *
     * @param  TKey  $offset
     * @return bool
     */
    public function offsetExists($offset): bool
    {
        return isset($this->attributes[$offset]);
    }

    /**
     * Get the value for a given offset.
     *
     * @param  TKey  $offset
     * @return TValue|null
     */
    public function offsetGet($offset): mixed
    {
        return $this->value($offset);
    }

    /**
     * Set the value at the given offset.
     *
     * @param  TKey  $offset
     * @param  TValue  $value
     * @return void
     */
    public function offsetSet($offset, $value): void
    {
        $this->attributes[$offset] = $value;
    }

    /**
     * Unset the value at the given offset.
     *
     * @param  TKey  $offset
     * @return void
     */
    public function offsetUnset($offset): void
    {
        unset($this->attributes[$offset]);
    }

    /**
     * Get an iterator for the attributes.
     *
     * @return ArrayIterator<TKey, TValue>
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->attributes);
    }

    /**
     * Handle dynamic calls to the fluent instance to set attributes.
     *
     * @param  TKey  $method
     * @param  array{0: ?TValue}  $parameters
     * @return $this
     */
    public function __call($method, $parameters)
    {
        if (static::hasMacro($method)) {
            return $this->macroCall($method, $parameters);
        }

        $this->attributes[$method] = count($parameters) > 0 ? array_first($parameters) : true;

        return $this;
    }

    /**
     * Dynamically retrieve the value of an attribute.
     *
     * @param  TKey  $key
     * @return TValue|null
     */
    public function __get($key)
    {
        return $this->value($key);
    }

    /**
     * Dynamically set the value of an attribute.
     *
     * @param  TKey  $key
     * @param  TValue  $value
     * @return void
     */
    public function __set($key, $value)
    {
        $this->offsetSet($key, $value);
    }

    /**
     * Dynamically check if an attribute is set.
     *
     * @param  TKey  $key
     * @return bool
     */
    public function __isset($key)
    {
        return $this->offsetExists($key);
    }

    /**
     * Dynamically unset an attribute.
     *
     * @param  TKey  $key
     * @return void
     */
    public function __unset($key)
    {
        $this->offsetUnset($key);
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Console\Application as Artisan;
use Illuminate\Contracts\Foundation\CachesConfiguration;
use Illuminate\Contracts\Foundation\CachesRoutes;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Database\Eloquent\Factory as ModelFactory;
use Illuminate\View\Compilers\BladeCompiler;

/**
 * @property array<string, string> $bindings All of the container bindings that should be registered.
 * @property array<array-key, string> $singletons All of the singletons that should be registered.
 */
abstract class ServiceProvider
{
    /**
     * The application instance.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected $app;

    /**
     * All of the registered booting callbacks.
     *
     * @var array
     */
    protected $bootingCallbacks = [];

    /**
     * All of the registered booted callbacks.
     *
     * @var array
     */
    protected $bootedCallbacks = [];

    /**
     * The paths that should be published.
     *
     * @var array
     */
    public static $publishes = [];

    /**
     * The paths that should be published by group.
     *
     * @var array
     */
    public static $publishGroups = [];

    /**
     * The migration paths available for publishing.
     *
     * @var array
     */
    protected static $publishableMigrationPaths = [];

    /**
     * Commands that should be run during the "optimize" command.
     *
     * @var array<string, string>
     */
    public static array $optimizeCommands = [];

    /**
     * Commands that should be run during the "optimize:clear" command.
     *
     * @var array<string, string>
     */
    public static array $optimizeClearCommands = [];

    /**
     * Commands that should be run during the "reload" command.
     *
     * @var array<string, string>
     */
    public static array $reloadCommands = [];

    /**
     * Create a new service provider instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     */
    public function __construct($app)
    {
        $this->app = $app;
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Register a booting callback to be run before the "boot" method is called.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public function booting(Closure $callback)
    {
        $this->bootingCallbacks[] = $callback;
    }

    /**
     * Register a booted callback to be run after the "boot" method is called.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public function booted(Closure $callback)
    {
        $this->bootedCallbacks[] = $callback;
    }

    /**
     * Call the registered booting callbacks.
     *
     * @return void
     */
    public function callBootingCallbacks()
    {
        $index = 0;

        while ($index < count($this->bootingCallbacks)) {
            $this->app->call($this->bootingCallbacks[$index]);

            $index++;
        }
    }

    /**
     * Call the registered booted callbacks.
     *
     * @return void
     */
    public function callBootedCallbacks()
    {
        $index = 0;

        while ($index < count($this->bootedCallbacks)) {
            $this->app->call($this->bootedCallbacks[$index]);

            $index++;
        }
    }

    /**
     * Merge the given configuration with the existing configuration.
     *
     * @param  string  $path
     * @param  string  $key
     * @return void
     */
    protected function mergeConfigFrom($path, $key)
    {
        if (! ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached())) {
            $config = $this->app->make('config');

            $config->set($key, array_merge(
                require $path, $config->get($key, [])
            ));
        }
    }

    /**
     * Replace the given configuration with the existing configuration recursively.
     *
     * @param  string  $path
     * @param  string  $key
     * @return void
     */
    protected function replaceConfigRecursivelyFrom($path, $key)
    {
        if (! ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached())) {
            $config = $this->app->make('config');

            $config->set($key, array_replace_recursive(
                require $path, $config->get($key, [])
            ));
        }
    }

    /**
     * Load the given routes file if routes are not already cached.
     *
     * @param  string  $path
     * @return void
     */
    protected function loadRoutesFrom($path)
    {
        if (! ($this->app instanceof CachesRoutes && $this->app->routesAreCached())) {
            require $path;
        }
    }

    /**
     * Register a view file namespace.
     *
     * @param  string|array  $path
     * @param  string  $namespace
     * @return void
     */
    protected function loadViewsFrom($path, $namespace)
    {
        $this->callAfterResolving('view', function ($view) use ($path, $namespace) {
            if (isset($this->app->config['view']['paths']) &&
                is_array($this->app->config['view']['paths'])) {
                foreach ($this->app->config['view']['paths'] as $viewPath) {
                    if (is_dir($appPath = $viewPath.'/vendor/'.$namespace)) {
                        $view->addNamespace($namespace, $appPath);
                    }
                }
            }

            $view->addNamespace($namespace, $path);
        });
    }

    /**
     * Register the given view components with a custom prefix.
     *
     * @param  string  $prefix
     * @param  array  $components
     * @return void
     */
    protected function loadViewComponentsAs($prefix, array $components)
    {
        $this->callAfterResolving(BladeCompiler::class, function ($blade) use ($prefix, $components) {
            foreach ($components as $alias => $component) {
                $blade->component($component, is_string($alias) ? $alias : null, $prefix);
            }
        });
    }

    /**
     * Register a translation file namespace or path.
     *
     * @param  string  $path
     * @param  string|null  $namespace
     * @return void
     */
    protected function loadTranslationsFrom($path, $namespace = null)
    {
        $this->callAfterResolving('translator', fn ($translator) => is_null($namespace)
            ? $translator->addPath($path)
            : $translator->addNamespace($namespace, $path));
    }

    /**
     * Register a JSON translation file path.
     *
     * @param  string  $path
     * @return void
     */
    protected function loadJsonTranslationsFrom($path)
    {
        $this->callAfterResolving('translator', function ($translator) use ($path) {
            $translator->addJsonPath($path);
        });
    }

    /**
     * Register database migration paths.
     *
     * @param  array|string  $paths
     * @return void
     */
    protected function loadMigrationsFrom($paths)
    {
        $this->callAfterResolving('migrator', function ($migrator) use ($paths) {
            foreach ((array) $paths as $path) {
                $migrator->path($path);
            }
        });
    }

    /**
     * Register Eloquent model factory paths.
     *
     * @deprecated Will be removed in a future Laravel version.
     *
     * @param  array|string  $paths
     * @return void
     */
    protected function loadFactoriesFrom($paths)
    {
        $this->callAfterResolving(ModelFactory::class, function ($factory) use ($paths) {
            foreach ((array) $paths as $path) {
                $factory->load($path);
            }
        });
    }

    /**
     * Setup an after resolving listener, or fire immediately if already resolved.
     *
     * @param  string  $name
     * @param  callable  $callback
     * @return void
     */
    protected function callAfterResolving($name, $callback)
    {
        $this->app->afterResolving($name, $callback);

        if ($this->app->resolved($name)) {
            $callback($this->app->make($name), $this->app);
        }
    }

    /**
     * Register migration paths to be published by the publish command.
     *
     * @param  array  $paths
     * @param  mixed  $groups
     * @return void
     */
    protected function publishesMigrations(array $paths, $groups = null)
    {
        $this->publishes($paths, $groups);

        if ($this->app->config->get('database.migrations.update_date_on_publish', false)) {
            static::$publishableMigrationPaths = array_unique(array_merge(static::$publishableMigrationPaths, array_keys($paths)));
        }
    }

    /**
     * Register paths to be published by the publish command.
     *
     * @param  array  $paths
     * @param  mixed  $groups
     * @return void
     */
    protected function publishes(array $paths, $groups = null)
    {
        $this->ensurePublishArrayInitialized($class = static::class);

        static::$publishes[$class] = array_merge(static::$publishes[$class], $paths);

        foreach ((array) $groups as $group) {
            $this->addPublishGroup($group, $paths);
        }
    }

    /**
     * Ensure the publish array for the service provider is initialized.
     *
     * @param  string  $class
     * @return void
     */
    protected function ensurePublishArrayInitialized($class)
    {
        if (! array_key_exists($class, static::$publishes)) {
            static::$publishes[$class] = [];
        }
    }

    /**
     * Add a publish group / tag to the service provider.
     *
     * @param  string  $group
     * @param  array  $paths
     * @return void
     */
    protected function addPublishGroup($group, $paths)
    {
        if (! array_key_exists($group, static::$publishGroups)) {
            static::$publishGroups[$group] = [];
        }

        static::$publishGroups[$group] = array_merge(
            static::$publishGroups[$group], $paths
        );
    }

    /**
     * Get the paths to publish.
     *
     * @param  string|null  $provider
     * @param  string|null  $group
     * @return array
     */
    public static function pathsToPublish($provider = null, $group = null)
    {
        if (! is_null($paths = static::pathsForProviderOrGroup($provider, $group))) {
            return $paths;
        }

        return (new Collection(static::$publishes))->reduce(function ($paths, $p) {
            return array_merge($paths, $p);
        }, []);
    }

    /**
     * Get the paths for the provider or group (or both).
     *
     * @param  string|null  $provider
     * @param  string|null  $group
     * @return array
     */
    protected static function pathsForProviderOrGroup($provider, $group)
    {
        if ($provider && $group) {
            return static::pathsForProviderAndGroup($provider, $group);
        } elseif ($group && array_key_exists($group, static::$publishGroups)) {
            return static::$publishGroups[$group];
        } elseif ($provider && array_key_exists($provider, static::$publishes)) {
            return static::$publishes[$provider];
        } elseif ($group || $provider) {
            return [];
        }
    }

    /**
     * Get the paths for the provider and group.
     *
     * @param  string  $provider
     * @param  string  $group
     * @return array
     */
    protected static function pathsForProviderAndGroup($provider, $group)
    {
        if (! empty(static::$publishes[$provider]) && ! empty(static::$publishGroups[$group])) {
            return array_intersect_key(static::$publishes[$provider], static::$publishGroups[$group]);
        }

        return [];
    }

    /**
     * Get the service providers available for publishing.
     *
     * @return array
     */
    public static function publishableProviders()
    {
        return array_keys(static::$publishes);
    }

    /**
     * Get the migration paths available for publishing.
     *
     * @return array
     */
    public static function publishableMigrationPaths()
    {
        return static::$publishableMigrationPaths;
    }

    /**
     * Get the groups available for publishing.
     *
     * @return array
     */
    public static function publishableGroups()
    {
        return array_keys(static::$publishGroups);
    }

    /**
     * Register the package's custom Artisan commands.
     *
     * @param  mixed  $commands
     * @return void
     */
    public function commands($commands)
    {
        $commands = is_array($commands) ? $commands : func_get_args();

        Artisan::starting(function ($artisan) use ($commands) {
            $artisan->resolveCommands($commands);
        });
    }

    /**
     * Register commands that should run on "optimize" or "optimize:clear".
     *
     * @param  string|null  $optimize
     * @param  string|null  $clear
     * @param  string|null  $key
     * @return void
     */
    protected function optimizes(?string $optimize = null, ?string $clear = null, ?string $key = null)
    {
        $key = $this->getProviderKey($key);

        if ($optimize) {
            static::$optimizeCommands[$key] = $optimize;
        }

        if ($clear) {
            static::$optimizeClearCommands[$key] = $clear;
        }
    }

    /**
     * Register commands that should run on "reload".
     *
     * @param  string|null  $reload
     * @param  string|null  $key
     * @return void
     */
    protected function reloads(string $reload, ?string $key = null)
    {
        $key = $this->getProviderKey($key);

        static::$reloadCommands[$key] = $reload;
    }

    /**
     * Get a short descriptive key for the current service provider.
     *
     * @param  string|null  $key
     * @return string
     */
    protected function getProviderKey(?string $key = null): string
    {
        $key ??= (string) Str::of(get_class($this))
            ->classBasename()
            ->before('ServiceProvider')
            ->kebab()
            ->lower()
            ->trim();

        if (empty($key)) {
            $key = class_basename(get_class($this));
        }

        return $key;
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [];
    }

    /**
     * Get the events that trigger this service provider to register.
     *
     * @return array
     */
    public function when()
    {
        return [];
    }

    /**
     * Determine if the provider is deferred.
     *
     * @return bool
     */
    public function isDeferred()
    {
        return $this instanceof DeferrableProvider;
    }

    /**
     * Get the default providers for a Laravel application.
     *
     * @return \Illuminate\Support\DefaultProviders
     */
    public static function defaultProviders()
    {
        return new DefaultProviders;
    }

    /**
     * Add the given provider to the application's provider bootstrap file.
     *
     * @param  string  $provider
     * @param  string|null  $path
     * @return bool
     */
    public static function addProviderToBootstrapFile(string $provider, ?string $path = null)
    {
        $path ??= app()->getBootstrapProvidersPath();

        if (! file_exists($path)) {
            return false;
        }

        if (function_exists('opcache_invalidate')) {
            opcache_invalidate($path, true);
        }

        $providers = (new Collection(require $path))
            ->merge([$provider])
            ->unique()
            ->sort()
            ->values()
            ->map(fn ($p) => '    '.$p.'::class,')
            ->implode(PHP_EOL);

        $content = '<?php

return [
'.$providers.'
];';

        file_put_contents($path, $content.PHP_EOL);

        return true;
    }

    /**
     * Remove a provider from the application's provider bootstrap file.
     *
     * @param  string|array  $providersToRemove
     * @param  string|null  $path
     * @param  bool  $strict
     * @return bool
     */
    public static function removeProviderFromBootstrapFile(string|array $providersToRemove, ?string $path = null, bool $strict = false)
    {
        $path ??= app()->getBootstrapProvidersPath();

        if (! file_exists($path)) {
            return false;
        }

        if (function_exists('opcache_invalidate')) {
            opcache_invalidate($path, true);
        }

        $providersToRemove = Arr::wrap($providersToRemove);

        $providers = (new Collection(require $path))
            ->unique()
            ->sort()
            ->values()
            ->when(
                $strict,
                static fn (Collection $providerCollection) => $providerCollection->reject(fn (string $p) => in_array($p, $providersToRemove, true)),
                static fn (Collection $providerCollection) => $providerCollection->reject(fn (string $p) => Str::contains($p, $providersToRemove))
            )
            ->map(fn ($p) => '    '.$p.'::class,')
            ->implode(PHP_EOL);

        $content = '<?php

return [
'.$providers.'
];';

        file_put_contents($path, $content.PHP_EOL);

        return true;
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Contracts\Container\Container;
use InvalidArgumentException;
use ReflectionException;
use RuntimeException;

abstract class Manager
{
    use RebindsCallbacksToSelf;

    /**
     * The container instance.
     *
     * @var \Illuminate\Contracts\Container\Container
     */
    protected $container;

    /**
     * The configuration repository instance.
     *
     * @var \Illuminate\Contracts\Config\Repository
     */
    protected $config;

    /**
     * The registered custom driver creators.
     *
     * @var array<string, \Closure>
     */
    protected $customCreators = [];

    /**
     * The array of created "drivers".
     *
     * @var array<string, mixed>
     */
    protected $drivers = [];

    /**
     * Create a new manager instance.
     *
     * @param  \Illuminate\Contracts\Container\Container  $container
     */
    public function __construct(Container $container)
    {
        $this->container = $container;
        $this->config = $container->make('config');
    }

    /**
     * Get the default driver name.
     *
     * @return string|null
     */
    abstract public function getDefaultDriver();

    /**
     * Get a driver instance.
     *
     * @param  \UnitEnum|string|null  $driver
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    public function driver($driver = null)
    {
        $driver = enum_value($driver) ?: $this->getDefaultDriver();

        if (is_null($driver)) {
            throw new InvalidArgumentException(sprintf(
                'Unable to resolve NULL driver for [%s].', static::class
            ));
        }

        // If the given driver has not been created before, we will create the instances
        // here and cache it so we can return it next time very quickly. If there is
        // already a driver created by this name, we'll just return that instance.
        return $this->drivers[$driver] ??= $this->createDriver($driver);
    }

    /**
     * Create a new driver instance.
     *
     * @param  string  $driver
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    protected function createDriver($driver)
    {
        // First, we will determine if a custom driver creator exists for the given driver and
        // if it does not we will check for a creator method for the driver. Custom creator
        // callbacks allow developers to build their own "drivers" easily using Closures.
        if (isset($this->customCreators[$driver])) {
            return $this->callCustomCreator($driver);
        }

        $method = 'create'.Str::studly($driver).'Driver';

        if (method_exists($this, $method)) {
            return $this->$method();
        }

        throw new InvalidArgumentException("Driver [$driver] not supported.");
    }

    /**
     * Call a custom driver creator.
     *
     * @param  string  $driver
     * @return mixed
     */
    protected function callCustomCreator($driver)
    {
        return $this->customCreators[$driver]($this->container);
    }

    /**
     * Register a custom driver creator Closure.
     *
     * @param  string  $driver
     *
     * @param-closure-this  $this  $callback
     *
     * @return $this
     */
    public function extend($driver, Closure $callback)
    {
        try {
            $callback = $this->bindCallbackToSelf($callback) ?? throw new RuntimeException('Unable to bind custom driver callback');
        } catch (ReflectionException $e) {
            throw new RuntimeException('Unable to bind custom driver callback', previous: $e);
        }

        $this->customCreators[$driver] = $callback;

        return $this;
    }

    /**
     * Get all of the created "drivers".
     *
     * @return array<string, mixed>
     */
    public function getDrivers()
    {
        return $this->drivers;
    }

    /**
     * Get the container instance used by the manager.
     *
     * @return \Illuminate\Contracts\Container\Container
     */
    public function getContainer()
    {
        return $this->container;
    }

    /**
     * Set the container instance used by the manager.
     *
     * @param  \Illuminate\Contracts\Container\Container  $container
     * @return $this
     */
    public function setContainer(Container $container)
    {
        $this->container = $container;

        return $this;
    }

    /**
     * Forget all of the resolved driver instances.
     *
     * @return $this
     */
    public function forgetDrivers()
    {
        $this->drivers = [];

        return $this;
    }

    /**
     * Dynamically call the default driver instance.
     *
     * @param  string  $method
     * @param  array<string, mixed>  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->driver()->$method(...$parameters);
    }
}
<?php

namespace Illuminate\Support;

use Carbon\CarbonInterval;
use DateInterval;
use DateTimeInterface;

trait InteractsWithTime
{
    /**
     * Get the number of seconds until the given DateTime.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @return int
     */
    protected function secondsUntil($delay)
    {
        $delay = $this->parseDateInterval($delay);

        return $delay instanceof DateTimeInterface
            ? max(0, $delay->getTimestamp() - $this->currentTime())
            : (int) $delay;
    }

    /**
     * Get the "available at" UNIX timestamp.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @return int
     */
    protected function availableAt($delay = 0)
    {
        $delay = $this->parseDateInterval($delay);

        return $delay instanceof DateTimeInterface
            ? $delay->getTimestamp()
            : Carbon::now()->addSeconds($delay)->getTimestamp();
    }

    /**
     * If the given value is an interval, convert it to a DateTime instance.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @return \DateTimeInterface|int
     */
    protected function parseDateInterval($delay)
    {
        if ($delay instanceof DateInterval) {
            $delay = Carbon::now()->add($delay);
        }

        return $delay;
    }

    /**
     * Get the current system time as a UNIX timestamp.
     *
     * @return int
     */
    protected function currentTime()
    {
        return Carbon::now()->getTimestamp();
    }

    /**
     * Given a start time, format the total run time for human readability.
     *
     * @param  float  $startTime
     * @param  float|null  $endTime
     * @return string
     */
    protected function runTimeForHumans($startTime, $endTime = null)
    {
        $endTime ??= microtime(true);

        $runTime = ($endTime - $startTime) * 1000;

        return $runTime > 1000
            ? CarbonInterval::milliseconds($runTime)->cascade()->forHumans(short: true)
            : number_format($runTime, 2).'ms';
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Contracts\Support\HasOnceHash;
use Laravel\SerializableClosure\Support\ReflectionClosure;

class Onceable
{
    /**
     * Create a new onceable instance.
     *
     * @param  string  $hash
     * @param  object|null  $object
     * @param  callable  $callable
     */
    public function __construct(
        public string $hash,
        public ?object $object,
        public $callable,
    ) {
        //
    }

    /**
     * Tries to create a new onceable instance from the given trace.
     *
     * @param  array<int, array<string, mixed>>  $trace
     * @return static|null
     */
    public static function tryFromTrace(array $trace, callable $callable)
    {
        if (! is_null($hash = static::hashFromTrace($trace, $callable))) {
            $object = static::objectFromTrace($trace);

            return new static($hash, $object, $callable);
        }
    }

    /**
     * Computes the object of the onceable from the given trace, if any.
     *
     * @param  array<int, array<string, mixed>>  $trace
     * @return object|null
     */
    protected static function objectFromTrace(array $trace)
    {
        return $trace[1]['object'] ?? null;
    }

    /**
     * Computes the hash of the onceable from the given trace.
     *
     * @param  array<int, array<string, mixed>>  $trace
     * @return string|null
     */
    protected static function hashFromTrace(array $trace, callable $callable)
    {
        if (str_contains($trace[0]['file'] ?? '', 'eval()\'d code')) {
            return null;
        }

        $uses = array_map(
            static function (mixed $argument) {
                if ($argument instanceof HasOnceHash) {
                    return $argument->onceHash();
                }

                if (is_object($argument)) {
                    return spl_object_hash($argument);
                }

                return $argument;
            },
            $callable instanceof Closure ? (new ReflectionClosure($callable))->getClosureUsedVariables() : [],
        );

        $class = $callable instanceof Closure ? (new ReflectionClosure($callable))->getClosureCalledClass()?->getName() : null;

        $class ??= isset($trace[1]['class']) ? $trace[1]['class'] : null;

        return hash('xxh128', sprintf(
            '%s@%s%s:%s (%s)',
            $trace[0]['file'],
            $class ? $class.'@' : '',
            $trace[1]['function'],
            $trace[0]['line'],
            serialize($uses),
        ));
    }
}
<?php

namespace Illuminate\Support;

use InvalidArgumentException;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Uid\Ulid;

class BinaryCodec
{
    /** @var array<string, array{encode: callable(UuidInterface|Ulid|string|null): ?string, decode: callable(?string): ?string}> */
    protected static array $customCodecs = [];

    /**
     * Register a custom codec.
     */
    public static function register(string $name, callable $encode, callable $decode): void
    {
        self::$customCodecs[$name] = [
            'encode' => $encode,
            'decode' => $decode,
        ];
    }

    /**
     * Encode a value to binary.
     *
     * @throws \InvalidArgumentException
     */
    public static function encode(UuidInterface|Ulid|string|null $value, string $format): ?string
    {
        if (blank($value)) {
            return null;
        }

        if (isset(self::$customCodecs[$format])) {
            return (self::$customCodecs[$format]['encode'])($value);
        }

        return match ($format) {
            'uuid' => match (true) {
                $value instanceof UuidInterface => $value->getBytes(),
                self::isBinary($value) => $value,
                default => Uuid::fromString($value)->getBytes(),
            },
            'ulid' => match (true) {
                $value instanceof Ulid => $value->toBinary(),
                self::isBinary($value) => $value,
                default => Ulid::fromString($value)->toBinary(),
            },
            default => throw new InvalidArgumentException("Format [$format] is invalid."),
        };
    }

    /**
     * Decode a binary value to string.
     *
     * @throws \InvalidArgumentException
     */
    public static function decode(?string $value, string $format): ?string
    {
        if (blank($value)) {
            return null;
        }

        if (isset(self::$customCodecs[$format])) {
            return (self::$customCodecs[$format]['decode'])($value);
        }

        return match ($format) {
            'uuid' => (self::isBinary($value) ? Uuid::fromBytes($value) : Uuid::fromString($value))->toString(),
            'ulid' => (self::isBinary($value) ? Ulid::fromBinary($value) : Ulid::fromString($value))->toString(),
            default => throw new InvalidArgumentException("Format [$format] is invalid."),
        };
    }

    /**
     * Get all available format names.
     *
     * @return array<string>
     */
    public static function formats(): array
    {
        return array_unique([...['uuid', 'ulid'], ...array_keys(self::$customCodecs)]);
    }

    /**
     * Determine if the given value is binary data.
     */
    public static function isBinary(mixed $value): bool
    {
        if (! is_string($value) || $value === '') {
            return false;
        }

        if (str_contains($value, "\0")) {
            return true;
        }

        return ! mb_check_encoding($value, 'UTF-8');
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Dotenv\Repository\Adapter\PutenvAdapter;
use Dotenv\Repository\RepositoryBuilder;
use Illuminate\Filesystem\Filesystem;
use PhpOption\Option;
use RuntimeException;

class Env
{
    /**
     * Indicates if the putenv adapter is enabled.
     *
     * @var bool
     */
    protected static $putenv = true;

    /**
     * The environment repository instance.
     *
     * @var \Dotenv\Repository\RepositoryInterface|null
     */
    protected static $repository;

    /**
     * The list of custom adapters for loading environment variables.
     *
     * @var array<Closure>
     */
    protected static $customAdapters = [];

    /**
     * Enable the putenv adapter.
     *
     * @return void
     */
    public static function enablePutenv()
    {
        static::$putenv = true;
        static::$repository = null;
    }

    /**
     * Disable the putenv adapter.
     *
     * @return void
     */
    public static function disablePutenv()
    {
        static::$putenv = false;
        static::$repository = null;
    }

    /**
     * Register a custom adapter creator Closure.
     */
    public static function extend(Closure $callback, ?string $name = null): void
    {
        if (! is_null($name)) {
            static::$customAdapters[$name] = $callback;
        } else {
            static::$customAdapters[] = $callback;
        }

        static::$repository = null;
    }

    /**
     * Get the environment repository instance.
     *
     * @return \Dotenv\Repository\RepositoryInterface
     */
    public static function getRepository()
    {
        if (static::$repository === null) {
            $builder = RepositoryBuilder::createWithDefaultAdapters();

            if (static::$putenv) {
                $builder = $builder->addAdapter(PutenvAdapter::class);
            }

            foreach (static::$customAdapters as $adapter) {
                $builder = $builder->addAdapter($adapter());
            }

            static::$repository = $builder->immutable()->make();
        }

        return static::$repository;
    }

    /**
     * Get the value of an environment variable.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return mixed
     */
    public static function get($key, $default = null)
    {
        return self::getOption($key)->getOrCall(fn () => value($default));
    }

    /**
     * Get the value of a required environment variable.
     *
     * @param  string  $key
     * @return mixed
     *
     * @throws \RuntimeException
     */
    public static function getOrFail($key)
    {
        return self::getOption($key)->getOrThrow(new RuntimeException("Environment variable [$key] has no value."));
    }

    /**
     * Write an array of key-value pairs to the environment file.
     *
     * @param  array<string, mixed>  $variables
     * @param  string  $pathToFile
     * @param  bool  $overwrite
     * @return void
     *
     * @throws \RuntimeException
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public static function writeVariables(array $variables, string $pathToFile, bool $overwrite = false): void
    {
        $filesystem = new Filesystem;

        if ($filesystem->missing($pathToFile)) {
            throw new RuntimeException("The file [{$pathToFile}] does not exist.");
        }

        $lines = explode(PHP_EOL, $filesystem->get($pathToFile));

        foreach ($variables as $key => $value) {
            $lines = self::addVariableToEnvContents($key, $value, $lines, $overwrite);
        }

        $filesystem->put($pathToFile, implode(PHP_EOL, $lines));
    }

    /**
     * Write a single key-value pair to the environment file.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @param  string  $pathToFile
     * @param  bool  $overwrite
     * @return void
     *
     * @throws \RuntimeException
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public static function writeVariable(string $key, mixed $value, string $pathToFile, bool $overwrite = false): void
    {
        $filesystem = new Filesystem;

        if ($filesystem->missing($pathToFile)) {
            throw new RuntimeException("The file [{$pathToFile}] does not exist.");
        }

        $envContent = $filesystem->get($pathToFile);

        $lines = explode(PHP_EOL, $envContent);
        $lines = self::addVariableToEnvContents($key, $value, $lines, $overwrite);

        $filesystem->put($pathToFile, implode(PHP_EOL, $lines));
    }

    /**
     * Add a variable to the environment file contents.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @param  array<int, string>  $envLines
     * @param  bool  $overwrite
     * @return array<int, string>
     */
    protected static function addVariableToEnvContents(string $key, mixed $value, array $envLines, bool $overwrite): array
    {
        $prefix = explode('_', $key)[0].'_';
        $lastPrefixIndex = -1;

        $shouldQuote = preg_match('/^[a-zA-z0-9]+$/', $value) === 0;

        $lineToAddVariations = [
            $key.'='.(is_string($value) ? self::prepareQuotedValue($value) : $value),
            $key.'='.$value,
        ];

        $lineToAdd = $shouldQuote ? $lineToAddVariations[0] : $lineToAddVariations[1];

        if ($value === '') {
            $lineToAdd = $key.'=';
        }

        foreach ($envLines as $index => $line) {
            if (str_starts_with($line, $prefix)) {
                $lastPrefixIndex = $index;
            }

            if (in_array($line, $lineToAddVariations)) {
                // This exact line already exists, so we don't need to add it again.
                return $envLines;
            }

            if ($line === $key.'=') {
                // If the value is empty, we can replace it with the new value.
                $envLines[$index] = $lineToAdd;

                return $envLines;
            }

            if (str_starts_with($line, $key.'=')) {
                if (! $overwrite) {
                    return $envLines;
                }

                $envLines[$index] = $lineToAdd;

                return $envLines;
            }
        }

        if ($lastPrefixIndex === -1) {
            if (count($envLines) && $envLines[count($envLines) - 1] !== '') {
                $envLines[] = '';
            }

            return array_merge($envLines, [$lineToAdd]);
        }

        return array_merge(
            array_slice($envLines, 0, $lastPrefixIndex + 1),
            [$lineToAdd],
            array_slice($envLines, $lastPrefixIndex + 1)
        );
    }

    /**
     * Get the possible option for this environment variable.
     *
     * @param  string  $key
     * @return \PhpOption\Option|\PhpOption\Some
     */
    protected static function getOption($key)
    {
        return Option::fromValue(static::getRepository()->get($key))
            ->map(function ($value) {
                switch (strtolower($value)) {
                    case 'true':
                    case '(true)':
                        return true;
                    case 'false':
                    case '(false)':
                        return false;
                    case 'empty':
                    case '(empty)':
                        return '';
                    case 'null':
                    case '(null)':
                        return;
                }

                if (preg_match('/\A([\'"])(.*)\1\z/', $value, $matches)) {
                    return $matches[2];
                }

                return $value;
            });
    }

    /**
     * Wrap a string in quotes, choosing double or single quotes.
     *
     * @param  string  $input
     * @return string
     */
    protected static function prepareQuotedValue(string $input)
    {
        return str_contains($input, '"')
            ? "'".self::addSlashesExceptFor($input, ['"'])."'"
            : '"'.self::addSlashesExceptFor($input, ["'"]).'"';
    }

    /**
     * Escape a string using addslashes, excluding the specified characters from being escaped.
     *
     * @param  string  $value
     * @param  array<string>  $except
     * @return string
     */
    protected static function addSlashesExceptFor(string $value, array $except = [])
    {
        $escaped = addslashes($value);

        foreach ($except as $character) {
            $escaped = str_replace('\\'.$character, $character, $escaped);
        }

        return $escaped;
    }
}
<?php

namespace Illuminate\Support;

use Carbon\Factory;
use InvalidArgumentException;

/**
 * @see https://carbon.nesbot.com/docs/
 * @see https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Factory.php
 *
 * @method bool canBeCreatedFromFormat(?string $date, string $format)
 * @method \Illuminate\Support\Carbon|null create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null)
 * @method \Illuminate\Support\Carbon createFromDate($year = null, $month = null, $day = null, $timezone = null)
 * @method \Illuminate\Support\Carbon|null createFromFormat($format, $time, $timezone = null)
 * @method \Illuminate\Support\Carbon|null createFromIsoFormat(string $format, string $time, $timezone = null, ?string $locale = 'en', ?\Symfony\Contracts\Translation\TranslatorInterface $translator = null)
 * @method \Illuminate\Support\Carbon|null createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null)
 * @method \Illuminate\Support\Carbon|null createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null)
 * @method \Illuminate\Support\Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null)
 * @method \Illuminate\Support\Carbon createFromTimeString(string $time, \DateTimeZone|string|int|null $timezone = null)
 * @method \Illuminate\Support\Carbon createFromTimestamp(string|int|float $timestamp, \DateTimeZone|string|int|null $timezone = null)
 * @method \Illuminate\Support\Carbon createFromTimestampMs(string|int|float $timestamp, \DateTimeZone|string|int|null $timezone = null)
 * @method \Illuminate\Support\Carbon createFromTimestampMsUTC($timestamp)
 * @method \Illuminate\Support\Carbon createFromTimestampUTC(string|int|float $timestamp)
 * @method \Illuminate\Support\Carbon createMidnightDate($year = null, $month = null, $day = null, $timezone = null)
 * @method \Illuminate\Support\Carbon|null createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null)
 * @method \Illuminate\Support\Carbon createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null)
 * @method void disableHumanDiffOption($humanDiffOption)
 * @method void enableHumanDiffOption($humanDiffOption)
 * @method mixed executeWithLocale(string $locale, callable $func)
 * @method \Illuminate\Support\Carbon fromSerialized($value)
 * @method array getAvailableLocales()
 * @method array getAvailableLocalesInfo()
 * @method array getDays()
 * @method ?string getFallbackLocale()
 * @method array getFormatsToIsoReplacements()
 * @method int getHumanDiffOptions()
 * @method array getIsoUnits()
 * @method array|false getLastErrors()
 * @method string getLocale()
 * @method int getMidDayAt()
 * @method string getTimeFormatByPrecision(string $unitPrecision)
 * @method string|\Closure|null getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)
 * @method \Illuminate\Support\Carbon|null getTestNow()
 * @method \Symfony\Contracts\Translation\TranslatorInterface getTranslator()
 * @method int getWeekEndsAt(?string $locale = null)
 * @method int getWeekStartsAt(?string $locale = null)
 * @method array getWeekendDays()
 * @method bool hasFormat(string $date, string $format)
 * @method bool hasFormatWithModifiers(string $date, string $format)
 * @method bool hasMacro($name)
 * @method bool hasRelativeKeywords(?string $time)
 * @method bool hasTestNow()
 * @method \Illuminate\Support\Carbon instance(\DateTimeInterface $date)
 * @method bool isImmutable()
 * @method bool isModifiableUnit($unit)
 * @method bool isMutable()
 * @method bool isStrictModeEnabled()
 * @method bool localeHasDiffOneDayWords(string $locale)
 * @method bool localeHasDiffSyntax(string $locale)
 * @method bool localeHasDiffTwoDayWords(string $locale)
 * @method bool localeHasPeriodSyntax($locale)
 * @method bool localeHasShortUnits(string $locale)
 * @method void macro(string $name, ?callable $macro)
 * @method \Illuminate\Support\Carbon|null make($var, \DateTimeZone|string|null $timezone = null)
 * @method void mixin(object|string $mixin)
 * @method \Illuminate\Support\Carbon now(\DateTimeZone|string|int|null $timezone = null)
 * @method \Illuminate\Support\Carbon parse(\DateTimeInterface|\Carbon\WeekDay|\Carbon\Month|string|int|float|null $time, \DateTimeZone|string|int|null $timezone = null)
 * @method \Illuminate\Support\Carbon parseFromLocale(string $time, ?string $locale = null, \DateTimeZone|string|int|null $timezone = null)
 * @method string pluralUnit(string $unit)
 * @method \Illuminate\Support\Carbon|null rawCreateFromFormat(string $format, string $time, $timezone = null)
 * @method \Illuminate\Support\Carbon rawParse(\DateTimeInterface|\Carbon\WeekDay|\Carbon\Month|string|int|float|null $time, \DateTimeZone|string|int|null $timezone = null)
 * @method void resetMonthsOverflow()
 * @method void resetToStringFormat()
 * @method void resetYearsOverflow()
 * @method void serializeUsing($callback)
 * @method void setFallbackLocale(string $locale)
 * @method void setHumanDiffOptions($humanDiffOptions)
 * @method void setLocale(string $locale)
 * @method void setMidDayAt($hour)
 * @method void setTestNow(mixed $testNow = null)
 * @method void setTestNowAndTimezone(mixed $testNow = null, $timezone = null)
 * @method void setToStringFormat(string|\Closure|null $format)
 * @method void setTranslator(\Symfony\Contracts\Translation\TranslatorInterface $translator)
 * @method void setWeekEndsAt($day)
 * @method void setWeekStartsAt($day)
 * @method void setWeekendDays($days)
 * @method bool shouldOverflowMonths()
 * @method bool shouldOverflowYears()
 * @method string singularUnit(string $unit)
 * @method void sleep(int|float $seconds)
 * @method \Illuminate\Support\Carbon today(\DateTimeZone|string|int|null $timezone = null)
 * @method \Illuminate\Support\Carbon tomorrow(\DateTimeZone|string|int|null $timezone = null)
 * @method string translateTimeString(string $timeString, ?string $from = null, ?string $to = null, int $mode = \Carbon\CarbonInterface::TRANSLATE_ALL)
 * @method string translateWith(\Symfony\Contracts\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null)
 * @method void useMonthsOverflow($monthsOverflow = true)
 * @method void useStrictMode($strictModeEnabled = true)
 * @method void useYearsOverflow($yearsOverflow = true)
 * @method mixed withTestNow(mixed $testNow, callable $callback)
 * @method static withTimeZone(\DateTimeZone|string|int|null $timezone)
 * @method \Illuminate\Support\Carbon yesterday(\DateTimeZone|string|int|null $timezone = null)
 */
class DateFactory
{
    /**
     * The default class that will be used for all created dates.
     *
     * @var string
     */
    const DEFAULT_CLASS_NAME = Carbon::class;

    /**
     * The type (class) of dates that should be created.
     *
     * @var string
     */
    protected static $dateClass;

    /**
     * This callable may be used to intercept date creation.
     *
     * @var callable
     */
    protected static $callable;

    /**
     * The Carbon factory that should be used when creating dates.
     *
     * @var object
     */
    protected static $factory;

    /**
     * Use the given handler when generating dates (class name, callable, or factory).
     *
     * @param  mixed  $handler
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    public static function use($handler)
    {
        if (is_callable($handler) && is_object($handler)) {
            return static::useCallable($handler);
        } elseif (is_string($handler)) {
            return static::useClass($handler);
        } elseif ($handler instanceof Factory) {
            return static::useFactory($handler);
        }

        throw new InvalidArgumentException('Invalid date creation handler. Please provide a class name, callable, or Carbon factory.');
    }

    /**
     * Use the default date class when generating dates.
     *
     * @return void
     */
    public static function useDefault()
    {
        static::$dateClass = null;
        static::$callable = null;
        static::$factory = null;
    }

    /**
     * Execute the given callable on each date creation.
     *
     * @param  callable  $callable
     * @return void
     */
    public static function useCallable(callable $callable)
    {
        static::$callable = $callable;

        static::$dateClass = null;
        static::$factory = null;
    }

    /**
     * Use the given date type (class) when generating dates.
     *
     * @param  string  $dateClass
     * @return void
     */
    public static function useClass($dateClass)
    {
        static::$dateClass = $dateClass;

        static::$factory = null;
        static::$callable = null;
    }

    /**
     * Use the given Carbon factory when generating dates.
     *
     * @param  object  $factory
     * @return void
     */
    public static function useFactory($factory)
    {
        static::$factory = $factory;

        static::$dateClass = null;
        static::$callable = null;
    }

    /**
     * Handle dynamic calls to generate dates.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \RuntimeException
     */
    public function __call($method, $parameters)
    {
        $defaultClassName = static::DEFAULT_CLASS_NAME;

        // Using callable to generate dates...
        if (static::$callable) {
            return call_user_func(static::$callable, $defaultClassName::$method(...$parameters));
        }

        // Using Carbon factory to generate dates...
        if (static::$factory) {
            return static::$factory->$method(...$parameters);
        }

        $dateClass = static::$dateClass ?: $defaultClassName;

        // Check if the date can be created using the public class method...
        if (method_exists($dateClass, $method) ||
            method_exists($dateClass, 'hasMacro') && $dateClass::hasMacro($method)) {
            return $dateClass::$method(...$parameters);
        }

        // If that fails, create the date with the default class...
        $date = $defaultClassName::$method(...$parameters);

        // If the configured class has an "instance" method, we'll try to pass our date into there...
        if (method_exists($dateClass, 'instance')) {
            return $dateClass::instance($date);
        }

        // Otherwise, assume the configured class has a DateTime compatible constructor...
        return new $dateClass($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
    }
}
<?php

namespace Illuminate\Support;

class NamespacedItemResolver
{
    /**
     * A cache of the parsed items.
     *
     * @var array
     */
    protected $parsed = [];

    /**
     * Parse a key into namespace, group, and item.
     *
     * @param  string  $key
     * @return array
     */
    public function parseKey($key)
    {
        // If we've already parsed the given key, we'll return the cached version we
        // already have, as this will save us some processing. We cache off every
        // key we parse so we can quickly return it on all subsequent requests.
        if (isset($this->parsed[$key])) {
            return $this->parsed[$key];
        }

        // If the key does not contain a double colon, it means the key is not in a
        // namespace, and is just a regular configuration item. Namespaces are a
        // tool for organizing configuration items for things such as modules.
        if (! str_contains($key, '::')) {
            $segments = explode('.', $key);

            $parsed = $this->parseBasicSegments($segments);
        } else {
            $parsed = $this->parseNamespacedSegments($key);
        }

        // Once we have the parsed array of this key's elements, such as its groups
        // and namespace, we will cache each array inside a simple list that has
        // the key and the parsed array for quick look-ups for later requests.
        return $this->parsed[$key] = $parsed;
    }

    /**
     * Parse an array of basic segments.
     *
     * @param  array  $segments
     * @return array
     */
    protected function parseBasicSegments(array $segments)
    {
        // The first segment in a basic array will always be the group, so we can go
        // ahead and grab that segment. If there is only one total segment we are
        // just pulling an entire group out of the array and not a single item.
        $group = $segments[0];

        // If there is more than one segment in this group, it means we are pulling
        // a specific item out of a group and will need to return this item name
        // as well as the group so we know which item to pull from the arrays.
        $item = count($segments) === 1
            ? null
            : implode('.', array_slice($segments, 1));

        return [null, $group, $item];
    }

    /**
     * Parse an array of namespaced segments.
     *
     * @param  string  $key
     * @return array
     */
    protected function parseNamespacedSegments($key)
    {
        [$namespace, $item] = explode('::', $key);

        // First we'll just explode the first segment to get the namespace and group
        // since the item should be in the remaining segments. Once we have these
        // two pieces of data we can proceed with parsing out the item's value.
        $itemSegments = explode('.', $item);

        $groupAndItem = array_slice(
            $this->parseBasicSegments($itemSegments), 1
        );

        return array_merge([$namespace], $groupAndItem);
    }

    /**
     * Set the parsed value of a key.
     *
     * @param  string  $key
     * @param  array  $parsed
     * @return void
     */
    public function setParsedKey($key, $parsed)
    {
        $this->parsed[$key] = $parsed;
    }

    /**
     * Flush the cache of parsed keys.
     *
     * @return void
     */
    public function flushParsedKeys()
    {
        $this->parsed = [];
    }
}
<?php

namespace Illuminate\Support\Traits;

use Exception;
use ReflectionClass;

trait ReadsClassAttributes
{
    /**
     * Get a configuration value from an attribute, falling back to a property.
     *
     * @param  object  $target
     * @param  class-string  $attributeClass
     * @param  string|null  $property
     * @param  mixed  $default
     * @return mixed
     */
    protected function getAttributeValue($target, string $attributeClass, ?string $property = null, $default = null)
    {
        $reflection = new ReflectionClass($target);

        $defaultProperties = $reflection->getDefaultProperties();

        if (isset($target->{$property}) && $target->{$property} !== ($defaultProperties[$property] ?? null)) {
            return $target->{$property};
        }

        if ($instance = $this->getAttributeInstance($target, $attributeClass)) {
            return $this->extractAttributeValue($instance);
        }

        return $target->{$property} ?? $default;
    }

    /**
     * Extract the value from an attribute instance.
     *
     * @param  object  $instance
     * @return mixed
     */
    protected function extractAttributeValue($instance)
    {
        $properties = get_object_vars($instance);

        return $properties === [] ? true : reset($properties);
    }

    /**
     * Get an instance of the given attribute class from the target class or its parents.
     *
     * @param  object  $target
     * @param  class-string  $attributeClass
     * @return object|null
     */
    protected function getAttributeInstance($target, string $attributeClass)
    {
        $reflection = new ReflectionClass($target);

        try {
            do {
                $attributes = $reflection->getAttributes($attributeClass);

                if (count($attributes) > 0) {
                    return $attributes[0]->newInstance();
                }
            } while ($reflection = $reflection->getParentClass());
        } catch (Exception) {
            //
        }

        return null;
    }
}
<?php

namespace Illuminate\Support\Traits;

use Carbon\CarbonInterval;
use Carbon\Unit;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Number;
use Illuminate\Support\Str;
use stdClass;

use function Illuminate\Support\enum_value;

trait InteractsWithData
{
    /**
     * Retrieve all data from the instance.
     *
     * @param  mixed  $keys
     * @return array
     */
    abstract public function all($keys = null);

    /**
     * Retrieve data from the instance.
     *
     * @param  string|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    abstract protected function data($key = null, $default = null);

    /**
     * Determine if the data contains a given key.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function exists($key)
    {
        return $this->has($key);
    }

    /**
     * Determine if the data contains a given key.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function has($key)
    {
        $keys = is_array($key) ? $key : func_get_args();

        $data = $this->all();

        foreach ($keys as $value) {
            if (! Arr::has($data, $value)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determine if the instance contains any of the given keys.
     *
     * @param  string|array  $keys
     * @return bool
     */
    public function hasAny($keys)
    {
        $keys = is_array($keys) ? $keys : func_get_args();

        $data = $this->all();

        return Arr::hasAny($data, $keys);
    }

    /**
     * Apply the callback if the instance contains the given key.
     *
     * @param  string  $key
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return $this|mixed
     */
    public function whenHas($key, callable $callback, ?callable $default = null)
    {
        if ($this->has($key)) {
            return $callback(data_get($this->all(), $key)) ?: $this;
        }

        if ($default) {
            return $default();
        }

        return $this;
    }

    /**
     * Determine if the instance contains a non-empty value for the given key.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function filled($key)
    {
        $keys = is_array($key) ? $key : func_get_args();

        foreach ($keys as $value) {
            if ($this->isEmptyString($value)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determine if the instance contains an empty value for the given key.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function isNotFilled($key)
    {
        $keys = is_array($key) ? $key : func_get_args();

        foreach ($keys as $value) {
            if (! $this->isEmptyString($value)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determine if the instance contains a non-empty value for any of the given keys.
     *
     * @param  string|array  $keys
     * @return bool
     */
    public function anyFilled($keys)
    {
        $keys = is_array($keys) ? $keys : func_get_args();

        foreach ($keys as $key) {
            if ($this->filled($key)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Apply the callback if the instance contains a non-empty value for the given key.
     *
     * @param  string  $key
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return $this|mixed
     */
    public function whenFilled($key, callable $callback, ?callable $default = null)
    {
        if ($this->filled($key)) {
            return $callback(data_get($this->all(), $key)) ?: $this;
        }

        if ($default) {
            return $default();
        }

        return $this;
    }

    /**
     * Determine if the instance is missing a given key.
     *
     * @param  string|array  $key
     * @return bool
     */
    public function missing($key)
    {
        $keys = is_array($key) ? $key : func_get_args();

        return ! $this->has($keys);
    }

    /**
     * Apply the callback if the instance is missing the given key.
     *
     * @param  string  $key
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return $this|mixed
     */
    public function whenMissing($key, callable $callback, ?callable $default = null)
    {
        if ($this->missing($key)) {
            return $callback(data_get($this->all(), $key)) ?: $this;
        }

        if ($default) {
            return $default();
        }

        return $this;
    }

    /**
     * Determine if the given key is an empty string for "filled".
     *
     * @param  string  $key
     * @return bool
     */
    protected function isEmptyString($key)
    {
        $value = $this->data($key);

        return ! is_bool($value) && ! is_array($value) && trim((string) $value) === '';
    }

    /**
     * Retrieve data from the instance as a Stringable instance.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return \Illuminate\Support\Stringable
     */
    public function str($key, $default = null)
    {
        return $this->string($key, $default);
    }

    /**
     * Retrieve data from the instance as a Stringable instance.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return \Illuminate\Support\Stringable
     */
    public function string($key, $default = null)
    {
        return Str::of($this->data($key, $default));
    }

    /**
     * Retrieve data as a boolean value.
     *
     * Returns true when value is "1", "true", "on", and "yes". Otherwise, returns false.
     *
     * @param  string|null  $key
     * @param  bool  $default
     * @return bool
     */
    public function boolean($key = null, $default = false)
    {
        return filter_var($this->data($key, $default), FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * Retrieve data as an integer value.
     *
     * @param  string  $key
     * @param  int  $default
     * @return int
     */
    public function integer($key, $default = 0)
    {
        return (int) $this->data($key, $default);
    }

    /**
     * Retrieve data as a float value.
     *
     * @param  string  $key
     * @param  float  $default
     * @return float
     */
    public function float($key, $default = 0.0)
    {
        return (float) $this->data($key, $default);
    }

    /**
     * Retrieve data clamped between min and max values.
     *
     * @param  string  $key
     * @param  int|float  $min
     * @param  int|float  $max
     * @param  int|float  $default
     * @return float|int
     */
    public function clamp($key, $min, $max, $default = 0)
    {
        return Number::clamp($this->data($key, $default), $min, $max);
    }

    /**
     * Retrieve data from the instance as a Carbon instance.
     *
     * @param  string  $key
     * @param  string|null  $format
     * @param  \UnitEnum|string|null  $tz
     * @return \Illuminate\Support\Carbon|null
     *
     * @throws \Carbon\Exceptions\InvalidFormatException
     */
    public function date($key, $format = null, $tz = null)
    {
        $tz = enum_value($tz);

        if ($this->isNotFilled($key)) {
            return null;
        }

        if (is_null($format)) {
            return Date::parse($this->data($key), $tz);
        }

        return Date::createFromFormat($format, $this->data($key), $tz);
    }

    /**
     * Retrieve data from the instance as a CarbonInterval instance.
     *
     * @param  string  $key
     * @param  \Carbon\Unit|string|null  $unit
     * @return \Carbon\CarbonInterval|null
     */
    public function interval($key, $unit = null)
    {
        if ($this->isNotFilled($key)) {
            return null;
        }

        $value = $this->data($key);

        if (is_null($unit)) {
            return CarbonInterval::make($value);
        }

        $unit = $unit instanceof Unit ? $unit : Unit::fromName($unit);

        return CarbonInterval::fromString(number_format((float) $value, 10, '.', '').' '.$unit->name);
    }

    /**
     * Retrieve data from the instance as an enum.
     *
     * @template TEnum of \BackedEnum
     * @template TDefault of TEnum|null
     *
     * @param  string  $key
     * @param  class-string<TEnum>  $enumClass
     * @param  TDefault  $default
     * @return TEnum|TDefault
     */
    public function enum($key, $enumClass, $default = null)
    {
        if ($this->isNotFilled($key) || ! $this->isBackedEnum($enumClass)) {
            return value($default);
        }

        return $enumClass::tryFrom($this->data($key)) ?: value($default);
    }

    /**
     * Retrieve data from the instance as an array of enums.
     *
     * @template TEnum of \BackedEnum
     *
     * @param  string  $key
     * @param  class-string<TEnum>  $enumClass
     * @return TEnum[]
     */
    public function enums($key, $enumClass)
    {
        if ($this->isNotFilled($key) || ! $this->isBackedEnum($enumClass)) {
            return [];
        }

        return $this->collect($key)
            ->map(fn ($value) => $enumClass::tryFrom($value))
            ->filter()
            ->all();
    }

    /**
     * Determine if the given enum class is backed.
     *
     * @param  class-string  $enumClass
     * @return bool
     */
    protected function isBackedEnum($enumClass)
    {
        return is_a($enumClass, \BackedEnum::class, true);
    }

    /**
     * Retrieve data from the instance as an array.
     *
     * @param  array|string|null  $key
     * @return array
     */
    public function array($key = null)
    {
        return (array) (is_array($key) ? $this->only($key) : $this->data($key));
    }

    /**
     * Retrieve data from the instance as a collection.
     *
     * @param  array|string|null  $key
     * @return \Illuminate\Support\Collection
     */
    public function collect($key = null)
    {
        return new Collection(is_array($key) ? $this->only($key) : $this->data($key));
    }

    /**
     * Get a subset containing the provided keys with values from the instance data.
     *
     * @param  mixed  $keys
     * @return array
     */
    public function only($keys)
    {
        $results = [];

        $data = $this->all();

        $placeholder = new stdClass;

        foreach (is_array($keys) ? $keys : func_get_args() as $key) {
            $value = data_get($data, $key, $placeholder);

            if ($value !== $placeholder) {
                Arr::set($results, $key, $value);
            }
        }

        return $results;
    }

    /**
     * Get all of the data except for a specified array of items.
     *
     * @param  mixed  $keys
     * @return array
     */
    public function except($keys)
    {
        $keys = is_array($keys) ? $keys : func_get_args();

        $results = $this->all();

        Arr::forget($results, $keys);

        return $results;
    }
}
<?php

namespace Illuminate\Support\Traits;

use BadMethodCallException;
use Error;

trait ForwardsCalls
{
    /**
     * Forward a method call to the given object.
     *
     * @param  mixed  $object
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    protected function forwardCallTo($object, $method, $parameters)
    {
        try {
            return $object->{$method}(...$parameters);
        } catch (Error|BadMethodCallException $e) {
            $pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';

            if (! preg_match($pattern, $e->getMessage(), $matches)) {
                throw $e;
            }

            if ($matches['class'] != get_class($object) ||
                $matches['method'] != $method) {
                throw $e;
            }

            static::throwBadMethodCallException($method);
        }
    }

    /**
     * Forward a method call to the given object, returning $this if the forwarded call returned itself.
     *
     * @param  mixed  $object
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    protected function forwardDecoratedCallTo($object, $method, $parameters)
    {
        $result = $this->forwardCallTo($object, $method, $parameters);

        return $result === $object ? $this : $result;
    }

    /**
     * Throw a bad method call exception for the given method.
     *
     * @param  string  $method
     * @return never
     *
     * @throws \BadMethodCallException
     */
    protected static function throwBadMethodCallException($method)
    {
        throw new BadMethodCallException(sprintf(
            'Call to undefined method %s::%s()', static::class, $method
        ));
    }
}
<?php

namespace Illuminate\Support\Traits;

use Illuminate\Container\Container;

trait Localizable
{
    /**
     * Run the callback with the given locale.
     *
     * @param  string  $locale
     * @param  \Closure  $callback
     * @return mixed
     */
    public function withLocale($locale, $callback)
    {
        if (! $locale) {
            return $callback();
        }

        $app = Container::getInstance();

        $original = $app->getLocale();

        try {
            $app->setLocale($locale);

            return $callback();
        } finally {
            $app->setLocale($original);
        }
    }
}
<?php

namespace Illuminate\Support\Traits;

trait Dumpable
{
    /**
     * Dump the given arguments and terminate execution.
     *
     * @param  mixed  ...$args
     * @return never
     */
    public function dd(...$args)
    {
        dd($this, ...$args);
    }

    /**
     * Dump the given arguments.
     *
     * @param  mixed  ...$args
     * @return $this
     */
    public function dump(...$args)
    {
        dump($this, ...$args);

        return $this;
    }
}
<?php

namespace Illuminate\Support\Traits;

trait Tappable
{
    /**
     * Call the given Closure with this instance then return the instance.
     *
     * @param  (callable($this): mixed)|null  $callback
     * @return ($callback is null ? \Illuminate\Support\HigherOrderTapProxy : $this)
     */
    public function tap($callback = null)
    {
        return tap($this, $callback);
    }
}
<?php

namespace Illuminate\Support\Traits;

use Illuminate\Contracts\Container\Container;
use Illuminate\Support\Fluent;

trait CapsuleManagerTrait
{
    /**
     * The current globally used instance.
     *
     * @var object
     */
    protected static $instance;

    /**
     * The container instance.
     *
     * @var \Illuminate\Contracts\Container\Container
     */
    protected $container;

    /**
     * Setup the IoC container instance.
     *
     * @param  \Illuminate\Contracts\Container\Container  $container
     * @return void
     */
    protected function setupContainer(Container $container)
    {
        $this->container = $container;

        if (! $this->container->bound('config')) {
            $this->container->instance('config', new Fluent);
        }
    }

    /**
     * Make this capsule instance available globally.
     *
     * @return void
     */
    public function setAsGlobal()
    {
        static::$instance = $this;
    }

    /**
     * Get the IoC container instance.
     *
     * @return \Illuminate\Contracts\Container\Container
     */
    public function getContainer()
    {
        return $this->container;
    }

    /**
     * Set the IoC container instance.
     *
     * @param  \Illuminate\Contracts\Container\Container  $container
     * @return void
     */
    public function setContainer(Container $container)
    {
        $this->container = $container;
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use InvalidArgumentException;
use ReflectionException;
use RuntimeException;

abstract class MultipleInstanceManager
{
    use RebindsCallbacksToSelf;

    /**
     * The application instance.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected $app;

    /**
     * The configuration repository instance.
     *
     * @var \Illuminate\Contracts\Config\Repository
     */
    protected $config;

    /**
     * The array of resolved instances.
     *
     * @var array
     */
    protected $instances = [];

    /**
     * The registered custom instance creators.
     *
     * @var array
     */
    protected $customCreators = [];

    /**
     * The key name of the "driver" equivalent configuration option.
     *
     * @var string
     */
    protected $driverKey = 'driver';

    /**
     * Create a new manager instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     */
    public function __construct($app)
    {
        $this->app = $app;
        $this->config = $app->make('config');
    }

    /**
     * Get the default instance name.
     *
     * @return string
     */
    abstract public function getDefaultInstance();

    /**
     * Set the default instance name.
     *
     * @param  string  $name
     * @return void
     */
    abstract public function setDefaultInstance($name);

    /**
     * Get the instance specific configuration.
     *
     * @param  string  $name
     * @return array
     */
    abstract public function getInstanceConfig($name);

    /**
     * Get an instance by name.
     *
     * @param  string|null  $name
     * @return mixed
     */
    public function instance($name = null)
    {
        $name = $name ?: $this->getDefaultInstance();

        return $this->instances[$name] = $this->get($name);
    }

    /**
     * Attempt to get an instance from the local cache.
     *
     * @param  string  $name
     * @return mixed
     */
    protected function get($name)
    {
        return $this->instances[$name] ?? $this->resolve($name);
    }

    /**
     * Resolve the given instance.
     *
     * @param  string  $name
     * @return mixed
     *
     * @throws \InvalidArgumentException
     * @throws \RuntimeException
     */
    protected function resolve($name)
    {
        $config = $this->getInstanceConfig($name);

        if (is_null($config)) {
            throw new InvalidArgumentException("Instance [{$name}] is not defined.");
        }

        if (! array_key_exists($this->driverKey, $config)) {
            throw new RuntimeException("Instance [{$name}] does not specify a {$this->driverKey}.");
        }

        $driverName = $config[$this->driverKey];

        if (isset($this->customCreators[$driverName])) {
            return $this->callCustomCreator($config);
        } else {
            $createMethod = 'create'.ucfirst($driverName).ucfirst($this->driverKey);

            if (method_exists($this, $createMethod)) {
                return $this->{$createMethod}($config);
            }

            $createMethod = 'create'.Str::studly($driverName).ucfirst($this->driverKey);

            if (method_exists($this, $createMethod)) {
                return $this->{$createMethod}($config);
            }

            throw new InvalidArgumentException("Instance {$this->driverKey} [{$config[$this->driverKey]}] is not supported.");
        }
    }

    /**
     * Call a custom instance creator.
     *
     * @param  array  $config
     * @return mixed
     */
    protected function callCustomCreator(array $config)
    {
        return $this->customCreators[$config[$this->driverKey]]($this->app, $config);
    }

    /**
     * Unset the given instances.
     *
     * @param  array|string|null  $name
     * @return $this
     */
    public function forgetInstance($name = null)
    {
        $name ??= $this->getDefaultInstance();

        foreach ((array) $name as $instanceName) {
            if (isset($this->instances[$instanceName])) {
                unset($this->instances[$instanceName]);
            }
        }

        return $this;
    }

    /**
     * Disconnect the given instance and remove from local cache.
     *
     * @param  string|null  $name
     * @return void
     */
    public function purge($name = null)
    {
        $name ??= $this->getDefaultInstance();

        unset($this->instances[$name]);
    }

    /**
     * Register a custom instance creator Closure.
     *
     * @param  string  $name
     * @param  \Closure  $callback
     *
     * @param-closure-this  $this  $callback
     *
     * @return $this
     */
    public function extend($name, Closure $callback)
    {
        try {
            $callback = $this->bindCallbackToSelf($callback) ?? throw new RuntimeException('Unable to bind custom driver callback');
        } catch (ReflectionException $e) {
            throw new RuntimeException('Unable to bind custom driver callback', previous: $e);
        }

        $this->customCreators[$name] = $callback;

        return $this;
    }

    /**
     * Set the application instance used by the manager.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return $this
     */
    public function setApplication($app)
    {
        $this->app = $app;

        return $this;
    }

    /**
     * Dynamically call the default instance.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->instance()->$method(...$parameters);
    }
}
<?php

namespace Illuminate\Support;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Traits\InteractsWithData;
use League\Uri\QueryString;
use Stringable;

class UriQueryString implements Arrayable, Stringable
{
    use InteractsWithData;

    /**
     * Create a new URI query string instance.
     */
    public function __construct(protected Uri $uri)
    {
        //
    }

    /**
     * Retrieve all data from the instance.
     *
     * @param  mixed  $keys
     * @return array
     */
    public function all($keys = null)
    {
        $query = $this->toArray();

        if (! $keys) {
            return $query;
        }

        $results = [];

        foreach (is_array($keys) ? $keys : func_get_args() as $key) {
            Arr::set($results, $key, Arr::get($query, $key));
        }

        return $results;
    }

    /**
     * Retrieve data from the instance.
     *
     * @param  string|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    protected function data($key = null, $default = null)
    {
        return $this->get($key, $default);
    }

    /**
     * Get a query string parameter.
     */
    public function get(?string $key = null, mixed $default = null): mixed
    {
        return data_get($this->toArray(), $key, $default);
    }

    /**
     * Get the URL decoded version of the query string.
     */
    public function decode(): string
    {
        return rawurldecode((string) $this);
    }

    /**
     * Get the string representation of the query string.
     */
    public function value(): string
    {
        return (string) $this;
    }

    /**
     * Convert the query string into an array.
     */
    public function toArray()
    {
        return QueryString::extract($this->value());
    }

    /**
     * Get the string representation of the query string.
     */
    public function __toString(): string
    {
        return (string) $this->uri->getUri()->getQuery();
    }
}
<?php

namespace Illuminate\Support;

use BackedEnum;
use Illuminate\Contracts\Support\DeferringDisplayableValue;
use Illuminate\Contracts\Support\Htmlable;

class EncodedHtmlString extends HtmlString
{
    /**
     * The HTML string.
     *
     * @var \Illuminate\Contracts\Support\DeferringDisplayableValue|\Illuminate\Contracts\Support\Htmlable|\BackedEnum|string|int|float|null
     */
    protected $html;

    /**
     * The callback that should be used to encode the HTML strings.
     *
     * @var callable|null
     */
    protected static $encodeUsingFactory;

    /**
     * Create a new encoded HTML string instance.
     *
     * @param  \Illuminate\Contracts\Support\DeferringDisplayableValue|\Illuminate\Contracts\Support\Htmlable|\BackedEnum|string|int|float|null  $html
     * @param  bool  $doubleEncode
     */
    public function __construct($html = '', protected bool $doubleEncode = true)
    {
        parent::__construct($html);
    }

    /**
     * Convert the special characters in the given value.
     *
     * @internal
     *
     * @param  string|null  $value
     * @param  int  $withQuote
     * @param  bool  $doubleEncode
     * @return string
     */
    public static function convert($value, bool $withQuote = true, bool $doubleEncode = true)
    {
        $flag = $withQuote ? ENT_QUOTES : ENT_NOQUOTES;

        return htmlspecialchars($value ?? '', $flag | ENT_SUBSTITUTE, 'UTF-8', $doubleEncode);
    }

    /**
     * Get the HTML string.
     *
     * @return string
     */
    #[\Override]
    public function toHtml()
    {
        $value = $this->html;

        if ($value instanceof DeferringDisplayableValue) {
            $value = $value->resolveDisplayableValue();
        }

        if ($value instanceof Htmlable) {
            return $value->toHtml();
        }

        if ($value instanceof BackedEnum) {
            $value = $value->value;
        }

        return (static::$encodeUsingFactory ?? function ($value, $doubleEncode) {
            return static::convert($value, doubleEncode: $doubleEncode);
        })($value, $this->doubleEncode);
    }

    /**
     * Set the callable that will be used to encode the HTML strings.
     *
     * @param  callable|null  $factory
     * @return void
     */
    public static function encodeUsing(?callable $factory = null)
    {
        static::$encodeUsingFactory = $factory;
    }

    /**
     * Flush the class's global state.
     *
     * @return void
     */
    public static function flushState()
    {
        static::$encodeUsingFactory = null;
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Support\Traits\Macroable;

class Benchmark
{
    use Macroable;

    /**
     * Measure a callable or array of callables over the given number of iterations.
     *
     * @param  \Closure|array<callable>  $benchmarkables
     * @param  int  $iterations
     * @return array<float|int|null>|float
     */
    public static function measure(Closure|array $benchmarkables, int $iterations = 1): array|float
    {
        return Collection::wrap($benchmarkables)->map(function ($callback) use ($iterations) {
            return Collection::range(1, $iterations)->map(function () use ($callback) {
                gc_collect_cycles();

                $start = hrtime(true);

                $callback();

                return (hrtime(true) - $start) / 1_000_000;
            })->average();
        })->when(
            $benchmarkables instanceof Closure,
            fn ($c) => $c->first(),
            fn ($c) => $c->all(),
        );
    }

    /**
     * Measure a callable once and return the result and duration in milliseconds.
     *
     * @template TReturn of mixed
     *
     * @param  (callable(): TReturn)  $callback
     * @return array{0: TReturn, 1: float}
     */
    public static function value(callable $callback): array
    {
        gc_collect_cycles();

        $start = hrtime(true);

        $result = $callback();

        return [$result, (hrtime(true) - $start) / 1_000_000];
    }

    /**
     * Measure a callable or array of callables over the given number of iterations, then dump and die.
     *
     * @param  \Closure|array<callable>  $benchmarkables
     * @param  int  $iterations
     * @return never
     */
    public static function dd(Closure|array $benchmarkables, int $iterations = 1): never
    {
        $result = (new Collection(static::measure(Arr::wrap($benchmarkables), $iterations)))
            ->map(fn ($average) => number_format($average, 3).'ms')
            ->when($benchmarkables instanceof Closure, fn ($c) => $c->first(), fn ($c) => $c->all());

        dd($result);
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Illuminate\Bus\BatchRepository;
use Illuminate\Bus\ChainedBatch;
use Illuminate\Bus\PendingBatch;
use Illuminate\Contracts\Bus\QueueingDispatcher;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
use RuntimeException;

class BusFake implements Fake, QueueingDispatcher
{
    use ReflectsClosures;

    /**
     * The original Bus dispatcher implementation.
     *
     * @var \Illuminate\Contracts\Bus\QueueingDispatcher
     */
    public $dispatcher;

    /**
     * The job types that should be intercepted instead of dispatched.
     *
     * @var array
     */
    protected $jobsToFake = [];

    /**
     * The job types that should be dispatched instead of faked.
     *
     * @var array
     */
    protected $jobsToDispatch = [];

    /**
     * The fake repository to track batched jobs.
     *
     * @var \Illuminate\Bus\BatchRepository
     */
    protected $batchRepository;

    /**
     * The commands that have been dispatched.
     *
     * @var array
     */
    protected $commands = [];

    /**
     * The commands that have been dispatched synchronously.
     *
     * @var array
     */
    protected $commandsSync = [];

    /**
     * The commands that have been dispatched after the response has been sent.
     *
     * @var array
     */
    protected $commandsAfterResponse = [];

    /**
     * The batches that have been dispatched.
     *
     * @var array
     */
    protected $batches = [];

    /**
     * Indicates if commands should be serialized and restored when pushed to the Bus.
     *
     * @var bool
     */
    protected bool $serializeAndRestore = false;

    /**
     * Create a new bus fake instance.
     *
     * @param  \Illuminate\Contracts\Bus\QueueingDispatcher  $dispatcher
     * @param  array|string  $jobsToFake
     * @param  \Illuminate\Bus\BatchRepository|null  $batchRepository
     */
    public function __construct(QueueingDispatcher $dispatcher, $jobsToFake = [], ?BatchRepository $batchRepository = null)
    {
        $this->dispatcher = $dispatcher;
        $this->jobsToFake = Arr::wrap($jobsToFake);
        $this->batchRepository = $batchRepository ?: new BatchRepositoryFake;
    }

    /**
     * Specify the jobs that should be dispatched instead of faked.
     *
     * @param  array|string  $jobsToDispatch
     * @return $this
     */
    public function except($jobsToDispatch)
    {
        $this->jobsToDispatch = array_merge($this->jobsToDispatch, Arr::wrap($jobsToDispatch));

        return $this;
    }

    /**
     * Assert if a job was dispatched based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|int|null  $callback
     * @return void
     */
    public function assertDispatched($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        if (is_numeric($callback)) {
            return $this->assertDispatchedTimes($command, $callback);
        }

        PHPUnit::assertTrue(
            $this->dispatched($command, $callback)->count() > 0 ||
            $this->dispatchedAfterResponse($command, $callback)->count() > 0 ||
            $this->dispatchedSync($command, $callback)->count() > 0,
            "The expected [{$command}] job was not dispatched."
        );
    }

    /**
     * Assert if a job was pushed exactly once.
     *
     * @param  string|\Closure  $command
     * @return void
     */
    public function assertDispatchedOnce($command)
    {
        $this->assertDispatchedTimes($command, 1);
    }

    /**
     * Assert if a job was pushed a number of times.
     *
     * @param  string|\Closure  $command
     * @param  int  $times
     * @return void
     */
    public function assertDispatchedTimes($command, $times = 1)
    {
        $callback = null;

        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        $count = $this->dispatched($command, $callback)->count() +
                 $this->dispatchedAfterResponse($command, $callback)->count() +
                 $this->dispatchedSync($command, $callback)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$command}] job was pushed {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Determine if a job was dispatched based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|null  $callback
     * @return void
     */
    public function assertNotDispatched($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        PHPUnit::assertTrue(
            $this->dispatched($command, $callback)->count() === 0 &&
            $this->dispatchedAfterResponse($command, $callback)->count() === 0 &&
            $this->dispatchedSync($command, $callback)->count() === 0,
            "The unexpected [{$command}] job was dispatched."
        );
    }

    /**
     * Assert that no jobs were dispatched.
     *
     * @return void
     */
    public function assertNothingDispatched()
    {
        $dispatchedCommands = $this->commands + $this->commandsSync + $this->commandsAfterResponse;

        $commandNames = implode("\n- ", array_keys($dispatchedCommands));

        PHPUnit::assertEmpty($dispatchedCommands, "The following jobs were dispatched unexpectedly:\n\n- $commandNames\n");
    }

    /**
     * Assert if a job was explicitly dispatched synchronously based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|int|null  $callback
     * @return void
     */
    public function assertDispatchedSync($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        if (is_numeric($callback)) {
            return $this->assertDispatchedSyncTimes($command, $callback);
        }

        PHPUnit::assertTrue(
            $this->dispatchedSync($command, $callback)->count() > 0,
            "The expected [{$command}] job was not dispatched synchronously."
        );
    }

    /**
     * Assert if a job was pushed synchronously a number of times.
     *
     * @param  string|\Closure  $command
     * @param  int  $times
     * @return void
     */
    public function assertDispatchedSyncTimes($command, $times = 1)
    {
        $callback = null;

        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        $count = $this->dispatchedSync($command, $callback)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$command}] job was synchronously pushed {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Determine if a job was dispatched based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|null  $callback
     * @return void
     */
    public function assertNotDispatchedSync($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        PHPUnit::assertCount(
            0, $this->dispatchedSync($command, $callback),
            "The unexpected [{$command}] job was dispatched synchronously."
        );
    }

    /**
     * Assert if a job was dispatched after the response was sent based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|int|null  $callback
     * @return void
     */
    public function assertDispatchedAfterResponse($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        if (is_numeric($callback)) {
            return $this->assertDispatchedAfterResponseTimes($command, $callback);
        }

        PHPUnit::assertTrue(
            $this->dispatchedAfterResponse($command, $callback)->count() > 0,
            "The expected [{$command}] job was not dispatched after sending the response."
        );
    }

    /**
     * Assert if a job was pushed after the response was sent a number of times.
     *
     * @param  string|\Closure  $command
     * @param  int  $times
     * @return void
     */
    public function assertDispatchedAfterResponseTimes($command, $times = 1)
    {
        $callback = null;

        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        $count = $this->dispatchedAfterResponse($command, $callback)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$command}] job was pushed {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Determine if a job was dispatched based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|null  $callback
     * @return void
     */
    public function assertNotDispatchedAfterResponse($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        PHPUnit::assertCount(
            0, $this->dispatchedAfterResponse($command, $callback),
            "The unexpected [{$command}] job was dispatched after sending the response."
        );
    }

    /**
     * Assert if a chain of jobs was dispatched.
     *
     * @param  array  $expectedChain
     * @return void
     */
    public function assertChained(array $expectedChain)
    {
        $command = $expectedChain[0];

        $expectedChain = array_slice($expectedChain, 1);

        $callback = null;

        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        } elseif ($command instanceof ChainedBatchTruthTest) {
            $instance = $command;

            $command = ChainedBatch::class;

            $callback = fn ($job) => $instance($job->toPendingBatch());
        } elseif (! is_string($command)) {
            $instance = $command;

            $command = get_class($instance);

            $callback = function ($job) use ($instance) {
                return serialize($this->resetChainPropertiesToDefaults($job)) === serialize($instance);
            };
        }

        PHPUnit::assertTrue(
            $this->dispatched($command, $callback)->isNotEmpty(),
            "The expected [{$command}] job was not dispatched."
        );

        $this->assertDispatchedWithChainOfObjects($command, $expectedChain, $callback);
    }

    /**
     * Assert no chained jobs was dispatched.
     *
     * @return void
     */
    public function assertNothingChained()
    {
        $this->assertNothingDispatched();
    }

    /**
     * Reset the chain properties to their default values on the job.
     *
     * @param  mixed  $job
     * @return mixed
     */
    protected function resetChainPropertiesToDefaults($job)
    {
        return tap(clone $job, function ($job) {
            $job->chainConnection = null;
            $job->chainQueue = null;
            $job->chainCatchCallbacks = null;
            $job->chained = [];
        });
    }

    /**
     * Assert if a job was dispatched with an empty chain based on a truth-test callback.
     *
     * @param  string|\Closure  $command
     * @param  callable|null  $callback
     * @return void
     */
    public function assertDispatchedWithoutChain($command, $callback = null)
    {
        if ($command instanceof Closure) {
            [$command, $callback] = [$this->firstClosureParameterType($command), $command];
        }

        PHPUnit::assertTrue(
            $this->dispatched($command, $callback)->isNotEmpty(),
            "The expected [{$command}] job was not dispatched."
        );

        $this->assertDispatchedWithChainOfObjects($command, [], $callback);
    }

    /**
     * Assert if a job was dispatched with chained jobs based on a truth-test callback.
     *
     * @param  string  $command
     * @param  array  $expectedChain
     * @param  callable|null  $callback
     * @return void
     *
     * @throws \RuntimeException
     */
    protected function assertDispatchedWithChainOfObjects($command, $expectedChain, $callback)
    {
        $chain = $expectedChain;

        PHPUnit::assertTrue(
            $this->dispatched($command, $callback)->filter(function ($job) use ($chain) {
                if (count($chain) !== count($job->chained)) {
                    return false;
                }

                foreach ($job->chained as $index => $serializedChainedJob) {
                    if ($chain[$index] instanceof ChainedBatchTruthTest) {
                        $chainedBatch = unserialize($serializedChainedJob);

                        if (! $chainedBatch instanceof ChainedBatch ||
                            ! $chain[$index]($chainedBatch->toPendingBatch())) {
                            return false;
                        }
                    } elseif ($chain[$index] instanceof Closure) {
                        [$expectedType, $callback] = [$this->firstClosureParameterType($chain[$index]), $chain[$index]];

                        $chainedJob = unserialize($serializedChainedJob);

                        if (! $chainedJob instanceof $expectedType) {
                            throw new RuntimeException('The chained job was expected to be of type '.$expectedType.', '.$chainedJob::class.' chained.');
                        }

                        if (! $callback($chainedJob)) {
                            return false;
                        }
                    } elseif (is_string($chain[$index])) {
                        if ($chain[$index] != get_class(unserialize($serializedChainedJob))) {
                            return false;
                        }
                    } elseif (serialize($chain[$index]) != $serializedChainedJob) {
                        return false;
                    }
                }

                return true;
            })->isNotEmpty(),
            'The expected chain was not dispatched.'
        );
    }

    /**
     * Create a new assertion about a chained batch.
     *
     * @param  \Closure(\Illuminate\Bus\PendingBatch): bool  $callback
     * @return \Illuminate\Support\Testing\Fakes\ChainedBatchTruthTest
     */
    public function chainedBatch(Closure $callback)
    {
        return new ChainedBatchTruthTest($callback);
    }

    /**
     * Assert if a batch was dispatched based on a truth-test callback.
     *
     * @param  array|callable(\Illuminate\Bus\PendingBatch): bool  $callback
     * @return void
     */
    public function assertBatched(callable|array $callback)
    {
        $callback = is_array($callback) ? fn (PendingBatchFake $batch) => $batch->hasJobs($callback) : $callback;

        PHPUnit::assertTrue(
            $this->batched($callback)->count() > 0,
            'The expected batch was not dispatched.'
        );
    }

    /**
     * Assert the number of batches that have been dispatched.
     *
     * @param  int  $count
     * @return void
     */
    public function assertBatchCount($count)
    {
        PHPUnit::assertCount(
            $count, $this->batches,
        );
    }

    /**
     * Assert that no batched jobs were dispatched.
     *
     * @return void
     */
    public function assertNothingBatched()
    {
        $jobNames = (new Collection($this->batches))
            ->map(fn ($batch) => $batch->jobs->map(fn ($job) => get_class($job)))
            ->flatten()
            ->join("\n- ");

        PHPUnit::assertEmpty($this->batches, "The following batched jobs were dispatched unexpectedly:\n\n- $jobNames\n");
    }

    /**
     * Assert that no jobs were dispatched, chained, or batched.
     *
     * @return void
     */
    public function assertNothingPlaced()
    {
        $this->assertNothingDispatched();
        $this->assertNothingBatched();
    }

    /**
     * Get all of the jobs matching a truth-test callback.
     *
     * @param  string  $command
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function dispatched($command, $callback = null)
    {
        if (! $this->hasDispatched($command)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return (new Collection($this->commands[$command]))->filter(fn ($command) => $callback($command));
    }

    /**
     * Get all of the jobs dispatched synchronously matching a truth-test callback.
     *
     * @param  string  $command
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function dispatchedSync(string $command, $callback = null)
    {
        if (! $this->hasDispatchedSync($command)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return (new Collection($this->commandsSync[$command]))->filter(fn ($command) => $callback($command));
    }

    /**
     * Get all of the jobs dispatched after the response was sent matching a truth-test callback.
     *
     * @param  string  $command
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function dispatchedAfterResponse(string $command, $callback = null)
    {
        if (! $this->hasDispatchedAfterResponse($command)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return (new Collection($this->commandsAfterResponse[$command]))->filter(fn ($command) => $callback($command));
    }

    /**
     * Get all of the pending batches matching a truth-test callback.
     *
     * @param  callable(\Illuminate\Bus\PendingBatch): bool  $callback
     * @return \Illuminate\Support\Collection<int, \Illuminate\Bus\PendingBatch>
     */
    public function batched(callable $callback)
    {
        if (empty($this->batches)) {
            return new Collection;
        }

        return (new Collection($this->batches))->filter(fn ($batch) => $callback($batch));
    }

    /**
     * Determine if there are any stored commands for a given class.
     *
     * @param  string  $command
     * @return bool
     */
    public function hasDispatched($command)
    {
        return isset($this->commands[$command]) && ! empty($this->commands[$command]);
    }

    /**
     * Determine if there are any stored commands for a given class.
     *
     * @param  string  $command
     * @return bool
     */
    public function hasDispatchedSync($command)
    {
        return isset($this->commandsSync[$command]) && ! empty($this->commandsSync[$command]);
    }

    /**
     * Determine if there are any stored commands for a given class.
     *
     * @param  string  $command
     * @return bool
     */
    public function hasDispatchedAfterResponse($command)
    {
        return isset($this->commandsAfterResponse[$command]) && ! empty($this->commandsAfterResponse[$command]);
    }

    /**
     * Dispatch a command to its appropriate handler.
     *
     * @param  mixed  $command
     * @return mixed
     */
    public function dispatch($command)
    {
        if ($this->shouldFakeJob($command)) {
            $this->commands[get_class($command)][] = $this->getCommandRepresentation($command);
        } else {
            return $this->dispatcher->dispatch($command);
        }
    }

    /**
     * Dispatch a command to its appropriate handler in the current process.
     *
     * Queueable jobs will be dispatched to the "sync" queue.
     *
     * @param  mixed  $command
     * @param  mixed  $handler
     * @return mixed
     */
    public function dispatchSync($command, $handler = null)
    {
        if ($this->shouldFakeJob($command)) {
            $this->commandsSync[get_class($command)][] = $this->getCommandRepresentation($command);
        } else {
            return $this->dispatcher->dispatchSync($command, $handler);
        }
    }

    /**
     * Dispatch a command to its appropriate handler in the current process.
     *
     * @param  mixed  $command
     * @param  mixed  $handler
     * @return mixed
     */
    public function dispatchNow($command, $handler = null)
    {
        if ($this->shouldFakeJob($command)) {
            $this->commands[get_class($command)][] = $this->getCommandRepresentation($command);
        } else {
            return $this->dispatcher->dispatchNow($command, $handler);
        }
    }

    /**
     * Dispatch a command to its appropriate handler behind a queue.
     *
     * @param  mixed  $command
     * @return mixed
     */
    public function dispatchToQueue($command)
    {
        if ($this->shouldFakeJob($command)) {
            $this->commands[get_class($command)][] = $this->getCommandRepresentation($command);
        } else {
            return $this->dispatcher->dispatchToQueue($command);
        }
    }

    /**
     * Dispatch a command to its appropriate handler after the current process.
     *
     * @param  mixed  $command
     * @param  mixed  $handler
     * @return void
     */
    public function dispatchAfterResponse($command, $handler = null)
    {
        if ($this->shouldFakeJob($command)) {
            $this->commandsAfterResponse[get_class($command)][] = $this->getCommandRepresentation($command);
        } else {
            $this->dispatcher->dispatchAfterResponse($command, $handler);
        }
    }

    /**
     * Create a new chain of queueable jobs.
     *
     * @param  \Illuminate\Support\Collection|array|null  $jobs
     * @return \Illuminate\Foundation\Bus\PendingChain
     */
    public function chain($jobs = null)
    {
        $jobs = Collection::wrap($jobs);
        $jobs = ChainedBatch::prepareNestedBatches($jobs);

        return new PendingChainFake($this, $jobs->shift(), $jobs->toArray());
    }

    /**
     * Attempt to find the batch with the given ID.
     *
     * @param  string  $batchId
     * @return \Illuminate\Bus\Batch|null
     */
    public function findBatch(string $batchId)
    {
        return $this->batchRepository->find($batchId);
    }

    /**
     * Create a new batch of queueable jobs.
     *
     * @param  \Illuminate\Support\Collection|array  $jobs
     * @return \Illuminate\Bus\PendingBatch
     */
    public function batch($jobs)
    {
        return new PendingBatchFake($this, Collection::wrap($jobs));
    }

    /**
     * Dispatch an empty job batch for testing.
     *
     * @param  string  $name
     * @return \Illuminate\Bus\Batch
     */
    public function dispatchFakeBatch($name = '')
    {
        return $this->batch([])->name($name)->dispatch();
    }

    /**
     * Record the fake pending batch dispatch.
     *
     * @param  \Illuminate\Bus\PendingBatch  $pendingBatch
     * @return \Illuminate\Bus\Batch
     */
    public function recordPendingBatch(PendingBatch $pendingBatch)
    {
        $this->batches[] = $pendingBatch;

        return $this->batchRepository->store($pendingBatch);
    }

    /**
     * Determine if a command should be faked or actually dispatched.
     *
     * @param  mixed  $command
     * @return bool
     */
    protected function shouldFakeJob($command)
    {
        if ($this->shouldDispatchCommand($command)) {
            return false;
        }

        if (empty($this->jobsToFake)) {
            return true;
        }

        return (new Collection($this->jobsToFake))
            ->filter(function ($job) use ($command) {
                return $job instanceof Closure
                    ? $job($command)
                    : $job === get_class($command);
            })->isNotEmpty();
    }

    /**
     * Determine if a command should be dispatched or not.
     *
     * @param  mixed  $command
     * @return bool
     */
    protected function shouldDispatchCommand($command)
    {
        return (new Collection($this->jobsToDispatch))
            ->filter(function ($job) use ($command) {
                return $job instanceof Closure
                    ? $job($command)
                    : $job === get_class($command);
            })->isNotEmpty();
    }

    /**
     * Specify if commands should be serialized and restored when being batched.
     *
     * @param  bool  $serializeAndRestore
     * @return $this
     */
    public function serializeAndRestore(bool $serializeAndRestore = true)
    {
        $this->serializeAndRestore = $serializeAndRestore;

        return $this;
    }

    /**
     * Serialize and unserialize the command to simulate the queueing process.
     *
     * @param  mixed  $command
     * @return mixed
     */
    protected function serializeAndRestoreCommand($command)
    {
        return unserialize(serialize($command));
    }

    /**
     * Return the command representation that should be stored.
     *
     * @param  mixed  $command
     * @return mixed
     */
    protected function getCommandRepresentation($command)
    {
        return $this->serializeAndRestore ? $this->serializeAndRestoreCommand($command) : $command;
    }

    /**
     * Set the pipes commands should be piped through before dispatching.
     *
     * @param  array  $pipes
     * @return $this
     */
    public function pipeThrough(array $pipes)
    {
        $this->dispatcher->pipeThrough($pipes);

        return $this;
    }

    /**
     * Determine if the given command has a handler.
     *
     * @param  mixed  $command
     * @return bool
     */
    public function hasCommandHandler($command)
    {
        return $this->dispatcher->hasCommandHandler($command);
    }

    /**
     * Retrieve the handler for a command.
     *
     * @param  mixed  $command
     * @return mixed
     */
    public function getCommandHandler($command)
    {
        return $this->dispatcher->getCommandHandler($command);
    }

    /**
     * Map a command to a handler.
     *
     * @param  array  $map
     * @return $this
     */
    public function map(array $map)
    {
        $this->dispatcher->map($map);

        return $this;
    }

    /**
     * Get the batches that have been dispatched.
     *
     * @return array
     */
    public function dispatchedBatches()
    {
        return $this->batches;
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Illuminate\Foundation\Bus\PendingChain;
use Illuminate\Queue\CallQueuedClosure;

class PendingChainFake extends PendingChain
{
    /**
     * The fake bus instance.
     *
     * @var \Illuminate\Support\Testing\Fakes\BusFake
     */
    protected $bus;

    /**
     * Create a new pending chain instance.
     *
     * @param  \Illuminate\Support\Testing\Fakes\BusFake  $bus
     * @param  mixed  $job
     * @param  array  $chain
     */
    public function __construct(BusFake $bus, $job, $chain)
    {
        $this->bus = $bus;
        $this->job = $job;
        $this->chain = $chain;
    }

    /**
     * Dispatch the job with the given arguments.
     *
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public function dispatch()
    {
        if (is_string($this->job)) {
            $firstJob = new $this->job(...func_get_args());
        } elseif ($this->job instanceof Closure) {
            $firstJob = CallQueuedClosure::create($this->job);
        } else {
            $firstJob = $this->job;
        }

        $firstJob->allOnConnection($this->connection);
        $firstJob->allOnQueue($this->queue);
        $firstJob->chain($this->chain);
        $firstJob->delay($this->delay);
        $firstJob->chainCatchCallbacks = $this->catchCallbacks();

        return $this->bus->dispatch($firstJob);
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Illuminate\Bus\PendingBatch;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\ReflectsClosures;

class PendingBatchFake extends PendingBatch
{
    use ReflectsClosures;

    /**
     * The fake bus instance.
     *
     * @var \Illuminate\Support\Testing\Fakes\BusFake
     */
    protected $bus;

    /**
     * Create a new pending batch instance.
     *
     * @param  \Illuminate\Support\Testing\Fakes\BusFake  $bus
     * @param  \Illuminate\Support\Collection  $jobs
     */
    public function __construct(BusFake $bus, Collection $jobs)
    {
        $this->bus = $bus;
        $this->jobs = $jobs->filter()->values();
    }

    /**
     * Dispatch the batch.
     *
     * @return \Illuminate\Bus\Batch
     */
    public function dispatch()
    {
        return $this->bus->recordPendingBatch($this);
    }

    /**
     * Dispatch the batch after the response is sent to the browser.
     *
     * @return \Illuminate\Bus\Batch
     */
    public function dispatchAfterResponse()
    {
        return $this->bus->recordPendingBatch($this);
    }

    /**
     * Determine if the jobs in the batch match the given jobs.
     *
     * @param  array  $expectedJobs
     * @return bool
     */
    public function hasJobs(array $expectedJobs)
    {
        if (count($this->jobs) !== count($expectedJobs)) {
            return false;
        }

        foreach ($expectedJobs as $index => $expectedJob) {
            if ($expectedJob instanceof Closure) {
                $expectedType = $this->firstClosureParameterType($expectedJob);

                if (! $this->jobs[$index] instanceof $expectedType) {
                    return false;
                }

                if (! $expectedJob($this->jobs[$index])) {
                    return false;
                }
            } elseif (is_string($expectedJob)) {
                if ($expectedJob != get_class($this->jobs[$index])) {
                    return false;
                }
            } elseif (serialize($expectedJob) != serialize($this->jobs[$index])) {
                return false;
            }
        }

        return true;
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Closure;
use Illuminate\Bus\BatchRepository;
use Illuminate\Bus\PendingBatch;
use Illuminate\Bus\UpdatedBatchJobCounts;
use Illuminate\Support\Str;

class BatchRepositoryFake implements BatchRepository
{
    /**
     * The batches stored in the repository.
     *
     * @var \Illuminate\Bus\Batch[]
     */
    protected $batches = [];

    /**
     * Retrieve a list of batches.
     *
     * @param  int  $limit
     * @param  mixed  $before
     * @return \Illuminate\Bus\Batch[]
     */
    public function get($limit, $before)
    {
        return $this->batches;
    }

    /**
     * Retrieve information about an existing batch.
     *
     * @param  string  $batchId
     * @return \Illuminate\Bus\Batch|null
     */
    public function find(string $batchId)
    {
        return $this->batches[$batchId] ?? null;
    }

    /**
     * Store a new pending batch.
     *
     * @param  \Illuminate\Bus\PendingBatch  $batch
     * @return \Illuminate\Bus\Batch
     */
    public function store(PendingBatch $batch)
    {
        $id = (string) Str::orderedUuid();

        $this->batches[$id] = new BatchFake(
            $id,
            $batch->name,
            count($batch->jobs),
            count($batch->jobs),
            0,
            [],
            $batch->options,
            CarbonImmutable::now(),
            null,
            null
        );

        return $this->batches[$id];
    }

    /**
     * Increment the total number of jobs within the batch.
     *
     * @param  string  $batchId
     * @param  int  $amount
     * @return void
     */
    public function incrementTotalJobs(string $batchId, int $amount)
    {
        //
    }

    /**
     * Decrement the total number of pending jobs for the batch.
     *
     * @param  string  $batchId
     * @param  string  $jobId
     * @return \Illuminate\Bus\UpdatedBatchJobCounts
     */
    public function decrementPendingJobs(string $batchId, string $jobId)
    {
        return new UpdatedBatchJobCounts;
    }

    /**
     * Increment the total number of failed jobs for the batch.
     *
     * @param  string  $batchId
     * @param  string  $jobId
     * @return \Illuminate\Bus\UpdatedBatchJobCounts
     */
    public function incrementFailedJobs(string $batchId, string $jobId)
    {
        return new UpdatedBatchJobCounts;
    }

    /**
     * Mark the batch that has the given ID as finished.
     *
     * @param  string  $batchId
     * @return void
     */
    public function markAsFinished(string $batchId)
    {
        if (isset($this->batches[$batchId])) {
            $this->batches[$batchId]->finishedAt = Carbon::now();
        }
    }

    /**
     * Cancel the batch that has the given ID.
     *
     * @param  string  $batchId
     * @return void
     */
    public function cancel(string $batchId)
    {
        if (isset($this->batches[$batchId])) {
            $this->batches[$batchId]->cancel();
        }
    }

    /**
     * Delete the batch that has the given ID.
     *
     * @param  string  $batchId
     * @return void
     */
    public function delete(string $batchId)
    {
        unset($this->batches[$batchId]);
    }

    /**
     * Execute the given Closure within a storage specific transaction.
     *
     * @param  \Closure  $callback
     * @return mixed
     */
    public function transaction(Closure $callback)
    {
        return $callback();
    }

    /**
     * Rollback the last database transaction for the connection.
     *
     * @return void
     */
    public function rollBack()
    {
        //
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Mail\PendingMail;

class PendingMailFake extends PendingMail
{
    /**
     * Create a new instance.
     *
     * @param  \Illuminate\Support\Testing\Fakes\MailFake  $mailer
     */
    public function __construct($mailer)
    {
        $this->mailer = $mailer;
    }

    /**
     * Send a new mailable message instance.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable  $mailable
     * @return void
     */
    public function send(Mailable $mailable)
    {
        $this->mailer->send($this->fill($mailable));
    }

    /**
     * Send a new mailable message instance synchronously.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable  $mailable
     * @return void
     */
    public function sendNow(Mailable $mailable)
    {
        $this->mailer->sendNow($this->fill($mailable));
    }

    /**
     * Push the given mailable onto the queue.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable  $mailable
     * @return mixed
     */
    public function queue(Mailable $mailable)
    {
        return $this->mailer->queue($this->fill($mailable));
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Illuminate\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
use ReflectionFunction;

class EventFake implements Dispatcher, Fake
{
    use ForwardsCalls, ReflectsClosures;

    /**
     * The original event dispatcher.
     *
     * @var \Illuminate\Contracts\Events\Dispatcher
     */
    public $dispatcher;

    /**
     * The event types that should be intercepted instead of dispatched.
     *
     * @var array
     */
    protected $eventsToFake = [];

    /**
     * The event types that should be dispatched instead of intercepted.
     *
     * @var array
     */
    protected $eventsToDispatch = [];

    /**
     * All of the events that have been intercepted keyed by type.
     *
     * @var array
     */
    protected $events = [];

    /**
     * Create a new event fake instance.
     *
     * @param  \Illuminate\Contracts\Events\Dispatcher  $dispatcher
     * @param  array|string  $eventsToFake
     */
    public function __construct(Dispatcher $dispatcher, $eventsToFake = [])
    {
        $this->dispatcher = $dispatcher;

        $this->eventsToFake = Arr::wrap($eventsToFake);
    }

    /**
     * Specify the events that should be dispatched instead of faked.
     *
     * @param  array|string  $eventsToDispatch
     * @return $this
     */
    public function except($eventsToDispatch)
    {
        $this->eventsToDispatch = array_merge(
            $this->eventsToDispatch,
            Arr::wrap($eventsToDispatch)
        );

        return $this;
    }

    /**
     * Assert if an event has a listener attached to it.
     *
     * @param  string  $expectedEvent
     * @param  string|array  $expectedListener
     * @return void
     */
    public function assertListening($expectedEvent, $expectedListener)
    {
        foreach ($this->dispatcher->getListeners($expectedEvent) as $listenerClosure) {
            $actualListener = (new ReflectionFunction($listenerClosure))
                ->getStaticVariables()['listener'];

            $normalizedListener = $expectedListener;

            if (is_string($actualListener) && Str::contains($actualListener, '@')) {
                $actualListener = Str::parseCallback($actualListener);

                if (is_string($expectedListener)) {
                    if (Str::contains($expectedListener, '@')) {
                        $normalizedListener = Str::parseCallback($expectedListener);
                    } else {
                        $normalizedListener = [
                            $expectedListener,
                            method_exists($expectedListener, 'handle') ? 'handle' : '__invoke',
                        ];
                    }
                }
            }

            if ($actualListener === $normalizedListener ||
                ($actualListener instanceof Closure &&
                $normalizedListener === Closure::class)) {
                PHPUnit::assertTrue(true);

                return;
            }
        }

        PHPUnit::assertTrue(
            false,
            sprintf(
                'Event [%s] does not have the [%s] listener attached to it',
                $expectedEvent,
                print_r($expectedListener, true)
            )
        );
    }

    /**
     * Assert if an event was dispatched based on a truth-test callback.
     *
     * @param  string|\Closure  $event
     * @param  callable|int|null  $callback
     * @return void
     */
    public function assertDispatched($event, $callback = null)
    {
        if ($event instanceof Closure) {
            [$event, $callback] = [$this->firstClosureParameterType($event), $event];
        }

        if (is_int($callback)) {
            return $this->assertDispatchedTimes($event, $callback);
        }

        PHPUnit::assertTrue(
            $this->dispatched($event, $callback)->count() > 0,
            "The expected [{$event}] event was not dispatched."
        );
    }

    /**
     * Assert if an event was dispatched exactly once.
     *
     * @param  string  $event
     * @return void
     */
    public function assertDispatchedOnce($event)
    {
        $this->assertDispatchedTimes($event, 1);
    }

    /**
     * Assert if an event was dispatched a number of times.
     *
     * @param  string  $event
     * @param  int  $times
     * @return void
     */
    public function assertDispatchedTimes($event, $times = 1)
    {
        $count = $this->dispatched($event)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$event}] event was dispatched {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Determine if an event was dispatched based on a truth-test callback.
     *
     * @param  string|\Closure  $event
     * @param  callable|null  $callback
     * @return void
     */
    public function assertNotDispatched($event, $callback = null)
    {
        if ($event instanceof Closure) {
            [$event, $callback] = [$this->firstClosureParameterType($event), $event];
        }

        PHPUnit::assertCount(
            0, $this->dispatched($event, $callback),
            "The unexpected [{$event}] event was dispatched."
        );
    }

    /**
     * Assert that no events were dispatched.
     *
     * @return void
     */
    public function assertNothingDispatched()
    {
        $count = count(Arr::flatten($this->events));

        $eventNames = (new Collection($this->events))
            ->map(fn ($events, $eventName) => sprintf(
                '%s dispatched %s %s',
                $eventName,
                count($events),
                Str::plural('time', count($events)),
            ))
            ->join("\n- ");

        PHPUnit::assertSame(
            0, $count,
            "{$count} unexpected events were dispatched:\n\n- $eventNames\n"
        );
    }

    /**
     * Get all of the events matching a truth-test callback.
     *
     * @param  string  $event
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function dispatched($event, $callback = null)
    {
        if (! $this->hasDispatched($event)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return (new Collection($this->events[$event]))->filter(
            fn ($arguments) => $callback(...$arguments)
        );
    }

    /**
     * Determine if the given event has been dispatched.
     *
     * @param  string  $event
     * @return bool
     */
    public function hasDispatched($event)
    {
        return isset($this->events[$event]) && ! empty($this->events[$event]);
    }

    /**
     * Register an event listener with the dispatcher.
     *
     * @param  \Closure|string|array  $events
     * @param  mixed  $listener
     * @return void
     */
    public function listen($events, $listener = null)
    {
        $this->dispatcher->listen($events, $listener);
    }

    /**
     * Determine if a given event has listeners.
     *
     * @param  string  $eventName
     * @return bool
     */
    public function hasListeners($eventName)
    {
        return $this->dispatcher->hasListeners($eventName);
    }

    /**
     * Register an event and payload to be dispatched later.
     *
     * @param  string  $event
     * @param  array  $payload
     * @return void
     */
    public function push($event, $payload = [])
    {
        //
    }

    /**
     * Register an event subscriber with the dispatcher.
     *
     * @param  object|string  $subscriber
     * @return void
     */
    public function subscribe($subscriber)
    {
        $this->dispatcher->subscribe($subscriber);
    }

    /**
     * Flush a set of pushed events.
     *
     * @param  string  $event
     * @return void
     */
    public function flush($event)
    {
        //
    }

    /**
     * Fire an event and call the listeners.
     *
     * @param  string|object  $event
     * @param  mixed  $payload
     * @param  bool  $halt
     * @return array|null
     */
    public function dispatch($event, $payload = [], $halt = false)
    {
        $name = is_object($event) ? get_class($event) : (string) $event;

        if ($this->shouldFakeEvent($name, $payload)) {
            $this->fakeEvent($event, $name, func_get_args());
        } else {
            return $this->dispatcher->dispatch($event, $payload, $halt);
        }
    }

    /**
     * Determine if an event should be faked or actually dispatched.
     *
     * @param  string  $eventName
     * @param  mixed  $payload
     * @return bool
     */
    protected function shouldFakeEvent($eventName, $payload)
    {
        if ($this->shouldDispatchEvent($eventName, $payload)) {
            return false;
        }

        if (empty($this->eventsToFake)) {
            return true;
        }

        return (new Collection($this->eventsToFake))
            ->filter(function ($event) use ($eventName, $payload) {
                return $event instanceof Closure
                    ? $event($eventName, $payload)
                    : $event === $eventName;
            })
            ->isNotEmpty();
    }

    /**
     * Push the event onto the fake events array immediately or after the next database transaction.
     *
     * @param  string|object  $event
     * @param  string  $name
     * @param  array  $arguments
     * @return void
     */
    protected function fakeEvent($event, $name, $arguments)
    {
        if ($event instanceof ShouldDispatchAfterCommit && Container::getInstance()->bound('db.transactions')) {
            return Container::getInstance()->make('db.transactions')
                ->addCallback(fn () => $this->events[$name][] = $arguments);
        }

        $this->events[$name][] = $arguments;
    }

    /**
     * Determine whether an event should be dispatched or not.
     *
     * @param  string  $eventName
     * @param  mixed  $payload
     * @return bool
     */
    protected function shouldDispatchEvent($eventName, $payload)
    {
        if (empty($this->eventsToDispatch)) {
            return false;
        }

        return (new Collection($this->eventsToDispatch))
            ->filter(function ($event) use ($eventName, $payload) {
                return $event instanceof Closure
                    ? $event($eventName, $payload)
                    : $event === $eventName;
            })
            ->isNotEmpty();
    }

    /**
     * Remove a set of listeners from the dispatcher.
     *
     * @param  string  $event
     * @return void
     */
    public function forget($event)
    {
        //
    }

    /**
     * Forget all of the queued listeners.
     *
     * @return void
     */
    public function forgetPushed()
    {
        //
    }

    /**
     * Dispatch an event and call the listeners.
     *
     * @param  string|object  $event
     * @param  mixed  $payload
     * @return mixed
     */
    public function until($event, $payload = [])
    {
        return $this->dispatch($event, $payload, true);
    }

    /**
     * Get the events that have been dispatched.
     *
     * @return array
     */
    public function dispatchedEvents()
    {
        return $this->events;
    }

    /**
     * Handle dynamic method calls to the dispatcher.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->forwardCallTo($this->dispatcher, $method, $parameters);
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

interface Fake
{
    //
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use BadMethodCallException;
use Closure;
use Illuminate\Bus\UniqueLock;
use Illuminate\Contracts\Cache\Repository as Cache;
use Illuminate\Contracts\Queue\Queue;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Events\CallQueuedListener;
use Illuminate\Queue\CallQueuedClosure;
use Illuminate\Queue\Jobs\InspectedJob;
use Illuminate\Queue\QueueManager;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;

use function Illuminate\Support\enum_value;

/**
 * @phpstan-type RawPushType array{"payload": string, "queue": string|null, "options": array<array-key, mixed>}
 */
class QueueFake extends QueueManager implements Fake, Queue
{
    use ReflectsClosures;

    /**
     * The original queue manager.
     *
     * @var \Illuminate\Contracts\Queue\Queue
     */
    public $queue;

    /**
     * The job types that should be intercepted instead of pushed to the queue.
     *
     * @var \Illuminate\Support\Collection
     */
    protected $jobsToFake;

    /**
     * The job types that should be pushed to the queue and not intercepted.
     *
     * @var \Illuminate\Support\Collection
     */
    protected $jobsToBeQueued;

    /**
     * All of the jobs that have been pushed.
     *
     * @var array
     */
    protected $jobs = [];

    /**
     * All of the payloads that have been raw pushed.
     *
     * @var list<RawPushType>
     */
    protected $rawPushes = [];

    /**
     * All of the unique jobs that were pushed.
     *
     * @var array
     */
    private $uniqueJobs = [];

    /**
     * Indicates if items should be serialized and restored when pushed to the queue.
     *
     * @var bool
     */
    protected bool $serializeAndRestore = false;

    /**
     * Create a new fake queue instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @param  array  $jobsToFake
     * @param  \Illuminate\Queue\QueueManager|null  $queue
     */
    public function __construct($app, $jobsToFake = [], $queue = null)
    {
        parent::__construct($app);

        $this->jobsToFake = Collection::wrap($jobsToFake);
        $this->jobsToBeQueued = new Collection;
        $this->queue = $queue;
    }

    /**
     * Specify the jobs that should be queued instead of faked.
     *
     * @param  array|string  $jobsToBeQueued
     * @return $this
     */
    public function except($jobsToBeQueued)
    {
        $this->jobsToBeQueued = Collection::wrap($jobsToBeQueued)->merge($this->jobsToBeQueued);

        return $this;
    }

    /**
     * Assert if a job was pushed based on a truth-test callback.
     *
     * @param  string|\Closure  $job
     * @param  callable|int|null  $callback
     * @return void
     */
    public function assertPushed($job, $callback = null)
    {
        if ($job instanceof Closure) {
            [$job, $callback] = [$this->firstClosureParameterType($job), $job];
        }

        if (is_numeric($callback)) {
            return $this->assertPushedTimes($job, $callback);
        }

        PHPUnit::assertTrue(
            $this->pushed($job, $callback)->count() > 0,
            "The expected [{$job}] job was not pushed."
        );
    }

    /**
     * Assert if a job was pushed a number of times.
     *
     * @param  string  $job
     * @param  int  $times
     * @return void
     */
    public function assertPushedTimes($job, $times = 1)
    {
        $count = $this->pushed($job)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$job}] job was pushed {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Assert if a job was pushed based on a truth-test callback.
     *
     * @param  \UnitEnum|string  $queue
     * @param  string|\Closure  $job
     * @param  callable|null  $callback
     * @return void
     */
    public function assertPushedOn($queue, $job, $callback = null)
    {
        if ($job instanceof Closure) {
            [$job, $callback] = [$this->firstClosureParameterType($job), $job];
        }

        $queue = enum_value($queue);

        $this->assertPushed($job, function ($job, $pushedQueue) use ($callback, $queue) {
            if (enum_value($pushedQueue) !== $queue) {
                return false;
            }

            return $callback ? $callback(...func_get_args()) : true;
        });
    }

    /**
     * Assert if a job was pushed with chained jobs based on a truth-test callback.
     *
     * @param  string  $job
     * @param  array  $expectedChain
     * @param  callable|null  $callback
     * @return void
     */
    public function assertPushedWithChain($job, $expectedChain = [], $callback = null)
    {
        PHPUnit::assertTrue(
            $this->pushed($job, $callback)->isNotEmpty(),
            "The expected [{$job}] job was not pushed."
        );

        PHPUnit::assertTrue(
            (new Collection($expectedChain))->isNotEmpty(),
            'The expected chain can not be empty.'
        );

        $this->isChainOfObjects($expectedChain)
            ? $this->assertPushedWithChainOfObjects($job, $expectedChain, $callback)
            : $this->assertPushedWithChainOfClasses($job, $expectedChain, $callback);
    }

    /**
     * Assert if a job was pushed with an empty chain based on a truth-test callback.
     *
     * @param  string  $job
     * @param  callable|null  $callback
     * @return void
     */
    public function assertPushedWithoutChain($job, $callback = null)
    {
        PHPUnit::assertTrue(
            $this->pushed($job, $callback)->isNotEmpty(),
            "The expected [{$job}] job was not pushed."
        );

        $this->assertPushedWithChainOfClasses($job, [], $callback);
    }

    /**
     * Assert if a job was pushed with chained jobs based on a truth-test callback.
     *
     * @param  string  $job
     * @param  array  $expectedChain
     * @param  callable|null  $callback
     * @return void
     */
    protected function assertPushedWithChainOfObjects($job, $expectedChain, $callback)
    {
        $chain = (new Collection($expectedChain))->map(fn ($job) => serialize($job))->all();

        PHPUnit::assertTrue(
            $this->pushed($job, $callback)->filter(fn ($job) => $job->chained == $chain)->isNotEmpty(),
            'The expected chain was not pushed.'
        );
    }

    /**
     * Assert if a job was pushed with chained jobs based on a truth-test callback.
     *
     * @param  string  $job
     * @param  array  $expectedChain
     * @param  callable|null  $callback
     * @return void
     */
    protected function assertPushedWithChainOfClasses($job, $expectedChain, $callback)
    {
        $matching = $this->pushed($job, $callback)->map->chained->map(function ($chain) {
            return (new Collection($chain))->map(function ($job) {
                return get_class(unserialize($job));
            });
        })->filter(function ($chain) use ($expectedChain) {
            return $chain->all() === $expectedChain;
        });

        PHPUnit::assertTrue(
            $matching->isNotEmpty(), 'The expected chain was not pushed.'
        );
    }

    /**
     * Assert if a closure was pushed based on a truth-test callback.
     *
     * @param  callable|int|null  $callback
     * @return void
     */
    public function assertClosurePushed($callback = null)
    {
        $this->assertPushed(CallQueuedClosure::class, $callback);
    }

    /**
     * Assert that a closure was not pushed based on a truth-test callback.
     *
     * @param  callable|null  $callback
     * @return void
     */
    public function assertClosureNotPushed($callback = null)
    {
        $this->assertNotPushed(CallQueuedClosure::class, $callback);
    }

    /**
     * Determine if the given chain is entirely composed of objects.
     *
     * @param  array  $chain
     * @return bool
     */
    protected function isChainOfObjects($chain)
    {
        return ! (new Collection($chain))->contains(fn ($job) => ! is_object($job));
    }

    /**
     * Determine if a job was pushed based on a truth-test callback.
     *
     * @param  string|\Closure  $job
     * @param  callable|null  $callback
     * @return void
     */
    public function assertNotPushed($job, $callback = null)
    {
        if ($job instanceof Closure) {
            [$job, $callback] = [$this->firstClosureParameterType($job), $job];
        }

        PHPUnit::assertCount(
            0, $this->pushed($job, $callback),
            "The unexpected [{$job}] job was pushed."
        );
    }

    /**
     * Assert the total count of jobs that were pushed.
     *
     * @param  int  $expectedCount
     * @return void
     */
    public function assertCount($expectedCount)
    {
        $actualCount = (new Collection($this->jobs))->flatten(1)->count();

        PHPUnit::assertSame(
            $expectedCount, $actualCount,
            "Expected {$expectedCount} jobs to be pushed, but found {$actualCount} instead."
        );
    }

    /**
     * Assert that no jobs were pushed.
     *
     * @return void
     */
    public function assertNothingPushed()
    {
        $pushedJobs = implode("\n- ", array_keys($this->jobs));

        PHPUnit::assertEmpty($this->jobs, "The following jobs were pushed unexpectedly:\n\n- $pushedJobs\n");
    }

    /**
     * Get all of the jobs matching a truth-test callback.
     *
     * @param  string  $job
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function pushed($job, $callback = null)
    {
        if (! $this->hasPushed($job)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return (new Collection($this->jobs[$job]))->filter(
            fn ($data) => $callback($data['job'], $data['queue'], $data['data'])
        )->pluck('job');
    }

    /**
     * Get all of the raw pushes matching a truth-test callback.
     *
     * @param  null|\Closure(string, ?string, array): bool  $callback
     * @return \Illuminate\Support\Collection<int, RawPushType>
     */
    public function pushedRaw($callback = null)
    {
        $callback ??= static fn () => true;

        return (new Collection($this->rawPushes))->filter(fn ($data) => $callback($data['payload'], $data['queue'], $data['options']));
    }

    /**
     * Get all of the jobs by listener class, passing an optional truth-test callback.
     *
     * @param  class-string  $listenerClass
     * @param  (\Closure(mixed, \Illuminate\Events\CallQueuedListener, string|null, mixed): bool)|null  $callback
     * @return \Illuminate\Support\Collection<int, \Illuminate\Events\CallQueuedListener>
     */
    public function listenersPushed($listenerClass, $callback = null)
    {
        if (! $this->hasPushed(CallQueuedListener::class)) {
            return new Collection;
        }

        $collection = (new Collection($this->jobs[CallQueuedListener::class]))
            ->filter(fn ($data) => $data['job']->class === $listenerClass);

        if ($callback) {
            $collection = $collection->filter(fn ($data) => $callback($data['job']->data[0] ?? null, $data['job'], $data['queue'], $data['data']));
        }

        return $collection->pluck('job');
    }

    /**
     * Determine if there are any stored jobs for a given class.
     *
     * @param  string  $job
     * @return bool
     */
    public function hasPushed($job)
    {
        return isset($this->jobs[$job]) && ! empty($this->jobs[$job]);
    }

    /**
     * Resolve a queue connection instance.
     *
     * @param  mixed  $value
     * @return \Illuminate\Contracts\Queue\Queue
     */
    public function connection($value = null)
    {
        return $this;
    }

    /**
     * Get the size of the queue.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function size($queue = null)
    {
        return (new Collection($this->jobs))
            ->flatten(1)
            ->filter(fn ($job) => $job['queue'] === $queue)
            ->count();
    }

    /**
     * Get the number of pending jobs.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function pendingSize($queue = null)
    {
        return $this->size($queue);
    }

    /**
     * Get the number of delayed jobs.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function delayedSize($queue = null)
    {
        return 0;
    }

    /**
     * Get the number of reserved jobs.
     *
     * @param  string|null  $queue
     * @return int
     */
    public function reservedSize($queue = null)
    {
        return 0;
    }

    /**
     * Get the pending jobs for the given queue.
     *
     * @param  string|null  $queue
     * @return \Illuminate\Support\Collection<int, \Illuminate\Queue\Jobs\InspectedJob>
     */
    public function pendingJobs($queue = null): Collection
    {
        return (new Collection($this->jobs))
            ->flatten(1)
            ->filter(fn ($job) => $job['queue'] === $queue)
            ->map(fn ($data) => new InspectedJob(
                uuid: null,
                name: is_object($data['job'])
                    ? (method_exists($data['job'], 'displayName') ? $data['job']->displayName() : get_class($data['job']))
                    : $data['job'],
                attempts: 0,
                createdAt: null,
            ));
    }

    /**
     * Get the delayed jobs for the given queue.
     *
     * @param  string|null  $queue
     * @return \Illuminate\Support\Collection
     */
    public function delayedJobs($queue = null): Collection
    {
        return new Collection;
    }

    /**
     * Get the reserved jobs for the given queue.
     *
     * @param  string|null  $queue
     * @return \Illuminate\Support\Collection
     */
    public function reservedJobs($queue = null): Collection
    {
        return new Collection;
    }

    /**
     * Get all pending jobs across every queue.
     *
     * @return \Illuminate\Support\Collection<int, \Illuminate\Queue\Jobs\InspectedJob>
     */
    public function allPendingJobs(): Collection
    {
        return (new Collection($this->jobs))
            ->flatten(1)
            ->map(fn ($data) => new InspectedJob(
                uuid: null,
                name: is_object($data['job'])
                    ? (method_exists($data['job'], 'displayName') ? $data['job']->displayName() : get_class($data['job']))
                    : $data['job'],
                attempts: 0,
                createdAt: null,
            ));
    }

    /**
     * Get all delayed jobs across every queue.
     *
     * @return \Illuminate\Support\Collection
     */
    public function allDelayedJobs(): Collection
    {
        return new Collection;
    }

    /**
     * Get all reserved jobs across every queue.
     *
     * @return \Illuminate\Support\Collection
     */
    public function allReservedJobs(): Collection
    {
        return new Collection;
    }

    /**
     * Get the creation timestamp of the oldest pending job, excluding delayed jobs.
     *
     * @param  string|null  $queue
     * @return int|null
     */
    public function creationTimeOfOldestPendingJob($queue = null)
    {
        return null;
    }

    /**
     * Push a new job onto the queue.
     *
     * @param  string|object  $job
     * @param  mixed  $data
     * @param  string|null  $queue
     * @return mixed
     */
    public function push($job, $data = '', $queue = null)
    {
        if ($this->shouldFakeJob($job)) {
            if ($job instanceof Closure) {
                $job = CallQueuedClosure::create($job);
            }

            $this->jobs[is_object($job) ? get_class($job) : $job][] = [
                'job' => $this->serializeAndRestore ? $this->serializeAndRestoreJob($job) : $job,
                'queue' => $queue,
                'data' => $data,
            ];

            if ($job instanceof ShouldBeUnique) {
                $this->uniqueJobs[] = $job;
            }
        } else {
            is_object($job) && isset($job->connection)
                ? $this->queue->connection($job->connection)->push($job, $data, $queue)
                : $this->queue->push($job, $data, $queue);
        }
    }

    /**
     * Determine if a job should be faked or actually dispatched.
     *
     * @param  object  $job
     * @return bool
     */
    public function shouldFakeJob($job)
    {
        if ($this->shouldDispatchJob($job)) {
            return false;
        }

        if ($this->jobsToFake->isEmpty()) {
            return true;
        }

        return $this->jobsToFake->contains(
            fn ($jobToFake) => $job instanceof ((string) $jobToFake) || $job === (string) $jobToFake
        );
    }

    /**
     * Determine if a job should be pushed to the queue instead of faked.
     *
     * @param  object  $job
     * @return bool
     */
    protected function shouldDispatchJob($job)
    {
        if ($this->jobsToBeQueued->isEmpty()) {
            return false;
        }

        return $this->jobsToBeQueued->contains(
            fn ($jobToQueue) => $job instanceof ((string) $jobToQueue)
        );
    }

    /**
     * Push a raw payload onto the queue.
     *
     * @param  string  $payload
     * @param  string|null  $queue
     * @param  array  $options
     * @return mixed
     */
    public function pushRaw($payload, $queue = null, array $options = [])
    {
        $this->rawPushes[] = [
            'payload' => $payload,
            'queue' => $queue,
            'options' => $options,
        ];
    }

    /**
     * Push a new job onto the queue after (n) seconds.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  string|object  $job
     * @param  mixed  $data
     * @param  string|null  $queue
     * @return mixed
     */
    public function later($delay, $job, $data = '', $queue = null)
    {
        return $this->push($job, $data, $queue);
    }

    /**
     * Push a new job onto the queue.
     *
     * @param  string  $queue
     * @param  string|object  $job
     * @param  mixed  $data
     * @return mixed
     */
    public function pushOn($queue, $job, $data = '')
    {
        return $this->push($job, $data, $queue);
    }

    /**
     * Push a new job onto a specific queue after (n) seconds.
     *
     * @param  string  $queue
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  string|object  $job
     * @param  mixed  $data
     * @return mixed
     */
    public function laterOn($queue, $delay, $job, $data = '')
    {
        return $this->push($job, $data, $queue);
    }

    /**
     * Pop the next job off of the queue.
     *
     * @param  string|null  $queue
     * @return \Illuminate\Contracts\Queue\Job|null
     */
    public function pop($queue = null)
    {
        //
    }

    /**
     * Push an array of jobs onto the queue.
     *
     * @param  array  $jobs
     * @param  mixed  $data
     * @param  string|null  $queue
     * @return mixed
     */
    public function bulk($jobs, $data = '', $queue = null)
    {
        foreach ($jobs as $job) {
            $this->push($job, $data, $queue);
        }
    }

    /**
     * Get the jobs that have been pushed.
     *
     * @return array
     */
    public function pushedJobs()
    {
        return $this->jobs;
    }

    /**
     * Get the payloads that were pushed raw.
     *
     * @return list<RawPushType>
     */
    public function rawPushes()
    {
        return $this->rawPushes;
    }

    /**
     * Specify if jobs should be serialized and restored when being "pushed" to the queue.
     *
     * @param  bool  $serializeAndRestore
     * @return $this
     */
    public function serializeAndRestore(bool $serializeAndRestore = true)
    {
        $this->serializeAndRestore = $serializeAndRestore;

        return $this;
    }

    /**
     * Serialize and unserialize the job to simulate the queueing process.
     *
     * @param  mixed  $job
     * @return mixed
     */
    protected function serializeAndRestoreJob($job)
    {
        return unserialize(serialize($job));
    }

    /**
     * Release the locks for all unique jobs that were pushed.
     *
     * @return void
     */
    public function releaseUniqueJobLocks()
    {
        $lock = new UniqueLock($this->app->make(Cache::class));

        foreach ($this->uniqueJobs as $job) {
            $lock->release($job);
        }

        $this->uniqueJobs = [];
    }

    /**
     * Get the connection name for the queue.
     *
     * @return string
     */
    public function getConnectionName()
    {
        //
    }

    /**
     * Set the connection name for the queue.
     *
     * @param  string  $name
     * @return $this
     */
    public function setConnectionName($name)
    {
        return $this;
    }

    /**
     * Override the QueueManager to prevent circular dependency.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public function __call($method, $parameters)
    {
        throw new BadMethodCallException(sprintf(
            'Call to undefined method %s::%s()', static::class, $method
        ));
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Exception;
use Illuminate\Contracts\Notifications\Dispatcher as NotificationDispatcher;
use Illuminate\Contracts\Notifications\Factory as NotificationFactory;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;

class NotificationFake implements Fake, NotificationDispatcher, NotificationFactory
{
    use Macroable, ReflectsClosures;

    /**
     * All of the notifications that have been sent.
     *
     * @var array
     */
    protected $notifications = [];

    /**
     * Locale used when sending notifications.
     *
     * @var string|null
     */
    public $locale;

    /**
     * Indicates if notifications should be serialized and restored when pushed to the queue.
     *
     * @var bool
     */
    protected $serializeAndRestore = false;

    /**
     * Assert if a notification was sent on-demand based on a truth-test callback.
     *
     * @param  string|\Closure  $notification
     * @param  callable|null  $callback
     * @return void
     *
     * @throws \Exception
     */
    public function assertSentOnDemand($notification, $callback = null)
    {
        $this->assertSentTo(new AnonymousNotifiable, $notification, $callback);
    }

    /**
     * Assert if a notification was sent based on a truth-test callback.
     *
     * @param  mixed  $notifiable
     * @param  string|\Closure  $notification
     * @param  callable|null  $callback
     * @return void
     *
     * @throws \Exception
     */
    public function assertSentTo($notifiable, $notification, $callback = null)
    {
        if (is_array($notifiable) || $notifiable instanceof Collection) {
            if (count($notifiable) === 0) {
                throw new Exception('No notifiable given.');
            }

            foreach ($notifiable as $singleNotifiable) {
                $this->assertSentTo($singleNotifiable, $notification, $callback);
            }

            return;
        }

        if ($notification instanceof Closure) {
            [$notification, $callback] = [$this->firstClosureParameterType($notification), $notification];
        }

        if (is_numeric($callback)) {
            return $this->assertSentToTimes($notifiable, $notification, $callback);
        }

        PHPUnit::assertTrue(
            $this->sent($notifiable, $notification, $callback)->count() > 0,
            "The expected [{$notification}] notification was not sent."
        );
    }

    /**
     * Assert if a notification was sent on-demand a number of times.
     *
     * @param  string  $notification
     * @param  int  $times
     * @return void
     */
    public function assertSentOnDemandTimes($notification, $times = 1)
    {
        $this->assertSentToTimes(new AnonymousNotifiable, $notification, $times);
    }

    /**
     * Assert if a notification was sent a number of times.
     *
     * @param  mixed  $notifiable
     * @param  string  $notification
     * @param  int  $times
     * @return void
     */
    public function assertSentToTimes($notifiable, $notification, $times = 1)
    {
        $count = $this->sent($notifiable, $notification)->count();

        PHPUnit::assertSame(
            $times, $count,
            "Expected [{$notification}] to be sent {$times} times, but was sent {$count} times."
        );
    }

    /**
     * Determine if a notification was sent based on a truth-test callback.
     *
     * @param  mixed  $notifiable
     * @param  string|\Closure  $notification
     * @param  callable|null  $callback
     * @return void
     *
     * @throws \Exception
     */
    public function assertNotSentTo($notifiable, $notification, $callback = null)
    {
        if (is_array($notifiable) || $notifiable instanceof Collection) {
            if (count($notifiable) === 0) {
                throw new Exception('No notifiable given.');
            }

            foreach ($notifiable as $singleNotifiable) {
                $this->assertNotSentTo($singleNotifiable, $notification, $callback);
            }

            return;
        }

        if ($notification instanceof Closure) {
            [$notification, $callback] = [$this->firstClosureParameterType($notification), $notification];
        }

        PHPUnit::assertCount(
            0, $this->sent($notifiable, $notification, $callback),
            "The unexpected [{$notification}] notification was sent."
        );
    }

    /**
     * Assert that no notifications were sent.
     *
     * @return void
     */
    public function assertNothingSent()
    {
        $notificationNames = (new Collection($this->notifications))
            ->map(fn ($notifiableModels) => (new Collection($notifiableModels))
                ->map(fn ($notifiables) => (new Collection($notifiables))->keys())
            )
            ->flatten()->join("\n- ");

        PHPUnit::assertEmpty($this->notifications, "The following notifications were sent unexpectedly:\n\n- $notificationNames\n");
    }

    /**
     * Assert that no notifications were sent to the given notifiable.
     *
     * @param  mixed  $notifiable
     * @return void
     *
     * @throws \Exception
     */
    public function assertNothingSentTo($notifiable)
    {
        if (is_array($notifiable) || $notifiable instanceof Collection) {
            if (count($notifiable) === 0) {
                throw new Exception('No notifiable given.');
            }

            foreach ($notifiable as $singleNotifiable) {
                $this->assertNothingSentTo($singleNotifiable);
            }

            return;
        }

        PHPUnit::assertEmpty(
            $this->notifications[get_class($notifiable)][$notifiable->getKey() ?? ''] ?? [],
            'Notifications were sent unexpectedly.',
        );
    }

    /**
     * Assert the total amount of times a notification was sent.
     *
     * @param  string  $notification
     * @param  int  $expectedCount
     * @return void
     */
    public function assertSentTimes($notification, $expectedCount)
    {
        $actualCount = (new Collection($this->notifications))
            ->flatten(1)
            ->reduce(fn ($count, $sent) => $count + count($sent[$notification] ?? []), 0);

        PHPUnit::assertSame(
            $expectedCount, $actualCount,
            sprintf(
                "Expected [{$notification}] to be sent {$expectedCount} %s, but was sent {$actualCount} %s.",
                Str::plural('time', $expectedCount),
                Str::plural('time', $actualCount)
            )
        );
    }

    /**
     * Assert the total count of notification that were sent.
     *
     * @param  int  $expectedCount
     * @return void
     */
    public function assertCount($expectedCount)
    {
        $actualCount = (new Collection($this->notifications))->flatten(3)->count();

        PHPUnit::assertSame(
            $expectedCount, $actualCount,
            "Expected {$expectedCount} notifications to be sent, but {$actualCount} were sent."
        );
    }

    /**
     * Get all of the notifications matching a truth-test callback.
     *
     * @param  mixed  $notifiable
     * @param  string  $notification
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function sent($notifiable, $notification, $callback = null)
    {
        if (! $this->hasSent($notifiable, $notification)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        $notifications = new Collection($this->notificationsFor($notifiable, $notification));

        return $notifications->filter(
            fn ($arguments) => $callback(...array_values($arguments))
        )->pluck('notification');
    }

    /**
     * Determine if there are more notifications left to inspect.
     *
     * @param  mixed  $notifiable
     * @param  string  $notification
     * @return bool
     */
    public function hasSent($notifiable, $notification)
    {
        return ! empty($this->notificationsFor($notifiable, $notification));
    }

    /**
     * Get all of the notifications for a notifiable entity by type.
     *
     * @param  mixed  $notifiable
     * @param  string  $notification
     * @return array
     */
    protected function notificationsFor($notifiable, $notification)
    {
        return $this->notifications[get_class($notifiable)][(string) $notifiable->getKey()][$notification] ?? [];
    }

    /**
     * Send the given notification to the given notifiable entities.
     *
     * @param  \Illuminate\Support\Collection|mixed  $notifiables
     * @param  mixed  $notification
     * @return void
     */
    public function send($notifiables, $notification)
    {
        $this->sendNow($notifiables, $notification);
    }

    /**
     * Send the given notification immediately.
     *
     * @param  \Illuminate\Support\Collection|mixed  $notifiables
     * @param  mixed  $notification
     * @param  array|null  $channels
     * @return void
     */
    public function sendNow($notifiables, $notification, ?array $channels = null)
    {
        if (! $notifiables instanceof Collection && ! is_array($notifiables)) {
            $notifiables = [$notifiables];
        }

        foreach ($notifiables as $notifiable) {
            if (! $notification->id) {
                $notification->id = (string) Str::uuid();
            }

            $notifiableChannels = $channels ?: $notification->via($notifiable);

            if (method_exists($notification, 'shouldSend')) {
                $notifiableChannels = array_filter(
                    $notifiableChannels,
                    fn ($channel) => $notification->shouldSend($notifiable, $channel) !== false
                );
            }

            if (empty($notifiableChannels)) {
                continue;
            }

            $this->notifications[get_class($notifiable)][(string) $notifiable->getKey()][get_class($notification)][] = [
                'notification' => $this->serializeAndRestore && $notification instanceof ShouldQueue
                    ? $this->serializeAndRestoreNotification($notification)
                    : $notification,
                'channels' => $notifiableChannels,
                'notifiable' => $notifiable,
                'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) {
                    if ($notifiable instanceof HasLocalePreference) {
                        return $notifiable->preferredLocale();
                    }
                }),
            ];
        }
    }

    /**
     * Get a channel instance by name.
     *
     * @param  string|null  $name
     * @return mixed
     */
    public function channel($name = null)
    {
        //
    }

    /**
     * Set the locale of notifications.
     *
     * @param  string  $locale
     * @return $this
     */
    public function locale($locale)
    {
        $this->locale = $locale;

        return $this;
    }

    /**
     * Specify if notification should be serialized and restored when being "pushed" to the queue.
     *
     * @param  bool  $serializeAndRestore
     * @return $this
     */
    public function serializeAndRestore(bool $serializeAndRestore = true)
    {
        $this->serializeAndRestore = $serializeAndRestore;

        return $this;
    }

    /**
     * Serialize and unserialize the notification to simulate the queueing process.
     *
     * @param  mixed  $notification
     * @return mixed
     */
    protected function serializeAndRestoreNotification($notification)
    {
        return unserialize(serialize($notification));
    }

    /**
     * Get the notifications that have been sent.
     *
     * @return array
     */
    public function sentNotifications()
    {
        return $this->notifications;
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Illuminate\Contracts\Mail\Factory;
use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Mail\MailQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\MailManager;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;

class MailFake implements Factory, Fake, Mailer, MailQueue
{
    use ForwardsCalls, ReflectsClosures;

    /**
     * The mailer instance.
     *
     * @var MailManager
     */
    public $manager;

    /**
     * The mailer currently being used to send a message.
     *
     * @var string
     */
    protected $currentMailer;

    /**
     * All of the mailables that have been sent.
     *
     * @var array
     */
    protected $mailables = [];

    /**
     * All of the mailables that have been queued.
     *
     * @var array
     */
    protected $queuedMailables = [];

    /**
     * Create a new mail fake.
     *
     * @param  MailManager  $manager
     */
    public function __construct(MailManager $manager)
    {
        $this->manager = $manager;
        $this->currentMailer = $manager->getDefaultDriver();
    }

    /**
     * Assert if a mailable was sent based on a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|array|string|int|null  $callback
     * @return void
     */
    public function assertSent($mailable, $callback = null)
    {
        [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);

        if (is_numeric($callback)) {
            return $this->assertSentTimes($mailable, $callback);
        }

        $suggestion = count($this->queuedMailables) ? ' Did you mean to use assertQueued() instead?' : '';

        if (is_array($callback) || is_string($callback)) {
            foreach (Arr::wrap($callback) as $address) {
                $callback = fn ($mail) => $mail->hasTo($address);

                PHPUnit::assertTrue(
                    $this->sent($mailable, $callback)->count() > 0,
                    "The expected [{$mailable}] mailable was not sent to address [{$address}].".$suggestion
                );
            }

            return;
        }

        PHPUnit::assertTrue(
            $this->sent($mailable, $callback)->count() > 0,
            "The expected [{$mailable}] mailable was not sent.".$suggestion
        );
    }

    /**
     * Assert if a mailable was sent a number of times.
     *
     * @param  string  $mailable
     * @param  int  $times
     * @return void
     */
    public function assertSentTimes($mailable, $times = 1)
    {
        $count = $this->sent($mailable)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$mailable}] mailable was sent {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Determine if a mailable was not sent or queued to be sent based on a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|null  $callback
     * @return void
     */
    public function assertNotOutgoing($mailable, $callback = null)
    {
        $this->assertNotSent($mailable, $callback);
        $this->assertNotQueued($mailable, $callback);
    }

    /**
     * Determine if a mailable was not sent based on a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|array|string|null  $callback
     * @return void
     */
    public function assertNotSent($mailable, $callback = null)
    {
        if (is_string($callback) || is_array($callback)) {
            foreach (Arr::wrap($callback) as $address) {
                $callback = fn ($mail) => $mail->hasTo($address);

                PHPUnit::assertCount(
                    0, $this->sent($mailable, $callback),
                    "The unexpected [{$mailable}] mailable was sent to address [{$address}]."
                );
            }

            return;
        }

        [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);

        PHPUnit::assertCount(
            0, $this->sent($mailable, $callback),
            "The unexpected [{$mailable}] mailable was sent."
        );
    }

    /**
     * Assert that no mailables were sent or queued to be sent.
     *
     * @return void
     */
    public function assertNothingOutgoing()
    {
        $this->assertNothingSent();
        $this->assertNothingQueued();
    }

    /**
     * Assert that no mailables were sent.
     *
     * @return void
     */
    public function assertNothingSent()
    {
        $mailableNames = (new Collection($this->mailables))->map(
            fn ($mailable) => get_class($mailable)
        )->join("\n- ");

        PHPUnit::assertEmpty($this->mailables, "The following mailables were sent unexpectedly:\n\n- $mailableNames\n");
    }

    /**
     * Assert if a mailable was queued based on a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|array|string|int|null  $callback
     * @return void
     */
    public function assertQueued($mailable, $callback = null)
    {
        [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);

        if (is_numeric($callback)) {
            return $this->assertQueuedTimes($mailable, $callback);
        }

        if (is_string($callback) || is_array($callback)) {
            foreach (Arr::wrap($callback) as $address) {
                $callback = fn ($mail) => $mail->hasTo($address);

                PHPUnit::assertTrue(
                    $this->queued($mailable, $callback)->count() > 0,
                    "The expected [{$mailable}] mailable was not queued to address [{$address}]."
                );
            }

            return;
        }

        PHPUnit::assertTrue(
            $this->queued($mailable, $callback)->count() > 0,
            "The expected [{$mailable}] mailable was not queued."
        );
    }

    /**
     * Assert if a mailable was queued a number of times.
     *
     * @param  string  $mailable
     * @param  int  $times
     * @return void
     */
    protected function assertQueuedTimes($mailable, $times = 1)
    {
        $count = $this->queued($mailable)->count();

        PHPUnit::assertSame(
            $times, $count,
            sprintf(
                "The expected [{$mailable}] mailable was queued {$count} %s instead of {$times} %s.",
                Str::plural('time', $count),
                Str::plural('time', $times)
            )
        );
    }

    /**
     * Determine if a mailable was not queued based on a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|array|string|null  $callback
     * @return void
     */
    public function assertNotQueued($mailable, $callback = null)
    {
        if (is_string($callback) || is_array($callback)) {
            foreach (Arr::wrap($callback) as $address) {
                $callback = fn ($mail) => $mail->hasTo($address);

                PHPUnit::assertCount(
                    0, $this->queued($mailable, $callback),
                    "The unexpected [{$mailable}] mailable was queued to address [{$address}]."
                );
            }

            return;
        }

        [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);

        PHPUnit::assertCount(
            0, $this->queued($mailable, $callback),
            "The unexpected [{$mailable}] mailable was queued."
        );
    }

    /**
     * Assert that no mailables were queued.
     *
     * @return void
     */
    public function assertNothingQueued()
    {
        $mailableNames = (new Collection($this->queuedMailables))->map(
            fn ($mailable) => get_class($mailable)
        )->join("\n- ");

        PHPUnit::assertEmpty($this->queuedMailables, "The following mailables were queued unexpectedly:\n\n- $mailableNames\n");
    }

    /**
     * Assert the total number of mailables that were sent.
     *
     * @param  int  $count
     * @return void
     */
    public function assertSentCount($count)
    {
        $total = (new Collection($this->mailables))->count();

        PHPUnit::assertSame(
            $count, $total,
            "The total number of mailables sent was {$total} instead of {$count}."
        );
    }

    /**
     * Assert the total number of mailables that were queued.
     *
     * @param  int  $count
     * @return void
     */
    public function assertQueuedCount($count)
    {
        $total = (new Collection($this->queuedMailables))->count();

        PHPUnit::assertSame(
            $count, $total,
            "The total number of mailables queued was {$total} instead of {$count}."
        );
    }

    /**
     * Assert the total number of mailables that were sent or queued.
     *
     * @param  int  $count
     * @return void
     */
    public function assertOutgoingCount($count)
    {
        $total = (new Collection($this->mailables))
            ->concat($this->queuedMailables)
            ->count();

        PHPUnit::assertSame(
            $count, $total,
            "The total number of outgoing mailables was {$total} instead of {$count}."
        );
    }

    /**
     * Get all of the mailables matching a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function sent($mailable, $callback = null)
    {
        [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);

        if (! $this->hasSent($mailable)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return $this->mailablesOf($mailable)->filter(fn ($mailable) => $callback($mailable));
    }

    /**
     * Determine if the given mailable has been sent.
     *
     * @param  string  $mailable
     * @return bool
     */
    public function hasSent($mailable)
    {
        return $this->mailablesOf($mailable)->count() > 0;
    }

    /**
     * Get all of the queued mailables matching a truth-test callback.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|null  $callback
     * @return \Illuminate\Support\Collection
     */
    public function queued($mailable, $callback = null)
    {
        [$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);

        if (! $this->hasQueued($mailable)) {
            return new Collection;
        }

        $callback = $callback ?: fn () => true;

        return $this->queuedMailablesOf($mailable)->filter(fn ($mailable) => $callback($mailable));
    }

    /**
     * Determine if the given mailable has been queued.
     *
     * @param  string  $mailable
     * @return bool
     */
    public function hasQueued($mailable)
    {
        return $this->queuedMailablesOf($mailable)->count() > 0;
    }

    /**
     * Get all of the mailed mailables for a given type.
     *
     * @param  string  $type
     * @return \Illuminate\Support\Collection
     */
    protected function mailablesOf($type)
    {
        return (new Collection($this->mailables))->filter(fn ($mailable) => $mailable instanceof $type);
    }

    /**
     * Get all of the mailed mailables for a given type.
     *
     * @param  string  $type
     * @return \Illuminate\Support\Collection
     */
    protected function queuedMailablesOf($type)
    {
        return (new Collection($this->queuedMailables))->filter(fn ($mailable) => $mailable instanceof $type);
    }

    /**
     * Get a mailer instance by name.
     *
     * @param  string|null  $name
     * @return \Illuminate\Contracts\Mail\Mailer
     */
    public function mailer($name = null)
    {
        $this->currentMailer = $name;

        return $this;
    }

    /**
     * Get a mailer driver instance.
     *
     * @param  string|null  $driver
     * @return \Illuminate\Contracts\Mail\Mailer
     */
    public function driver($driver = null)
    {
        return $this->mailer($driver);
    }

    /**
     * Begin the process of mailing a mailable class instance.
     *
     * @param  mixed  $users
     * @return \Illuminate\Mail\PendingMail
     */
    public function to($users)
    {
        return (new PendingMailFake($this))->to($users);
    }

    /**
     * Begin the process of mailing a mailable class instance.
     *
     * @param  mixed  $users
     * @return \Illuminate\Mail\PendingMail
     */
    public function cc($users)
    {
        return (new PendingMailFake($this))->cc($users);
    }

    /**
     * Begin the process of mailing a mailable class instance.
     *
     * @param  mixed  $users
     * @return \Illuminate\Mail\PendingMail
     */
    public function bcc($users)
    {
        return (new PendingMailFake($this))->bcc($users);
    }

    /**
     * Send a new message with only a raw text part.
     *
     * @param  string  $text
     * @param  \Closure|string  $callback
     * @return void
     */
    public function raw($text, $callback)
    {
        //
    }

    /**
     * Send a new message using a view.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  array  $data
     * @param  \Closure|string|null  $callback
     * @return mixed|void
     */
    public function send($view, array $data = [], $callback = null)
    {
        return $this->sendMail($view, $view instanceof ShouldQueue);
    }

    /**
     * Send a new message synchronously using a view.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $mailable
     * @param  array  $data
     * @param  \Closure|string|null  $callback
     * @return void
     */
    public function sendNow($mailable, array $data = [], $callback = null)
    {
        $this->sendMail($mailable, shouldQueue: false);
    }

    /**
     * Send a new message using a view.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  bool  $shouldQueue
     * @return mixed|void
     */
    protected function sendMail($view, $shouldQueue = false)
    {
        if (! $view instanceof Mailable) {
            return;
        }

        $view->mailer($this->currentMailer);

        if ($shouldQueue) {
            return $this->queue($view);
        }

        $this->currentMailer = null;

        $this->mailables[] = $view;
    }

    /**
     * Queue a new message for sending.
     *
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  string|null  $queue
     * @return mixed
     */
    public function queue($view, $queue = null)
    {
        if (! $view instanceof Mailable) {
            return;
        }

        $view->mailer($this->currentMailer);

        $this->currentMailer = null;

        $this->queuedMailables[] = $view;
    }

    /**
     * Queue a new e-mail message for sending after (n) seconds.
     *
     * @param  \DateTimeInterface|\DateInterval|int  $delay
     * @param  \Illuminate\Contracts\Mail\Mailable|string|array  $view
     * @param  string|null  $queue
     * @return mixed
     */
    public function later($delay, $view, $queue = null)
    {
        $this->queue($view, $queue);
    }

    /**
     * Infer mailable class using reflection if a typehinted closure is passed to assertion.
     *
     * @param  string|\Closure  $mailable
     * @param  callable|null  $callback
     * @return array
     */
    protected function prepareMailableAndCallback($mailable, $callback)
    {
        if ($mailable instanceof Closure) {
            return [$this->firstClosureParameterType($mailable), $mailable];
        }

        return [$mailable, $callback];
    }

    /**
     * Forget all of the resolved mailer instances.
     *
     * @return $this
     */
    public function forgetMailers()
    {
        $this->currentMailer = null;

        return $this;
    }

    /**
     * Handle dynamic method calls to the mailer.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->forwardCallTo($this->manager, $method, $parameters);
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;

class ChainedBatchTruthTest
{
    /**
     * The underlying truth test.
     *
     * @var \Closure(\Illuminate\Bus\PendingBatch): bool
     */
    protected $callback;

    /**
     * Create a new truth test instance.
     *
     * @param  \Closure(\Illuminate\Bus\PendingBatch): bool  $callback
     */
    public function __construct(Closure $callback)
    {
        $this->callback = $callback;
    }

    /**
     * Invoke the truth test with the given pending batch.
     *
     * @param  \Illuminate\Bus\PendingBatch  $pendingBatch
     * @return bool
     */
    public function __invoke($pendingBatch)
    {
        return call_user_func($this->callback, $pendingBatch);
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Closure;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Foundation\Testing\Concerns\WithoutExceptionHandlingHandler;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\ReflectsClosures;
use Illuminate\Testing\Assert;
use PHPUnit\Framework\Assert as PHPUnit;
use PHPUnit\Framework\ExpectationFailedException;
use Throwable;

/**
 * @mixin \Illuminate\Foundation\Exceptions\Handler
 */
class ExceptionHandlerFake implements ExceptionHandler, Fake
{
    use ForwardsCalls, ReflectsClosures;

    /**
     * All of the exceptions that have been reported.
     *
     * @var list<\Throwable>
     */
    protected $reported = [];

    /**
     * If the fake should throw exceptions when they are reported.
     *
     * @var bool
     */
    protected $throwOnReport = false;

    /**
     * Create a new exception handler fake.
     *
     * @param  \Illuminate\Contracts\Debug\ExceptionHandler  $handler
     * @param  list<class-string<\Throwable>>  $exceptions
     */
    public function __construct(
        protected ExceptionHandler $handler,
        protected array $exceptions = [],
    ) {
        //
    }

    /**
     * Get the underlying handler implementation.
     *
     * @return \Illuminate\Contracts\Debug\ExceptionHandler
     */
    public function handler()
    {
        return $this->handler;
    }

    /**
     * Assert if an exception of the given type has been reported.
     *
     * @param  (\Closure(\Throwable): bool)|class-string<\Throwable>  $exception
     * @return void
     */
    public function assertReported(Closure|string $exception)
    {
        $message = sprintf(
            'The expected [%s] exception was not reported.',
            is_string($exception) ? $exception : $this->firstClosureParameterType($exception)
        );

        if (is_string($exception)) {
            Assert::assertTrue(
                in_array($exception, array_map(get_class(...), $this->reported), true),
                $message,
            );

            return;
        }

        Assert::assertTrue(
            (new Collection($this->reported))->contains(
                fn (Throwable $e) => $this->firstClosureParameterType($exception) === get_class($e)
                    && $exception($e) === true,
            ), $message,
        );
    }

    /**
     * Assert the number of exceptions that have been reported.
     *
     * @param  int  $count
     * @return void
     */
    public function assertReportedCount(int $count)
    {
        $total = (new Collection($this->reported))->count();

        PHPUnit::assertSame(
            $count, $total,
            "The total number of exceptions reported was {$total} instead of {$count}."
        );
    }

    /**
     * Assert if an exception of the given type has not been reported.
     *
     * @param  (\Closure(\Throwable): bool)|class-string<\Throwable>  $exception
     * @return void
     *
     * @throws \PHPUnit\Framework\ExpectationFailedException
     */
    public function assertNotReported(Closure|string $exception)
    {
        try {
            $this->assertReported($exception);
        } catch (ExpectationFailedException) {
            return;
        }

        throw new ExpectationFailedException(sprintf(
            'The expected [%s] exception was reported.',
            is_string($exception) ? $exception : $this->firstClosureParameterType($exception)
        ));
    }

    /**
     * Assert nothing has been reported.
     *
     * @return void
     */
    public function assertNothingReported()
    {
        Assert::assertEmpty(
            $this->reported,
            sprintf(
                'The following exceptions were reported: %s.',
                implode(', ', array_map(get_class(...), $this->reported)),
            ),
        );
    }

    /**
     * Report or log an exception.
     *
     * @param  \Throwable  $e
     * @return void
     *
     * @throws \Throwable
     */
    public function report($e)
    {
        if (! $this->isFakedException($e)) {
            $this->handler->report($e);

            return;
        }

        if (! $this->shouldReport($e)) {
            return;
        }

        $this->reported[] = $e;

        if ($this->throwOnReport) {
            throw $e;
        }
    }

    /**
     * Determine if the given exception is faked.
     *
     * @param  \Throwable  $e
     * @return bool
     */
    protected function isFakedException(Throwable $e)
    {
        return $this->exceptions === [] || in_array(get_class($e), $this->exceptions, true);
    }

    /**
     * Determine if the exception should be reported.
     *
     * @param  \Throwable  $e
     * @return bool
     */
    public function shouldReport($e)
    {
        return $this->runningWithoutExceptionHandling() || $this->handler->shouldReport($e);
    }

    /**
     * Determine if the handler is running without exception handling.
     *
     * @return bool
     */
    protected function runningWithoutExceptionHandling()
    {
        return $this->handler instanceof WithoutExceptionHandlingHandler;
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $e
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function render($request, $e)
    {
        return $this->handler->render($request, $e);
    }

    /**
     * Render an exception to the console.
     *
     * @param  \Symfony\Component\Console\Output\OutputInterface  $output
     * @param  \Throwable  $e
     * @return void
     */
    public function renderForConsole($output, Throwable $e)
    {
        $this->handler->renderForConsole($output, $e);
    }

    /**
     * Throw exceptions when they are reported.
     *
     * @return $this
     */
    public function throwOnReport()
    {
        $this->throwOnReport = true;

        return $this;
    }

    /**
     * Throw the first reported exception.
     *
     * @return $this
     *
     * @throws \Throwable
     */
    public function throwFirstReported()
    {
        foreach ($this->reported as $e) {
            throw $e;
        }

        return $this;
    }

    /**
     * Get the exceptions that have been reported.
     *
     * @return list<\Throwable>
     */
    public function reported()
    {
        return $this->reported;
    }

    /**
     * Set the "original" handler that should be used by the fake.
     *
     * @param  \Illuminate\Contracts\Debug\ExceptionHandler  $handler
     * @return $this
     */
    public function setHandler(ExceptionHandler $handler)
    {
        $this->handler = $handler;

        return $this;
    }

    /**
     * Handle dynamic method calls to the handler.
     *
     * @param  string  $method
     * @param  array<string, mixed>  $parameters
     * @return mixed
     */
    public function __call(string $method, array $parameters)
    {
        return $this->forwardCallTo($this->handler, $method, $parameters);
    }
}
<?php

namespace Illuminate\Support\Testing\Fakes;

use Carbon\CarbonImmutable;
use Illuminate\Bus\Batch;
use Illuminate\Bus\UpdatedBatchJobCounts;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Throwable;

class BatchFake extends Batch
{
    /**
     * The jobs that have been added to the batch.
     *
     * @var array
     */
    public $added = [];

    /**
     * Indicates if the batch has been deleted.
     *
     * @var bool
     */
    public $deleted = false;

    /**
     * Create a new batch instance.
     *
     * @param  string  $id
     * @param  string  $name
     * @param  int  $totalJobs
     * @param  int  $pendingJobs
     * @param  int  $failedJobs
     * @param  array  $failedJobIds
     * @param  array  $options
     * @param  \Carbon\CarbonImmutable  $createdAt
     * @param  \Carbon\CarbonImmutable|null  $cancelledAt
     * @param  \Carbon\CarbonImmutable|null  $finishedAt
     */
    public function __construct(
        string $id,
        string $name,
        int $totalJobs,
        int $pendingJobs,
        int $failedJobs,
        array $failedJobIds,
        array $options,
        CarbonImmutable $createdAt,
        ?CarbonImmutable $cancelledAt = null,
        ?CarbonImmutable $finishedAt = null,
    ) {
        $this->id = $id;
        $this->name = $name;
        $this->totalJobs = $totalJobs;
        $this->pendingJobs = $pendingJobs;
        $this->failedJobs = $failedJobs;
        $this->failedJobIds = $failedJobIds;
        $this->options = $options;
        $this->createdAt = $createdAt;
        $this->cancelledAt = $cancelledAt;
        $this->finishedAt = $finishedAt;
    }

    /**
     * Get a fresh instance of the batch represented by this ID.
     *
     * @return self
     */
    #[\Override]
    public function fresh()
    {
        return $this;
    }

    /**
     * Add additional jobs to the batch.
     *
     * @param  \Illuminate\Support\Enumerable|object|array  $jobs
     * @return self
     */
    #[\Override]
    public function add($jobs)
    {
        $jobs = Collection::wrap($jobs);

        foreach ($jobs as $job) {
            $this->added[] = $job;
        }

        $this->totalJobs += $jobs->count();

        return $this;
    }

    /**
     * Record that a job within the batch finished successfully, executing any callbacks if necessary.
     *
     * @param  string  $jobId
     * @return void
     */
    #[\Override]
    public function recordSuccessfulJob(string $jobId)
    {
        //
    }

    /**
     * Decrement the pending jobs for the batch.
     *
     * @param  string  $jobId
     * @return void
     */
    #[\Override]
    public function decrementPendingJobs(string $jobId)
    {
        //
    }

    /**
     * Record that a job within the batch failed to finish successfully, executing any callbacks if necessary.
     *
     * @param  string  $jobId
     * @param  \Throwable  $e
     * @return void
     */
    #[\Override]
    public function recordFailedJob(string $jobId, $e)
    {
        //
    }

    /**
     * Increment the failed jobs for the batch.
     *
     * @param  string  $jobId
     * @return \Illuminate\Bus\UpdatedBatchJobCounts
     */
    #[\Override]
    public function incrementFailedJobs(string $jobId)
    {
        return new UpdatedBatchJobCounts;
    }

    /**
     * Cancel the batch.
     *
     * @return void
     */
    #[\Override]
    public function cancel(?Throwable $exception = null)
    {
        $this->cancelledAt = Carbon::now();
    }

    /**
     * Delete the batch from storage.
     *
     * @return void
     */
    #[\Override]
    public function delete()
    {
        $this->deleted = true;
    }

    /**
     * Determine if the batch has been deleted.
     *
     * @return bool
     */
    public function deleted()
    {
        return $this->deleted;
    }
}
<?php

namespace Illuminate\Support;

use Carbon\Carbon as BaseCarbon;
use Carbon\CarbonImmutable as BaseCarbonImmutable;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Dumpable;
use Ramsey\Uuid\Uuid;
use Symfony\Component\Uid\Ulid;

class Carbon extends BaseCarbon
{
    use Conditionable, Dumpable;

    /**
     * {@inheritdoc}
     */
    public static function setTestNow(mixed $testNow = null): void
    {
        BaseCarbon::setTestNow($testNow);
        BaseCarbonImmutable::setTestNow($testNow);
    }

    /**
     * Create a Carbon instance from a given ordered UUID or ULID.
     */
    public static function createFromId(Uuid|Ulid|string $id): static
    {
        if (is_string($id)) {
            $id = Ulid::isValid($id) ? Ulid::fromString($id) : Uuid::fromString($id);
        }

        return static::createFromInterface($id->getDateTime());
    }

    /**
     * Get the current date / time plus a given amount of time.
     */
    public function plus(
        int $years = 0,
        int $months = 0,
        int $weeks = 0,
        int $days = 0,
        int $hours = 0,
        int $minutes = 0,
        int $seconds = 0,
        int $microseconds = 0,
        ?bool $overflow = null
    ): static {
        return $this->add('years', $years, $overflow)
            ->add('months', $months, $overflow)
            ->add("
                $weeks weeks $days days
                $hours hours $minutes minutes $seconds seconds $microseconds microseconds
            ");
    }

    /**
     * Get the current date / time minus a given amount of time.
     */
    public function minus(
        int $years = 0,
        int $months = 0,
        int $weeks = 0,
        int $days = 0,
        int $hours = 0,
        int $minutes = 0,
        int $seconds = 0,
        int $microseconds = 0,
        ?bool $overflow = null
    ): static {
        return $this->sub('years', $years, $overflow)
            ->sub('months', $months, $overflow)
            ->sub("
                $weeks weeks $days days
                $hours hours $minutes minutes $seconds seconds $microseconds microseconds
            ");
    }
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Filesystem\Filesystem;
use RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;

class Composer
{
    /**
     * The filesystem instance.
     *
     * @var \Illuminate\Filesystem\Filesystem
     */
    protected $files;

    /**
     * The working path to regenerate from.
     *
     * @var string|null
     */
    protected $workingPath;

    /**
     * Create a new Composer manager instance.
     *
     * @param  \Illuminate\Filesystem\Filesystem  $files
     * @param  string|null  $workingPath
     */
    public function __construct(Filesystem $files, $workingPath = null)
    {
        $this->files = $files;
        $this->workingPath = $workingPath;
    }

    /**
     * Determine if the given Composer package is installed.
     *
     * @param  string  $package
     * @return bool
     *
     * @throws \RuntimeException
     */
    public function hasPackage($package)
    {
        $composer = json_decode(file_get_contents($this->findComposerFile()), true);

        return array_key_exists($package, $composer['require'] ?? [])
            || array_key_exists($package, $composer['require-dev'] ?? []);
    }

    /**
     * Install the given Composer packages into the application.
     *
     * @param  array<int, string>  $packages
     * @param  bool  $dev
     * @param  \Closure|\Symfony\Component\Console\Output\OutputInterface|null  $output
     * @param  string|null  $composerBinary
     * @return bool
     */
    public function requirePackages(array $packages, bool $dev = false, Closure|OutputInterface|null $output = null, $composerBinary = null)
    {
        $command = (new Collection([
            ...$this->findComposer($composerBinary),
            'require',
            ...$packages,
        ]))
            ->when($dev, function ($command) {
                $command->push('--dev');
            })->all();

        return 0 === $this->getProcess($command, ['COMPOSER_MEMORY_LIMIT' => '-1'])
            ->run(
                $output instanceof OutputInterface
                    ? function ($type, $line) use ($output) {
                        $output->write('    '.$line);
                    } : $output
            );
    }

    /**
     * Remove the given Composer packages from the application.
     *
     * @param  array<int, string>  $packages
     * @param  bool  $dev
     * @param  \Closure|\Symfony\Component\Console\Output\OutputInterface|null  $output
     * @param  string|null  $composerBinary
     * @return bool
     */
    public function removePackages(array $packages, bool $dev = false, Closure|OutputInterface|null $output = null, $composerBinary = null)
    {
        $command = (new Collection([
            ...$this->findComposer($composerBinary),
            'remove',
            ...$packages,
        ]))
            ->when($dev, function ($command) {
                $command->push('--dev');
            })->all();

        return 0 === $this->getProcess($command, ['COMPOSER_MEMORY_LIMIT' => '-1'])
            ->run(
                $output instanceof OutputInterface
                    ? function ($type, $line) use ($output) {
                        $output->write('    '.$line);
                    } : $output
            );
    }

    /**
     * Modify the "composer.json" file contents using the given callback.
     *
     * @param  callable(array<string, mixed>):array<string, mixed>  $callback
     * @return void
     *
     * @throws \RuntimeException
     */
    public function modify(callable $callback)
    {
        $composerFile = $this->findComposerFile();

        $composer = json_decode(file_get_contents($composerFile), true, 512, JSON_THROW_ON_ERROR);

        file_put_contents(
            $composerFile,
            json_encode(
                call_user_func($callback, $composer),
                JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
            )
        );
    }

    /**
     * Regenerate the Composer autoloader files.
     *
     * @param  string|array<string>  $extra
     * @param  string|null  $composerBinary
     * @return int
     */
    public function dumpAutoloads($extra = '', $composerBinary = null)
    {
        $extra = $extra ? (array) $extra : [];

        $command = array_merge($this->findComposer($composerBinary), ['dump-autoload'], $extra);

        return $this->getProcess($command)->run();
    }

    /**
     * Regenerate the optimized Composer autoloader files.
     *
     * @param  string|null  $composerBinary
     * @return int
     */
    public function dumpOptimized($composerBinary = null)
    {
        return $this->dumpAutoloads('--optimize', $composerBinary);
    }

    /**
     * Get the Composer binary / command for the environment.
     *
     * @param  string|null  $composerBinary
     * @return array<string>
     */
    public function findComposer($composerBinary = null)
    {
        if (! is_null($composerBinary) && $this->files->exists($composerBinary)) {
            return [$this->phpBinary(), $composerBinary];
        } elseif ($this->files->exists($this->workingPath.'/composer.phar')) {
            return [$this->phpBinary(), 'composer.phar'];
        }

        return ['composer'];
    }

    /**
     * Get the path to the "composer.json" file.
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    protected function findComposerFile()
    {
        $composerFile = "{$this->workingPath}/composer.json";

        if (! file_exists($composerFile)) {
            throw new RuntimeException("Unable to locate `composer.json` file at [{$this->workingPath}].");
        }

        return $composerFile;
    }

    /**
     * Get the PHP binary.
     *
     * @return string
     */
    protected function phpBinary()
    {
        return php_binary();
    }

    /**
     * Get a new Symfony process instance.
     *
     * @param  array<string>  $command
     * @param  array<string, string>  $env
     * @return \Symfony\Component\Process\Process
     */
    protected function getProcess(array $command, array $env = [])
    {
        return (new Process($command, $this->workingPath, $env))->setTimeout(null);
    }

    /**
     * Set the working path used by the class.
     *
     * @param  string  $path
     * @return $this
     */
    public function setWorkingPath($path)
    {
        $this->workingPath = realpath($path);

        return $this;
    }

    /**
     * Get the version of Composer.
     *
     * @return string|null
     */
    public function getVersion()
    {
        $command = array_merge($this->findComposer(), ['-V', '--no-ansi']);

        $process = $this->getProcess($command);

        $process->run();

        $output = $process->getOutput();

        if (preg_match('/(\d+(\.\d+){2})/', $output, $version)) {
            return $version[1];
        }

        return explode(' ', $output)[2] ?? null;
    }
}
<?php

namespace Illuminate\Support;

use Countable;
use Illuminate\Contracts\Support\MessageBag as MessageBagContract;
use Stringable;

/**
 * @mixin \Illuminate\Contracts\Support\MessageBag
 */
class ViewErrorBag implements Countable, Stringable
{
    /**
     * The array of the view error bags.
     *
     * @var array<string, \Illuminate\Contracts\Support\MessageBag>
     */
    protected $bags = [];

    /**
     * Checks if a named MessageBag exists in the bags.
     *
     * @param  string  $key
     * @return bool
     */
    public function hasBag($key = 'default')
    {
        return isset($this->bags[$key]);
    }

    /**
     * Get a MessageBag instance from the bags.
     *
     * @param  string  $key
     * @return \Illuminate\Contracts\Support\MessageBag
     */
    public function getBag($key)
    {
        return Arr::get($this->bags, $key) ?: new MessageBag;
    }

    /**
     * Get all the bags.
     *
     * @return array<string, \Illuminate\Contracts\Support\MessageBag>
     */
    public function getBags()
    {
        return $this->bags;
    }

    /**
     * Add a new MessageBag instance to the bags.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\MessageBag  $bag
     * @return $this
     */
    public function put($key, MessageBagContract $bag)
    {
        $this->bags[$key] = $bag;

        return $this;
    }

    /**
     * Determine if the default message bag has any messages.
     *
     * @return bool
     */
    public function any()
    {
        return $this->count() > 0;
    }

    /**
     * Get the number of messages in the default bag.
     *
     * @return int
     */
    public function count(): int
    {
        return $this->getBag('default')->count();
    }

    /**
     * Dynamically call methods on the default bag.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->getBag('default')->$method(...$parameters);
    }

    /**
     * Dynamically access a view error bag.
     *
     * @param  string  $key
     * @return \Illuminate\Contracts\Support\MessageBag
     */
    public function __get($key)
    {
        return $this->getBag($key);
    }

    /**
     * Dynamically set a view error bag.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\MessageBag  $value
     * @return void
     */
    public function __set($key, $value)
    {
        $this->put($key, $value);
    }

    /**
     * Convert the default bag to its string representation.
     *
     * @return string
     */
    public function __toString()
    {
        return (string) $this->getBag('default');
    }
}
<?php

namespace Illuminate\Support\Queue\Concerns;

use Illuminate\Container\Container;
use Illuminate\Queue\QueueRoutes;

trait ResolvesQueueRoutes
{
    /**
     * Resolve the default connection name for a given queueable instance.
     *
     * @param  object  $queueable
     * @return string|null
     */
    public function resolveConnectionFromQueueRoute($queueable)
    {
        return $this->queueRoutes()->getConnection($queueable);
    }

    /**
     * Resolve the default queue name for a given queueable instance.
     *
     * @param  object  $queueable
     * @return string|null
     */
    public function resolveQueueFromQueueRoute($queueable)
    {
        return $this->queueRoutes()->getQueue($queueable);
    }

    /**
     * Get the queue routes manager instance.
     *
     * @return \Illuminate\Queue\QueueRoutes
     */
    protected function queueRoutes()
    {
        $container = Container::getInstance();

        return $container->bound('queue.routes')
            ? $container->make('queue.routes')
            : new QueueRoutes;
    }
}
<?php

namespace Illuminate\Support;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\Support\Jsonable;
use JsonSerializable;
use Stringable;
use UnitEnum;

class Js implements Htmlable, Stringable
{
    /**
     * The JavaScript string.
     *
     * @var string
     */
    protected $js;

    /**
     * Flags that should be used when encoding to JSON.
     *
     * @var int
     */
    protected const REQUIRED_FLAGS = 0
        | JSON_HEX_TAG
        | JSON_HEX_APOS
        | JSON_HEX_AMP
        | JSON_HEX_QUOT
        | JSON_UNESCAPED_UNICODE
        | JSON_THROW_ON_ERROR;

    /**
     * Create a new class instance.
     *
     * @param  mixed  $data
     * @param  int|null  $flags
     * @param  int  $depth
     *
     * @throws \JsonException
     */
    public function __construct($data, $flags = 0, $depth = 512)
    {
        $this->js = $this->convertDataToJavaScriptExpression($data, $flags, $depth);
    }

    /**
     * Create a new JavaScript string from the given data.
     *
     * @param  mixed  $data
     * @param  int  $flags
     * @param  int  $depth
     * @return static
     *
     * @throws \JsonException
     */
    public static function from($data, $flags = 0, $depth = 512)
    {
        return new static($data, $flags, $depth);
    }

    /**
     * Convert the given data to a JavaScript expression.
     *
     * @param  mixed  $data
     * @param  int  $flags
     * @param  int  $depth
     * @return string
     *
     * @throws \JsonException
     */
    protected function convertDataToJavaScriptExpression($data, $flags = 0, $depth = 512)
    {
        if ($data instanceof self) {
            return $data->toHtml();
        }

        if ($data instanceof Htmlable &&
            ! $data instanceof Arrayable &&
            ! $data instanceof Jsonable &&
            ! $data instanceof JsonSerializable) {
            $data = $data->toHtml();
        }

        if ($data instanceof UnitEnum) {
            $data = enum_value($data);
        }

        $json = static::encode($data, $flags, $depth);

        if (is_string($data)) {
            return "'".substr($json, 1, -1)."'";
        }

        return $this->convertJsonToJavaScriptExpression($json, $flags);
    }

    /**
     * Encode the given data as JSON.
     *
     * Invalid UTF-8 sequences are replaced with � instead of throwing.
     *
     * @param  mixed  $data
     * @param  int  $flags
     * @param  int  $depth
     * @return string
     *
     * @throws \JsonException
     */
    public static function encode($data, $flags = 0, $depth = 512)
    {
        if ($data instanceof Jsonable) {
            return $data->toJson($flags | static::REQUIRED_FLAGS);
        }

        if ($data instanceof Arrayable && ! ($data instanceof JsonSerializable)) {
            $data = $data->toArray();
        }

        return json_encode($data, $flags | static::REQUIRED_FLAGS | JSON_INVALID_UTF8_SUBSTITUTE, $depth);
    }

    /**
     * Convert the given JSON to a JavaScript expression.
     *
     * @param  string  $json
     * @param  int  $flags
     * @return string
     *
     * @throws \JsonException
     */
    protected function convertJsonToJavaScriptExpression($json, $flags = 0)
    {
        if ($json === '[]' || $json === '{}') {
            return $json;
        }

        if (Str::startsWith($json, ['"', '{', '['])) {
            return "JSON.parse('".substr(json_encode($json, $flags | static::REQUIRED_FLAGS), 1, -1)."')";
        }

        return $json;
    }

    /**
     * Get the string representation of the data for use in HTML.
     *
     * @return string
     */
    public function toHtml()
    {
        return $this->js;
    }

    /**
     * Get the string representation of the data for use in HTML.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toHtml();
    }
}
<?php

use Carbon\CarbonInterval;
use Illuminate\Contracts\Support\DeferringDisplayableValue;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Env;
use Illuminate\Support\Fluent;
use Illuminate\Support\HigherOrderTapProxy;
use Illuminate\Support\Once;
use Illuminate\Support\Onceable;
use Illuminate\Support\Optional;
use Illuminate\Support\Sleep;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable as SupportStringable;

if (! function_exists('append_config')) {
    /**
     * Assign high numeric IDs to a config item to force appending.
     *
     * @param  array  $array
     */
    function append_config(array $array): array
    {
        $start = 9999;

        foreach ($array as $key => $value) {
            if (is_numeric($key)) {
                $start++;

                $array[$start] = Arr::pull($array, $key);
            }
        }

        return $array;
    }
}

if (! function_exists('blank')) {
    /**
     * Determine if the given value is "blank".
     *
     * @phpstan-assert-if-false !=null|'' $value
     *
     * @phpstan-assert-if-true !=numeric|bool $value
     *
     * @param  mixed  $value
     */
    function blank($value): bool
    {
        if (is_null($value)) {
            return true;
        }

        if (is_string($value)) {
            return trim($value) === '';
        }

        if (is_numeric($value) || is_bool($value)) {
            return false;
        }

        if ($value instanceof Model) {
            return false;
        }

        if ($value instanceof Countable) {
            return count($value) === 0;
        }

        if ($value instanceof Stringable) {
            return trim((string) $value) === '';
        }

        return empty($value);
    }
}

if (! function_exists('class_basename')) {
    /**
     * Get the class "basename" of the given object / class.
     *
     * @param  string|object  $class
     */
    function class_basename($class): string
    {
        $class = is_object($class) ? get_class($class) : $class;

        return basename(str_replace('\\', '/', $class));
    }
}

if (! function_exists('class_uses_recursive')) {
    /**
     * Returns all traits used by a class, its parent classes and trait of their traits.
     *
     * @param  object|string  $class
     * @return array<string, string>
     */
    function class_uses_recursive($class): array
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        $results = [];

        foreach (array_reverse(class_parents($class) ?: []) + [$class => $class] as $class) {
            $results += trait_uses_recursive($class);
        }

        return array_unique($results);
    }
}

if (! function_exists('e')) {
    /**
     * Encode HTML special characters in a string.
     *
     * @param  \Illuminate\Contracts\Support\DeferringDisplayableValue|\Illuminate\Contracts\Support\Htmlable|\BackedEnum|string|int|float|null  $value
     * @param  bool  $doubleEncode
     */
    function e($value, $doubleEncode = true): string
    {
        if ($value instanceof DeferringDisplayableValue) {
            $value = $value->resolveDisplayableValue();
        }

        if ($value instanceof Htmlable) {
            return $value->toHtml() ?? '';
        }

        if ($value instanceof BackedEnum) {
            $value = $value->value;
        }

        return htmlspecialchars($value ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', $doubleEncode);
    }
}

if (! function_exists('env')) {
    /**
     * Gets the value of an environment variable.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return mixed
     */
    function env($key, $default = null)
    {
        return Env::get($key, $default);
    }
}

if (! function_exists('filled')) {
    /**
     * Determine if a value is "filled".
     *
     * @phpstan-assert-if-true !=null|'' $value
     *
     * @phpstan-assert-if-false !=numeric|bool $value
     *
     * @param  mixed  $value
     */
    function filled($value): bool
    {
        return ! blank($value);
    }
}

if (! function_exists('fluent')) {
    /**
     * Create a Fluent object from the given value.
     *
     * @param  iterable|object|null  $value
     */
    function fluent($value = null): Fluent
    {
        return new Fluent($value ?? []);
    }
}

if (! function_exists('literal')) {
    /**
     * Return a new literal or anonymous object using named arguments.
     *
     * @return mixed
     */
    function literal(...$arguments)
    {
        if (count($arguments) === 1 && array_is_list($arguments)) {
            return $arguments[0];
        }

        return (object) $arguments;
    }
}

if (! function_exists('object_get')) {
    /**
     * Get an item from an object using "dot" notation.
     *
     * @template TValue of object
     *
     * @param  TValue  $object
     * @param  string|null  $key
     * @param  mixed  $default
     * @return ($key is empty ? TValue : mixed)
     */
    function object_get($object, $key, $default = null)
    {
        if (is_null($key) || trim($key) === '') {
            return $object;
        }

        foreach (explode('.', $key) as $segment) {
            if (! is_object($object) || ! isset($object->{$segment})) {
                return value($default);
            }

            $object = $object->{$segment};
        }

        return $object;
    }
}

if (! function_exists('laravel_cloud')) {
    /**
     * Determine if the application is running on Laravel Cloud.
     */
    function laravel_cloud(): bool
    {
        return ($_ENV['LARAVEL_CLOUD'] ?? false) === '1' ||
            ($_SERVER['LARAVEL_CLOUD'] ?? false) === '1';
    }
}

if (! function_exists('once')) {
    /**
     * Ensures a callable is only called once, and returns the result on subsequent calls.
     *
     * @template  TReturnType
     *
     * @param  callable(): TReturnType  $callback
     * @return TReturnType
     */
    function once(callable $callback)
    {
        $onceable = Onceable::tryFromTrace(
            debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2),
            $callback,
        );

        return $onceable ? Once::instance()->value($onceable) : call_user_func($callback);
    }
}

if (! function_exists('optional')) {
    /**
     * Provide access to optional objects.
     *
     * @template TValue
     * @template TReturn
     *
     * @param  TValue  $value
     * @param  (callable(TValue): TReturn)|null  $callback
     * @return ($callback is null ? \Illuminate\Support\Optional : ($value is null ? null : TReturn))
     */
    function optional($value = null, ?callable $callback = null)
    {
        if (is_null($callback)) {
            return new Optional($value);
        } elseif (! is_null($value)) {
            return $callback($value);
        }
    }
}

if (! function_exists('preg_replace_array')) {
    /**
     * Replace a given pattern with each value in the array in sequentially.
     *
     * @param  string  $pattern
     * @param  array  $replacements
     * @param  string  $subject
     */
    function preg_replace_array($pattern, array $replacements, $subject): string
    {
        return preg_replace_callback($pattern, function () use (&$replacements) {
            return array_shift($replacements);
        }, $subject);
    }
}

if (! function_exists('retry')) {
    /**
     * Retry an operation a given number of times.
     *
     * @template TValue
     *
     * @param  int|array<int, int>  $times
     * @param  callable(int): TValue  $callback
     * @param  CarbonInterval|int|\Closure(int, \Throwable): CarbonInterval|int  $sleepMilliseconds
     * @param  (callable(\Throwable): bool)|null  $when
     * @return TValue
     *
     * @throws \Throwable
     */
    function retry($times, callable $callback, $sleepMilliseconds = 0, $when = null)
    {
        $attempts = 0;

        $backoff = [];

        if (is_array($times)) {
            $backoff = $times;

            $times = count($times) + 1;
        }

        beginning:
        $attempts++;
        $times--;

        try {
            return $callback($attempts);
        } catch (Throwable $e) {
            if ($times < 1 || ($when && ! $when($e))) {
                throw $e;
            }

            $sleepMilliseconds = $backoff[$attempts - 1] ?? $sleepMilliseconds;

            if ($sleepMilliseconds) {
                $duration = value($sleepMilliseconds, $attempts, $e);

                $duration instanceof CarbonInterval
                    ? Sleep::usleep($duration->totalMicroseconds)
                    : Sleep::usleep($duration * 1000);
            }

            goto beginning;
        }
    }
}

if (! function_exists('str')) {
    /**
     * Get a new stringable object from the given string.
     *
     * @param  string|null  $string
     * @return ($string is null ? object : \Illuminate\Support\Stringable)
     */
    function str($string = null)
    {
        if (func_num_args() === 0) {
            return new class
            {
                public function __call($method, $parameters)
                {
                    return Str::$method(...$parameters);
                }

                public function __toString()
                {
                    return '';
                }
            };
        }

        return new SupportStringable($string);
    }
}

if (! function_exists('tap')) {
    /**
     * Call the given Closure with the given value then return the value.
     *
     * @template TValue
     *
     * @param  TValue  $value
     * @param  (callable(TValue): mixed)|null  $callback
     * @return ($callback is null ? \Illuminate\Support\HigherOrderTapProxy : TValue)
     */
    function tap($value, $callback = null)
    {
        if (is_null($callback)) {
            return new HigherOrderTapProxy($value);
        }

        $callback($value);

        return $value;
    }
}

if (! function_exists('throw_if')) {
    /**
     * Throw the given exception if the given condition is true.
     *
     * @template TValue
     * @template TParams of mixed
     * @template TException of \Throwable
     * @template TExceptionValue of TException|class-string<TException>|string
     *
     * @param  TValue  $condition
     * @param  Closure(TParams): TExceptionValue|TExceptionValue  $exception
     * @param  TParams  ...$parameters
     * @return ($condition is true ? never : ($condition is non-empty-mixed ? never : TValue))
     *
     * @throws TException
     */
    function throw_if($condition, $exception = 'RuntimeException', ...$parameters)
    {
        if ($condition) {
            if ($exception instanceof Closure) {
                $exception = $exception(...$parameters);
            }

            if (is_string($exception) && class_exists($exception)) {
                $exception = new $exception(...$parameters);
            }

            throw is_string($exception) ? new RuntimeException($exception) : $exception;
        }

        return $condition;
    }
}

if (! function_exists('throw_unless')) {
    /**
     * Throw the given exception unless the given condition is true.
     *
     * @template TValue
     * @template TParams of mixed
     * @template TException of \Throwable
     * @template TExceptionValue of TException|class-string<TException>|string
     *
     * @param  TValue  $condition
     * @param  Closure(TParams): TExceptionValue|TExceptionValue  $exception
     * @param  TParams  ...$parameters
     * @return ($condition is false ? never : ($condition is non-empty-mixed ? TValue : never))
     *
     * @throws TException
     */
    function throw_unless($condition, $exception = 'RuntimeException', ...$parameters)
    {
        throw_if(! $condition, $exception, ...$parameters);

        return $condition;
    }
}

if (! function_exists('trait_uses_recursive')) {
    /**
     * Returns all traits used by a trait and its traits.
     *
     * @param  object|string  $trait
     * @return array<string, string>
     */
    function trait_uses_recursive($trait): array
    {
        $traits = class_uses($trait) ?: [];

        foreach ($traits as $trait) {
            $traits += trait_uses_recursive($trait);
        }

        return $traits;
    }
}

if (! function_exists('transform')) {
    /**
     * Transform the given value if it is present.
     *
     * @template TValue
     * @template TReturn
     * @template TDefault
     *
     * @param  TValue  $value
     * @param  callable(TValue): TReturn  $callback
     * @param  TDefault|callable(TValue): TDefault  $default
     * @return ($value is empty ? TDefault : TReturn)
     */
    function transform($value, callable $callback, $default = null)
    {
        if (filled($value)) {
            return $callback($value);
        }

        if (is_callable($default)) {
            return $default($value);
        }

        return $default;
    }
}

if (! function_exists('windows_os')) {
    /**
     * Determine whether the current environment is Windows based.
     */
    function windows_os(): bool
    {
        return PHP_OS_FAMILY === 'Windows';
    }
}

if (! function_exists('with')) {
    /**
     * Return the given value, optionally passed through the given callback.
     *
     * @template TValue
     * @template TReturn
     *
     * @param  TValue  $value
     * @param  (callable(TValue): (TReturn))|null  $callback
     * @return ($callback is null ? TValue : TReturn)
     */
    function with($value, ?callable $callback = null)
    {
        return is_null($callback) ? $value : $callback($value);
    }
}
<?php

namespace Illuminate\Support;

use Illuminate\Support\Traits\Macroable;
use NumberFormatter;
use RuntimeException;

class Number
{
    use Macroable;

    /**
     * The current default locale.
     *
     * @var string
     */
    protected static $locale = 'en';

    /**
     * The current default currency.
     *
     * @var string
     */
    protected static $currency = 'USD';

    /**
     * Format the given number according to the current locale.
     *
     * @param  int|float  $number
     * @param  int|null  $precision
     * @param  int|null  $maxPrecision
     * @param  string|null  $locale
     * @return string|false
     */
    public static function format(int|float $number, ?int $precision = null, ?int $maxPrecision = null, ?string $locale = null)
    {
        static::ensureIntlExtensionIsInstalled();

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::DECIMAL);

        if (! is_null($maxPrecision)) {
            $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $maxPrecision);
        } elseif (! is_null($precision)) {
            $formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, $precision);
        }

        return $formatter->format($number);
    }

    /**
     * Parse the given string according to the specified format type.
     *
     * @param  string  $string
     * @param  int|null  $type
     * @param  string|null  $locale
     * @return int|float|false
     */
    public static function parse(string $string, ?int $type = NumberFormatter::TYPE_DOUBLE, ?string $locale = null): int|float|false
    {
        static::ensureIntlExtensionIsInstalled();

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::DECIMAL);

        return $formatter->parse($string, $type);
    }

    /**
     * Parse a string into an integer according to the specified locale.
     *
     * @param  string  $string
     * @param  string|null  $locale
     * @return int|false
     */
    public static function parseInt(string $string, ?string $locale = null): int|false
    {
        return self::parse($string, NumberFormatter::TYPE_INT32, $locale);
    }

    /**
     * Parse a string into a float according to the specified locale.
     *
     * @param  string  $string
     * @param  string|null  $locale
     * @return float|false
     */
    public static function parseFloat(string $string, ?string $locale = null): float|false
    {
        return self::parse($string, NumberFormatter::TYPE_DOUBLE, $locale);
    }

    /**
     * Spell out the given number in the given locale.
     *
     * @param  int|float  $number
     * @param  string|null  $locale
     * @param  int|null  $after
     * @param  int|null  $until
     * @return string
     */
    public static function spell(int|float $number, ?string $locale = null, ?int $after = null, ?int $until = null)
    {
        static::ensureIntlExtensionIsInstalled();

        if (! is_null($after) && $number <= $after) {
            return static::format($number, locale: $locale);
        }

        if (! is_null($until) && $number >= $until) {
            return static::format($number, locale: $locale);
        }

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::SPELLOUT);

        return $formatter->format($number);
    }

    /**
     * Convert the given number to ordinal form.
     *
     * @param  int|float  $number
     * @param  string|null  $locale
     * @return string
     */
    public static function ordinal(int|float $number, ?string $locale = null)
    {
        static::ensureIntlExtensionIsInstalled();

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::ORDINAL);

        return $formatter->format($number);
    }

    /**
     * Spell out the given number in the given locale in ordinal form.
     *
     * @param  int|float  $number
     * @param  string|null  $locale
     * @return string
     */
    public static function spellOrdinal(int|float $number, ?string $locale = null)
    {
        static::ensureIntlExtensionIsInstalled();

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::SPELLOUT);

        $formatter->setTextAttribute(NumberFormatter::DEFAULT_RULESET, '%spellout-ordinal');

        return $formatter->format($number);
    }

    /**
     * Convert the given number to its percentage equivalent.
     *
     * @param  int|float  $number
     * @param  int  $precision
     * @param  int|null  $maxPrecision
     * @param  string|null  $locale
     * @return string|false
     */
    public static function percentage(int|float $number, int $precision = 0, ?int $maxPrecision = null, ?string $locale = null)
    {
        static::ensureIntlExtensionIsInstalled();

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::PERCENT);

        if (! is_null($maxPrecision)) {
            $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $maxPrecision);
        } else {
            $formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, $precision);
        }

        return $formatter->format($number / 100);
    }

    /**
     * Convert the given number to its currency equivalent.
     *
     * @param  int|float  $number
     * @param  string  $in
     * @param  string|null  $locale
     * @param  int|null  $precision
     * @return string|false
     */
    public static function currency(int|float $number, string $in = '', ?string $locale = null, ?int $precision = null)
    {
        static::ensureIntlExtensionIsInstalled();

        $formatter = new NumberFormatter($locale ?? static::$locale, NumberFormatter::CURRENCY);

        if (! is_null($precision)) {
            $formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, $precision);
        }

        return $formatter->formatCurrency($number, ! empty($in) ? $in : static::$currency);
    }

    /**
     * Convert the given number to its file size equivalent.
     *
     * @param  int|float  $bytes
     * @param  int  $precision
     * @param  int|null  $maxPrecision
     * @return string
     */
    public static function fileSize(int|float $bytes, int $precision = 0, ?int $maxPrecision = null)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

        $unitCount = count($units);

        for ($i = 0; ($bytes / 1024) > 0.9 && ($i < $unitCount - 1); $i++) {
            $bytes /= 1024;
        }

        return sprintf('%s %s', static::format($bytes, $precision, $maxPrecision), $units[$i]);
    }

    /**
     * Convert the number to its human-readable equivalent.
     *
     * @param  int|float  $number
     * @param  int  $precision
     * @param  int|null  $maxPrecision
     * @return string|false
     */
    public static function abbreviate(int|float $number, int $precision = 0, ?int $maxPrecision = null)
    {
        return static::forHumans($number, $precision, $maxPrecision, abbreviate: true);
    }

    /**
     * Convert the number to its human-readable equivalent.
     *
     * @param  int|float  $number
     * @param  int  $precision
     * @param  int|null  $maxPrecision
     * @param  bool  $abbreviate
     * @return string|false
     */
    public static function forHumans(int|float $number, int $precision = 0, ?int $maxPrecision = null, bool $abbreviate = false)
    {
        return static::summarize($number, $precision, $maxPrecision, $abbreviate ? [
            3 => 'K',
            6 => 'M',
            9 => 'B',
            12 => 'T',
            15 => 'Q',
        ] : [
            3 => ' thousand',
            6 => ' million',
            9 => ' billion',
            12 => ' trillion',
            15 => ' quadrillion',
        ]);
    }

    /**
     * Convert the number to its human-readable equivalent.
     *
     * @param  int|float  $number
     * @param  int  $precision
     * @param  int|null  $maxPrecision
     * @param  array<int, string>  $units
     * @return string|false
     */
    protected static function summarize(int|float $number, int $precision = 0, ?int $maxPrecision = null, array $units = [])
    {
        if (empty($units)) {
            $units = [
                3 => 'K',
                6 => 'M',
                9 => 'B',
                12 => 'T',
                15 => 'Q',
            ];
        }

        switch (true) {
            case (float) $number === 0.0:
                return $precision > 0 ? static::format(0, $precision, $maxPrecision) : '0';
            case $number < 0:
                return sprintf('-%s', static::summarize(abs($number), $precision, $maxPrecision, $units));
            case $number >= 1e15:
                return sprintf('%s'.end($units), static::summarize($number / 1e15, $precision, $maxPrecision, $units));
        }

        $numberExponent = floor(log10($number));
        $displayExponent = $numberExponent - ($numberExponent % 3);
        $number /= pow(10, $displayExponent);

        $formatted = static::format($number, $precision, $maxPrecision);

        if (static::parseFloat($formatted) >= 1000 && isset($units[$displayExponent + 3])) {
            $number /= 1000;
            $displayExponent += 3;
            $formatted = static::format($number, $precision, $maxPrecision);
        }

        return trim(sprintf('%s%s', $formatted, $units[$displayExponent] ?? ''));
    }

    /**
     * Clamp the given number between the given minimum and maximum.
     *
     * @param  int|float  $number
     * @param  int|float  $min
     * @param  int|float  $max
     * @return int|float
     */
    public static function clamp(int|float $number, int|float $min, int|float $max)
    {
        return min(max($number, $min), $max);
    }

    /**
     * Split the given number into pairs of min/max values.
     *
     * @param  int|float  $to
     * @param  int|float  $by
     * @param  int|float  $start
     * @param  int|float  $offset
     * @return list<array{int|float, int|float}>
     */
    public static function pairs(int|float $to, int|float $by, int|float $start = 0, int|float $offset = 1)
    {
        $output = [];

        for ($lower = $start; $lower < $to; $lower += $by) {
            $upper = $lower + $by - $offset;

            if ($upper > $to) {
                $upper = $to;
            }

            $output[] = [$lower, $upper];
        }

        return $output;
    }

    /**
     * Remove any trailing zero digits after the decimal point of the given number.
     *
     * @param  int|float  $number
     * @return int|float
     */
    public static function trim(int|float $number)
    {
        return json_decode(json_encode($number));
    }

    /**
     * Execute the given callback using the given locale.
     *
     * @template TReturn
     *
     * @param  string  $locale
     * @param  callable(): TReturn  $callback
     * @return TReturn
     */
    public static function withLocale(string $locale, callable $callback)
    {
        $previousLocale = static::$locale;

        static::useLocale($locale);

        try {
            return $callback();
        } finally {
            static::useLocale($previousLocale);
        }
    }

    /**
     * Execute the given callback using the given currency.
     *
     * @template TReturn
     *
     * @param  string  $currency
     * @param  callable(): TReturn  $callback
     * @return TReturn
     */
    public static function withCurrency(string $currency, callable $callback)
    {
        $previousCurrency = static::$currency;

        static::useCurrency($currency);

        try {
            return $callback();
        } finally {
            static::useCurrency($previousCurrency);
        }
    }

    /**
     * Set the default locale.
     *
     * @param  string  $locale
     * @return void
     */
    public static function useLocale(string $locale)
    {
        static::$locale = $locale;
    }

    /**
     * Set the default currency.
     *
     * @param  string  $currency
     * @return void
     */
    public static function useCurrency(string $currency)
    {
        static::$currency = $currency;
    }

    /**
     * Get the default locale.
     *
     * @return string
     */
    public static function defaultLocale()
    {
        return static::$locale;
    }

    /**
     * Get the default currency.
     *
     * @return string
     */
    public static function defaultCurrency()
    {
        return static::$currency;
    }

    /**
     * Ensure the "intl" PHP extension is installed.
     *
     * @return void
     *
     * @throws \RuntimeException
     */
    protected static function ensureIntlExtensionIsInstalled()
    {
        if (! extension_loaded('intl')) {
            $method = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];

            throw new RuntimeException('The "intl" PHP extension is required to use the ['.$method.'] method.');
        }
    }
}
<?php

namespace Illuminate\Support;

use InvalidArgumentException;

class ConfigurationUrlParser
{
    /**
     * The drivers aliases map.
     *
     * @var array<string, string>
     */
    protected static $driverAliases = [
        'mssql' => 'sqlsrv',
        'mysql2' => 'mysql', // RDS
        'postgres' => 'pgsql',
        'postgresql' => 'pgsql',
        'sqlite3' => 'sqlite',
        'redis' => 'tcp',
        'rediss' => 'tls',
    ];

    /**
     * Parse the database configuration, hydrating options using a database configuration URL if possible.
     *
     * @param  array<string, mixed>|string  $config
     * @return array<string, mixed>
     */
    public function parseConfiguration($config)
    {
        if (is_string($config)) {
            $config = ['url' => $config];
        }

        $url = Arr::pull($config, 'url');

        if (! $url) {
            return $config;
        }

        $rawComponents = $this->parseUrl($url);

        $decodedComponents = $this->parseStringsToNativeTypes(
            array_map(rawurldecode(...), $rawComponents)
        );

        return array_merge(
            $config,
            $this->getPrimaryOptions($decodedComponents),
            $this->getQueryOptions($rawComponents)
        );
    }

    /**
     * Get the primary database connection options.
     *
     * @param  array<string, mixed>  $url
     * @return array<string, mixed>
     */
    protected function getPrimaryOptions($url)
    {
        return array_filter([
            'driver' => $this->getDriver($url),
            'database' => $this->getDatabase($url),
            'host' => $url['host'] ?? null,
            'port' => $url['port'] ?? null,
            'username' => $url['user'] ?? null,
            'password' => $url['pass'] ?? null,
        ], fn ($value) => ! is_null($value));
    }

    /**
     * Get the database driver from the URL.
     *
     * @param  array<string, mixed>  $url
     * @return string|null
     */
    protected function getDriver($url)
    {
        $alias = $url['scheme'] ?? null;

        if (! $alias) {
            return;
        }

        return static::$driverAliases[$alias] ?? $alias;
    }

    /**
     * Get the database name from the URL.
     *
     * @param  array<string, mixed>  $url
     * @return string|null
     */
    protected function getDatabase($url)
    {
        $path = $url['path'] ?? null;

        return $path && $path !== '/' ? substr($path, 1) : null;
    }

    /**
     * Get all of the additional database options from the query string.
     *
     * @param  array<string, mixed>  $url
     * @return array<string, mixed>
     */
    protected function getQueryOptions($url)
    {
        $queryString = $url['query'] ?? null;

        if (! $queryString) {
            return [];
        }

        $query = [];

        parse_str($queryString, $query);

        return $this->parseStringsToNativeTypes($query);
    }

    /**
     * Parse the string URL to an array of components.
     *
     * @param  string  $url
     * @return array<string, mixed>
     *
     * @throws \InvalidArgumentException
     */
    protected function parseUrl($url)
    {
        $url = preg_replace('#^(sqlite3?):///#', '$1://null/', $url);

        $parsedUrl = parse_url($url);

        if ($parsedUrl === false) {
            throw new InvalidArgumentException('The database configuration URL is malformed.');
        }

        return $parsedUrl;
    }

    /**
     * Convert string casted values to their native types.
     *
     * @param  mixed  $value
     * @return mixed
     */
    protected function parseStringsToNativeTypes($value)
    {
        if (is_array($value)) {
            return array_map($this->parseStringsToNativeTypes(...), $value);
        }

        if (! is_string($value)) {
            return $value;
        }

        $parsedValue = json_decode($value, true);

        if (json_last_error() === JSON_ERROR_NONE) {
            return $parsedValue;
        }

        return $value;
    }

    /**
     * Get all of the current drivers' aliases.
     *
     * @return array<string, string>
     */
    public static function getDriverAliases()
    {
        return static::$driverAliases;
    }

    /**
     * Add the given driver alias to the driver aliases array.
     *
     * @param  string  $alias
     * @param  string  $driver
     * @return void
     */
    public static function addDriverAlias($alias, $driver)
    {
        static::$driverAliases[$alias] = $driver;
    }
}
<?php

namespace Illuminate\Support;

class HigherOrderTapProxy
{
    /**
     * The target being tapped.
     *
     * @var mixed
     */
    public $target;

    /**
     * Create a new tap proxy instance.
     *
     * @param  mixed  $target
     */
    public function __construct($target)
    {
        $this->target = $target;
    }

    /**
     * Dynamically pass method calls to the target.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        $this->target->{$method}(...$parameters);

        return $this->target;
    }
}
<?php

namespace Illuminate\Support;

use WeakMap;

class Once
{
    /**
     * The current globally used instance.
     *
     * @var static|null
     */
    protected static ?self $instance = null;

    /**
     * Indicates if the once instance is enabled.
     *
     * @var bool
     */
    protected static bool $enabled = true;

    /**
     * Create a new once instance.
     *
     * @param  \WeakMap<object, array<string, mixed>>  $values
     */
    protected function __construct(protected WeakMap $values)
    {
        //
    }

    /**
     * Create a new once instance.
     *
     * @return static
     */
    public static function instance()
    {
        return static::$instance ??= new static(new WeakMap);
    }

    /**
     * Get the value of the given onceable.
     *
     * @param  Onceable  $onceable
     * @return mixed
     */
    public function value(Onceable $onceable)
    {
        if (! static::$enabled) {
            return call_user_func($onceable->callable);
        }

        $object = $onceable->object ?: $this;

        $hash = $onceable->hash;

        if (! isset($this->values[$object])) {
            $this->values[$object] = [];
        }

        if (array_key_exists($hash, $this->values[$object])) {
            return $this->values[$object][$hash];
        }

        return $this->values[$object][$hash] = call_user_func($onceable->callable);
    }

    /**
     * Re-enable the once instance if it was disabled.
     *
     * @return void
     */
    public static function enable()
    {
        static::$enabled = true;
    }

    /**
     * Disable the once instance.
     *
     * @return void
     */
    public static function disable()
    {
        static::$enabled = false;
    }

    /**
     * Flush the once instance.
     *
     * @return void
     */
    public static function flush()
    {
        static::$instance = null;
    }
}
<?php

namespace Illuminate\Support;

use Illuminate\Contracts\Support\Htmlable;
use Stringable;

class HtmlString implements Htmlable, Stringable
{
    /**
     * The HTML string.
     *
     * @var string
     */
    protected $html;

    /**
     * Create a new HTML string instance.
     *
     * @param  string  $html
     */
    public function __construct($html = '')
    {
        $this->html = $html;
    }

    /**
     * Get the HTML string.
     *
     * @return string
     */
    public function toHtml()
    {
        return $this->html;
    }

    /**
     * Determine if the given HTML string is empty.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return ($this->html ?? '') === '';
    }

    /**
     * Determine if the given HTML string is not empty.
     *
     * @return bool
     */
    public function isNotEmpty()
    {
        return ! $this->isEmpty();
    }

    /**
     * Get the HTML string.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toHtml() ?? '';
    }
}
<?php

namespace Illuminate\Support;

/**
 * ProcessUtils is a bunch of utility methods.
 *
 * This class was originally copied from Symfony 3.
 */
class ProcessUtils
{
    /**
     * Escapes a string to be used as a shell argument.
     *
     * @param  string  $argument
     * @return string
     */
    public static function escapeArgument($argument)
    {
        // Fix for PHP bug #43784 escapeshellarg removes % from given string
        // Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
        // @see https://bugs.php.net/bug.php?id=43784
        // @see https://bugs.php.net/bug.php?id=49446
        if ('\\' === DIRECTORY_SEPARATOR) {
            if ($argument === '') {
                return '""';
            }

            $escapedArgument = '';
            $quote = false;

            foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
                if ($part === '"') {
                    $escapedArgument .= '\\"';
                } elseif (self::isSurroundedBy($part, '%')) {
                    // Avoid environment variable expansion
                    $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
                } else {
                    // escape trailing backslash
                    if (str_ends_with($part, '\\')) {
                        $part .= '\\';
                    }
                    $quote = true;
                    $escapedArgument .= $part;
                }
            }

            if ($quote) {
                $escapedArgument = '"'.$escapedArgument.'"';
            }

            return $escapedArgument;
        }

        return "'".str_replace("'", "'\\''", $argument)."'";
    }

    /**
     * Is the given string surrounded by the given character?
     *
     * @param  string  $arg
     * @param  string  $char
     * @return bool
     */
    protected static function isSurroundedBy($arg, $char)
    {
        return strlen($arg) > 2 && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
    }
}
<?php

namespace Illuminate\Support\Defer;

use ArrayAccess;
use Closure;
use Countable;
use Illuminate\Support\Collection;

class DeferredCallbackCollection implements ArrayAccess, Countable
{
    /**
     * All of the deferred callbacks.
     *
     * @var array
     */
    protected array $callbacks = [];

    /**
     * Get the first callback in the collection.
     *
     * @return callable
     */
    public function first()
    {
        return array_values($this->callbacks)[0];
    }

    /**
     * Invoke the deferred callbacks.
     *
     * @return void
     */
    public function invoke(): void
    {
        $this->invokeWhen(fn () => true);
    }

    /**
     * Invoke the deferred callbacks if the given truth test evaluates to true.
     *
     * @param  \Closure|null  $when
     * @return void
     */
    public function invokeWhen(?Closure $when = null): void
    {
        $when ??= fn () => true;

        $this->forgetDuplicates();

        foreach ($this->callbacks as $index => $callback) {
            if ($when($callback)) {
                rescue($callback);
            }

            unset($this->callbacks[$index]);
        }
    }

    /**
     * Remove any deferred callbacks with the given name.
     *
     * @param  string  $name
     * @return void
     */
    public function forget(string $name): void
    {
        $this->callbacks = (new Collection($this->callbacks))
            ->reject(fn ($callback) => $callback->name === $name)
            ->values()
            ->all();
    }

    /**
     * Remove any duplicate callbacks.
     *
     * @return $this
     */
    protected function forgetDuplicates(): static
    {
        $this->callbacks = (new Collection($this->callbacks))
            ->reverse()
            ->unique(fn ($c) => $c->name)
            ->reverse()
            ->values()
            ->all();

        return $this;
    }

    /**
     * Determine if the collection has a callback with the given key.
     *
     * @param  mixed  $offset
     * @return bool
     */
    public function offsetExists(mixed $offset): bool
    {
        $this->forgetDuplicates();

        return isset($this->callbacks[$offset]);
    }

    /**
     * Get the callback with the given key.
     *
     * @param  mixed  $offset
     * @return mixed
     */
    public function offsetGet(mixed $offset): mixed
    {
        $this->forgetDuplicates();

        return $this->callbacks[$offset];
    }

    /**
     * Set the callback with the given key.
     *
     * @param  mixed  $offset
     * @param  mixed  $value
     * @return void
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        if (is_null($offset)) {
            $this->callbacks[] = $value;
        } else {
            $this->callbacks[$offset] = $value;
        }
    }

    /**
     * Remove the callback with the given key from the collection.
     *
     * @param  mixed  $offset
     * @return void
     */
    public function offsetUnset(mixed $offset): void
    {
        $this->forgetDuplicates();

        unset($this->callbacks[$offset]);
    }

    /**
     * Determine how many callbacks are in the collection.
     *
     * @return int
     */
    public function count(): int
    {
        $this->forgetDuplicates();

        return count($this->callbacks);
    }
}
<?php

namespace Illuminate\Support\Defer;

use Illuminate\Support\Str;

class DeferredCallback
{
    /**
     * Create a new deferred callback instance.
     *
     * @param  callable  $callback
     */
    public function __construct(public $callback, public ?string $name = null, public bool $always = false)
    {
        $this->name = $name ?? (string) Str::uuid();
    }

    /**
     * Specify the name of the deferred callback so it can be cancelled later.
     *
     * @param  string  $name
     * @return $this
     */
    public function name(string $name): static
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Indicate that the deferred callback should run even on unsuccessful requests and jobs.
     *
     * @param  bool  $always
     * @return $this
     */
    public function always(bool $always = true): static
    {
        $this->always = $always;

        return $this;
    }

    /**
     * Invoke the deferred callback.
     *
     * @return void
     */
    public function __invoke(): void
    {
        call_user_func($this->callback);
    }
}
<?php

namespace Illuminate\Support\Exceptions;

use RuntimeException;

class MathException extends RuntimeException
{
    //
}
<?php

namespace Illuminate\Support;

use Closure;
use Illuminate\Support\Traits\Macroable;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
use League\CommonMark\Extension\InlinesOnly\InlinesOnlyExtension;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use League\CommonMark\MarkdownConverter;
use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
use Ramsey\Uuid\Generator\CombGenerator;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidFactory;
use Symfony\Component\Uid\Ulid;
use Throwable;
use Traversable;
use voku\helper\ASCII;

class Str
{
    use Macroable;

    /**
     * The list of characters that are considered "invisible" in strings.
     *
     * @var string
     */
    const INVISIBLE_CHARACTERS = '\x{0009}\x{0020}\x{00A0}\x{00AD}\x{034F}\x{061C}\x{115F}\x{1160}\x{17B4}\x{17B5}\x{180E}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005}\x{2006}\x{2007}\x{2008}\x{2009}\x{200A}\x{200B}\x{200C}\x{200D}\x{200E}\x{200F}\x{202F}\x{205F}\x{2060}\x{2061}\x{2062}\x{2063}\x{2064}\x{2065}\x{206A}\x{206B}\x{206C}\x{206D}\x{206E}\x{206F}\x{3000}\x{2800}\x{3164}\x{FEFF}\x{FFA0}\x{1D159}\x{1D173}\x{1D174}\x{1D175}\x{1D176}\x{1D177}\x{1D178}\x{1D179}\x{1D17A}\x{E0020}';

    /**
     * The cache of snake-cased words.
     *
     * @var array<string, string>
     */
    protected static $snakeCache = [];

    /**
     * The cache of camel-cased words.
     *
     * @var array<string, string>
     */
    protected static $camelCache = [];

    /**
     * The cache of studly-cased words.
     *
     * @var array<string, string>
     */
    protected static $studlyCache = [];

    /**
     * The callback that should be used to generate UUIDs.
     *
     * @var (callable(): \Ramsey\Uuid\UuidInterface)|null
     */
    protected static $uuidFactory;

    /**
     * The callback that should be used to generate ULIDs.
     *
     * @var (callable(): \Symfony\Component\Uid\Ulid)|null
     */
    protected static $ulidFactory;

    /**
     * The callback that should be used to generate random strings.
     *
     * @var (callable(int): string)|null
     */
    protected static $randomStringFactory;

    /**
     * Get a new stringable object from the given string.
     *
     * @param  string  $string
     * @return \Illuminate\Support\Stringable
     */
    public static function of($string)
    {
        return new Stringable($string);
    }

    /**
     * Return the remainder of a string after the first occurrence of a given value.
     *
     * @param  string  $subject
     * @param  string  $search
     * @return string
     */
    public static function after($subject, $search)
    {
        return $search === '' ? $subject : array_reverse(explode($search, $subject, 2))[0];
    }

    /**
     * Return the remainder of a string after the last occurrence of a given value.
     *
     * @param  string  $subject
     * @param  string  $search
     * @return string
     */
    public static function afterLast($subject, $search)
    {
        if ($search === '') {
            return $subject;
        }

        $position = mb_strrpos($subject, $search);

        if ($position === false) {
            return $subject;
        }

        return static::substr($subject, $position + static::length($search));
    }

    /**
     * Transliterate a UTF-8 value to ASCII.
     *
     * @param  string  $value
     * @param  string  $language
     * @return string
     */
    public static function ascii($value, $language = 'en')
    {
        return ASCII::to_ascii((string) $value, $language, replace_single_chars_only: false);
    }

    /**
     * Transliterate a string to its closest ASCII representation.
     *
     * @param  string  $string
     * @param  string|null  $unknown
     * @param  bool|null  $strict
     * @return string
     */
    public static function transliterate($string, $unknown = '?', $strict = false)
    {
        return ASCII::to_transliterate((string) $string, $unknown, $strict);
    }

    /**
     * Get the portion of a string before the first occurrence of a given value.
     *
     * @param  string  $subject
     * @param  string  $search
     * @return string
     */
    public static function before($subject, $search)
    {
        if ($search === '') {
            return $subject;
        }

        $result = strstr($subject, (string) $search, true);

        return $result === false ? $subject : $result;
    }

    /**
     * Get the portion of a string before the last occurrence of a given value.
     *
     * @param  string  $subject
     * @param  string  $search
     * @return string
     */
    public static function beforeLast($subject, $search)
    {
        if ($search === '') {
            return $subject;
        }

        $pos = mb_strrpos($subject, $search);

        if ($pos === false) {
            return $subject;
        }

        return static::substr($subject, 0, $pos);
    }

    /**
     * Get the portion of a string between two given values.
     *
     * @param  string  $subject
     * @param  string  $from
     * @param  string  $to
     * @return string
     */
    public static function between($subject, $from, $to)
    {
        if ($from === '' || $to === '') {
            return $subject;
        }

        return static::beforeLast(static::after($subject, $from), $to);
    }

    /**
     * Get the smallest possible portion of a string between two given values.
     *
     * @param  string  $subject
     * @param  string  $from
     * @param  string  $to
     * @return string
     */
    public static function betweenFirst($subject, $from, $to)
    {
        if ($from === '' || $to === '') {
            return $subject;
        }

        return static::before(static::after($subject, $from), $to);
    }

    /**
     * Convert a value to camel case.
     *
     * @param  string  $value
     * @return ($value is '' ? '' : string)
     */
    public static function camel($value)
    {
        return static::$camelCache[$value] ?? static::$camelCache[$value] = lcfirst(static::studly($value));
    }

    /**
     * Get the character at the specified index.
     *
     * @param  string  $subject
     * @param  int  $index
     * @return string|false
     */
    public static function charAt($subject, $index)
    {
        $length = mb_strlen($subject);

        if ($index < 0 ? $index < -$length : $index > $length - 1) {
            return false;
        }

        return mb_substr($subject, $index, 1);
    }

    /**
     * Remove the given string(s) if it exists at the start of the haystack.
     *
     * @param  string  $subject
     * @param  string|string[]  $needle
     * @return string
     */
    public static function chopStart($subject, $needle)
    {
        foreach ((array) $needle as $n) {
            if ($n !== '' && str_starts_with($subject, $n)) {
                return mb_substr($subject, mb_strlen($n));
            }
        }

        return $subject;
    }

    /**
     * Remove the given string(s) if it exists at the end of the haystack.
     *
     * @param  string  $subject
     * @param  string|string[]  $needle
     * @return string
     */
    public static function chopEnd($subject, $needle)
    {
        foreach ((array) $needle as $n) {
            if ($n !== '' && str_ends_with($subject, $n)) {
                return mb_substr($subject, 0, -mb_strlen($n));
            }
        }

        return $subject;
    }

    /**
     * Determine if a given string contains a given substring.
     *
     * @param  string  $haystack
     * @param  string|iterable<string>  $needles
     * @param  bool  $ignoreCase
     * @return ($needles is array{} ? false : ($haystack is non-empty-string ? bool : false))
     */
    public static function contains($haystack, $needles, $ignoreCase = false)
    {
        if (is_null($haystack)) {
            return false;
        }

        if ($ignoreCase) {
            $haystack = mb_strtolower($haystack);
        }

        if (! is_iterable($needles)) {
            $needles = (array) $needles;
        }

        foreach ($needles as $needle) {
            if ($ignoreCase) {
                $needle = mb_strtolower($needle);
            }

            if ($needle !== '' && str_contains($haystack, $needle)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if a given string contains all array values.
     *
     * @param  string  $haystack
     * @param  iterable<string>  $needles
     * @param  bool  $ignoreCase
     * @return ($needles is array{} ? false : ($haystack is non-empty-string ? bool : false))
     */
    public static function containsAll($haystack, $needles, $ignoreCase = false)
    {
        foreach ($needles as $needle) {
            if (! static::contains($haystack, $needle, $ignoreCase)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determine if a given string doesn't contain a given substring.
     *
     * @param  string  $haystack
     * @param  string|iterable<string>  $needles
     * @param  bool  $ignoreCase
     * @return ($needles is array{} ? true : ($haystack is non-empty-string ? bool : true))
     */
    public static function doesntContain($haystack, $needles, $ignoreCase = false)
    {
        return ! static::contains($haystack, $needles, $ignoreCase);
    }

    /**
     * Convert the case of a string.
     *
     * @param  string  $string
     * @param  MB_CASE_UPPER|MB_CASE_LOWER|MB_CASE_TITLE|MB_CASE_FOLD|MB_CASE_UPPER_SIMPLE|MB_CASE_LOWER_SIMPLE|MB_CASE_TITLE_SIMPLE|MB_CASE_FOLD_SIMPLE  $mode
     * @param  string|null  $encoding
     * @return ($string is '' ? '' : string)
     */
    public static function convertCase(string $string, int $mode = MB_CASE_FOLD, ?string $encoding = 'UTF-8')
    {
        return mb_convert_case($string, $mode, $encoding);
    }

    /**
     * Replace consecutive instances of a given character with a single character in the given string.
     *
     * @param  string  $string
     * @param  array<string>|string  $characters
     * @return ($string is '' ? '' : string)
     */
    public static function deduplicate(string $string, array|string $characters = ' ')
    {
        if (is_string($characters)) {
            return preg_replace('/'.preg_quote($characters, '/').'+/u', $characters, $string);
        }

        return array_reduce(
            $characters,
            fn ($carry, $character) => preg_replace('/'.preg_quote($character, '/').'+/u', $character, $carry),
            $string
        );
    }

    /**
     * Determine if a given string ends with a given substring.
     *
     * @param  string  $haystack
     * @param  string|iterable<string>  $needles
     * @return ($needles is array{} ? false : ($haystack is non-empty-string ? bool : false))
     */
    public static function endsWith($haystack, $needles)
    {
        if (is_null($haystack)) {
            return false;
        }

        if (! is_iterable($needles)) {
            $needles = (array) $needles;
        }

        foreach ($needles as $needle) {
            if ((string) $needle !== '' && str_ends_with($haystack, $needle)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if a given string doesn't end with a given substring.
     *
     * @param  string  $haystack
     * @param  string|iterable<string>  $needles
     * @return ($needles is array{} ? true : ($haystack is non-empty-string ? bool : true))
     */
    public static function doesntEndWith($haystack, $needles)
    {
        return ! static::endsWith($haystack, $needles);
    }

    /**
     * Extracts an excerpt from text that matches the first instance of a phrase.
     *
     * @param  string  $text
     * @param  string  $phrase
     * @param  array{radius?: int|float, omission?: string}  $options
     * @return string|null
     */
    public static function excerpt($text, $phrase = '', $options = [])
    {
        $radius = $options['radius'] ?? 100;
        $omission = $options['omission'] ?? '...';

        preg_match('/^(.*?)('.preg_quote((string) $phrase, '/').')(.*)$/iu', (string) $text, $matches);

        if (empty($matches)) {
            return null;
        }

        $start = ltrim($matches[1]);

        $start = Str::of(mb_substr($start, max(mb_strlen($start, 'UTF-8') - $radius, 0), $radius, 'UTF-8'))->ltrim()->unless(
            fn ($startWithRadius) => $startWithRadius->exactly($start),
            fn ($startWithRadius) => $startWithRadius->prepend($omission),
        );

        $end = rtrim($matches[3]);

        $end = Str::of(mb_substr($end, 0, $radius, 'UTF-8'))->rtrim()->unless(
            fn ($endWithRadius) => $endWithRadius->exactly($end),
            fn ($endWithRadius) => $endWithRadius->append($omission),
        );

        return $start->append($matches[2], $end)->toString();
    }

    /**
     * Cap a string with a single instance of a given value.
     *
     * @param  string  $value
     * @param  string  $cap
     * @return ($value is '' ? ($cap is '' ? '' : non-empty-string) : non-empty-string)
     */
    public static function finish($value, $cap)
    {
        $quoted = preg_quote($cap, '/');

        return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap;
    }

    /**
     * Wrap the string with the given strings.
     *
     * @param  string  $value
     * @param  string  $before
     * @param  string|null  $after
     * @return ($value is '' ? ($before is '' ? ($after is '' ? '' : ($after is null ? '' : non-empty-string)) : non-empty-string) : non-empty-string)
     */
    public static function wrap($value, $before, $after = null)
    {
        return $before.$value.($after ?? $before);
    }

    /**
     * Unwrap the string with the given strings.
     *
     * @param  string  $value
     * @param  string  $before
     * @param  string|null  $after
     * @return string
     */
    public static function unwrap($value, $before, $after = null)
    {
        if (static::startsWith($value, $before)) {
            $value = static::substr($value, static::length($before));
        }

        if (static::endsWith($value, $after ??= $before)) {
            $value = static::substr($value, 0, -static::length($after));
        }

        return $value;
    }

    /**
     * Determine if a given string matches a given pattern.
     *
     * @param  string|iterable<string>  $pattern
     * @param  string  $value
     * @param  bool  $ignoreCase
     * @return bool
     */
    public static function is($pattern, $value, $ignoreCase = false)
    {
        $value = (string) $value;

        if (! is_iterable($pattern)) {
            $pattern = [$pattern];
        }

        foreach ($pattern as $pattern) {
            $pattern = (string) $pattern;

            // If the given value is an exact match we can of course return true right
            // from the beginning. Otherwise, we will translate asterisks and do an
            // actual pattern match against the two strings to see if they match.
            if ($pattern === '*' || $pattern === $value) {
                return true;
            }

            if ($ignoreCase && mb_strtolower($pattern) === mb_strtolower($value)) {
                return true;
            }

            $pattern = preg_quote($pattern, '#');

            // Asterisks are translated into zero-or-more regular expression wildcards
            // to make it convenient to check if the strings starts with the given
            // pattern such as "library/*", making any string check convenient.
            $pattern = str_replace('\*', '.*', $pattern);

            if (preg_match('#^'.$pattern.'\z#'.($ignoreCase ? 'isu' : 'su'), $value) === 1) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if a given string is 7 bit ASCII.
     *
     * @param  string  $value
     * @return bool
     */
    public static function isAscii($value)
    {
        return ASCII::is_ascii((string) $value);
    }

    /**
     * Determine if a given value is valid JSON.
     *
     * @param  mixed  $value
     * @return bool
     *
     * @phpstan-assert-if-true =non-empty-string $value
     */
    public static function isJson($value)
    {
        if (! is_string($value)) {
            return false;
        }

        return json_validate($value, 512);
    }

    /**
     * Determine if a given value is a valid URL.
     *
     * @param  mixed  $value
     * @param  string[]  $protocols
     * @return bool
     *
     * @phpstan-assert-if-true =non-empty-string $value
     */
    public static function isUrl($value, array $protocols = [])
    {
        if (! is_string($value)) {
            return false;
        }

        $protocolList = empty($protocols)
            ? 'aaa|aaas|about|acap|acct|acd|acr|adiumxtra|adt|afp|afs|aim|amss|android|appdata|apt|ark|attachment|aw|barion|beshare|bitcoin|bitcoincash|blob|bolo|browserext|calculator|callto|cap|cast|casts|chrome|chrome-extension|cid|coap|coap\+tcp|coap\+ws|coaps|coaps\+tcp|coaps\+ws|com-eventbrite-attendee|content|conti|crid|cvs|dab|data|dav|diaspora|dict|did|dis|dlna-playcontainer|dlna-playsingle|dns|dntp|dpp|drm|drop|dtn|dvb|ed2k|elsi|example|facetime|fax|feed|feedready|file|filesystem|finger|first-run-pen-experience|fish|fm|ftp|fuchsia-pkg|geo|gg|git|gizmoproject|go|gopher|graph|gtalk|h323|ham|hcap|hcp|http|https|hxxp|hxxps|hydrazone|iax|icap|icon|im|imap|info|iotdisco|ipn|ipp|ipps|irc|irc6|ircs|iris|iris\.beep|iris\.lwz|iris\.xpc|iris\.xpcs|isostore|itms|jabber|jar|jms|keyparc|lastfm|ldap|ldaps|leaptofrogans|lorawan|lvlt|magnet|mailserver|mailto|maps|market|message|mid|mms|modem|mongodb|moz|ms-access|ms-browser-extension|ms-calculator|ms-drive-to|ms-enrollment|ms-excel|ms-eyecontrolspeech|ms-gamebarservices|ms-gamingoverlay|ms-getoffice|ms-help|ms-infopath|ms-inputapp|ms-lockscreencomponent-config|ms-media-stream-id|ms-mixedrealitycapture|ms-mobileplans|ms-officeapp|ms-people|ms-project|ms-powerpoint|ms-publisher|ms-restoretabcompanion|ms-screenclip|ms-screensketch|ms-search|ms-search-repair|ms-secondary-screen-controller|ms-secondary-screen-setup|ms-settings|ms-settings-airplanemode|ms-settings-bluetooth|ms-settings-camera|ms-settings-cellular|ms-settings-cloudstorage|ms-settings-connectabledevices|ms-settings-displays-topology|ms-settings-emailandaccounts|ms-settings-language|ms-settings-location|ms-settings-lock|ms-settings-nfctransactions|ms-settings-notifications|ms-settings-power|ms-settings-privacy|ms-settings-proximity|ms-settings-screenrotation|ms-settings-wifi|ms-settings-workplace|ms-spd|ms-sttoverlay|ms-transit-to|ms-useractivityset|ms-virtualtouchpad|ms-visio|ms-walk-to|ms-whiteboard|ms-whiteboard-cmd|ms-word|msnim|msrp|msrps|mss|mtqp|mumble|mupdate|mvn|news|nfs|ni|nih|nntp|notes|ocf|oid|onenote|onenote-cmd|opaquelocktoken|openpgp4fpr|pack|palm|paparazzi|payto|pkcs11|platform|pop|pres|prospero|proxy|pwid|psyc|pttp|qb|query|redis|rediss|reload|res|resource|rmi|rsync|rtmfp|rtmp|rtsp|rtsps|rtspu|s3|secondlife|service|session|sftp|sgn|shttp|sieve|simpleledger|sip|sips|skype|smb|sms|smtp|snews|snmp|soap\.beep|soap\.beeps|soldat|spiffe|spotify|ssh|steam|stun|stuns|submit|svn|tag|teamspeak|tel|teliaeid|telnet|tftp|tg|things|thismessage|tip|tn3270|tool|ts3server|turn|turns|tv|udp|unreal|urn|ut2004|v-event|vemmi|ventrilo|videotex|vnc|view-source|wais|webcal|wpid|ws|wss|wtai|wyciwyg|xcon|xcon-userid|xfire|xmlrpc\.beep|xmlrpc\.beeps|xmpp|xri|ymsgr|z39\.50|z39\.50r|z39\.50s'
            : implode('|', $protocols);

        /*
         * This pattern is derived from Symfony\Component\Validator\Constraints\UrlValidator (5.0.7).
         *
         * (c) Fabien Potencier <fabien@symfony.com> http://symfony.com
         */
        $pattern = '~^
            (LARAVEL_PROTOCOLS)://                                 # protocol
            (((?:[\_\.\pL\pN-]|%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%[0-9A-Fa-f]{2})+)@)?  # basic auth
            (
                (?:
                    (?:
                        (?:[\pL\pN\pS\pM\-\_]++\.)+
                        (?:
                            (?:xn--[a-z0-9-]++)     # punycode in tld
                            |
                            (?:[\pL\pN\pM]++)       # no punycode in tld
                        )
                    )                               # a multi-level domain name
                        |
                    [a-z0-9\-\_]++                  # a single-level domain name
                )\.?
                    |                               # or
                \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}  # an IP address
                    |                               # or
                \[
                    (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
                \]  # an IPv6 address
            )
            (:[0-9]+)?                              # a port (optional)
            (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%[0-9A-Fa-f]{2})* )*          # a path
            (?:\? (?:[\pL\pN\-._\~!$&\'\[\]()*+,;=:@/?]|%[0-9A-Fa-f]{2})* )?   # a query (optional)
            (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%[0-9A-Fa-f]{2})* )?       # a fragment (optional)
        $~ixu';

        return preg_match(str_replace('LARAVEL_PROTOCOLS', $protocolList, $pattern), $value) > 0;
    }

    /**
     * Determine if a given value is a valid UUID.
     *
     * @param  mixed  $value
     * @param  int<0, 8>|'nil'|'max'|null  $version
     * @return bool
     *
     * @phpstan-assert-if-true =non-empty-string $value
     */
    public static function isUuid($value, $version = null)
    {
        if (! is_string($value)) {
            return false;
        }

        if ($version === null) {
            return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0;
        }

        $factory = new UuidFactory;

        try {
            $factoryUuid = $factory->fromString($value);
        } catch (InvalidUuidStringException) {
            return false;
        }

        $fields = $factoryUuid->getFields();

        if (! ($fields instanceof FieldsInterface)) {
            return false;
        }

        if ($version === 0 || $version === 'nil') {
            return $fields->isNil();
        }

        if ($version === 'max') {
            return $fields->isMax();
        }

        return $fields->getVersion() === $version;
    }

    /**
     * Determine if a given value is a valid ULID.
     *
     * @param  mixed  $value
     * @return bool
     *
     * @phpstan-assert-if-true =non-empty-string $value
     */
    public static function isUlid($value)
    {
        if (! is_string($value)) {
            return false;
        }

        return Ulid::isValid($value);
    }

    /**
     * Convert a string to kebab case.
     *
     * @param  string  $value
     * @return ($value is '' ? '' : string)
     */
    public static function kebab($value)
    {
        return static::snake($value, '-');
    }

    /**
     * Return the length of the given string.
     *
     * @param  string  $value
     * @param  string|null  $encoding
     * @return non-negative-int
     */
    public static function length($value, $encoding = null)
    {
        return mb_strlen($value, $encoding);
    }

    /**
     * Limit the number of characters in a string.
     *
     * @param  string  $value
     * @param  int  $limit
     * @param  string  $end
     * @param  bool  $preserveWords
     * @return string
     */
    public static function limit($value, $limit = 100, $end = '...', $preserveWords = false)
    {
        if (mb_strwidth($value, 'UTF-8') <= $limit) {
            return $value;
        }

        if (! $preserveWords) {
            return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end;
        }

        $value = trim(preg_replace('/[\n\r]+/', ' ', strip_tags($value)));

        $trimmed = rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8'));

        if (mb_substr($value, $limit, 1, 'UTF-8') === ' ') {
            return $trimmed.$end;
        }

        return preg_replace("/(.*)\s.*/", '$1', $trimmed).$end;
    }

    /**
     * Convert the given string to lower-case.
     *
     * @param  string  $value
     * @return ($value is '' ? '' : non-empty-string&lowercase-string)
     */
    public static function lower($value)
    {
        return mb_strtolower($value, 'UTF-8');
    }

    /**
     * Limit the number of words in a string.
     *
     * @param  string  $value
     * @param  int  $words
     * @param  string  $end
     * @return string
     */
    public static function words($value, $words = 100, $end = '...')
    {
        preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches);

        if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) {
            return $value;
        }

        return rtrim($matches[0]).$end;
    }

    /**
     * Converts GitHub flavored Markdown into HTML.
     *
     * @param  string  $string
     * @param  array  $options
     * @param  \League\CommonMark\Extension\ExtensionInterface[]  $extensions
     * @return ($string is '' ? '' : string)
     */
    public static function markdown($string, array $options = [], array $extensions = [])
    {
        $string = (string) $string;

        $converter = new GithubFlavoredMarkdownConverter($options);

        $environment = $converter->getEnvironment();

        foreach ($extensions as $extension) {
            $environment->addExtension($extension);
        }

        return (string) $converter->convert($string);
    }

    /**
     * Converts inline Markdown into HTML.
     *
     * @param  string  $string
     * @param  array  $options
     * @param  \League\CommonMark\Extension\ExtensionInterface[]  $extensions
     * @return ($string is '' ? '' : string)
     */
    public static function inlineMarkdown($string, array $options = [], array $extensions = [])
    {
        $string = (string) $string;

        $environment = new Environment($options);

        $environment->addExtension(new GithubFlavoredMarkdownExtension());
        $environment->addExtension(new InlinesOnlyExtension());

        foreach ($extensions as $extension) {
            $environment->addExtension($extension);
        }

        $converter = new MarkdownConverter($environment);

        return (string) $converter->convert($string);
    }

    /**
     * Masks a portion of a string with a repeated character.
     *
     * @param  string  $string
     * @param  string  $character
     * @param  int  $index
     * @param  int|null  $length
     * @param  string  $encoding
     * @return string
     */
    public static function mask($string, $character, $index, $length = null, $encoding = 'UTF-8')
    {
        if ($character === '') {
            return $string;
        }

        $segment = mb_substr($string, $index, $length, $encoding);

        if ($segment === '') {
            return $string;
        }

        $strlen = mb_strlen($string, $encoding);
        $startIndex = $index;

        if ($index < 0) {
            $startIndex = $index < -$strlen ? 0 : $strlen + $index;
        }

        $start = mb_substr($string, 0, $startIndex, $encoding);
        $segmentLen = mb_strlen($segment, $encoding);
        $end = mb_substr($string, $startIndex + $segmentLen);

        return $start.str_repeat(mb_substr($character, 0, 1, $encoding), $segmentLen).$end;
    }

    /**
     * Get the string matching the given pattern.
     *
     * @param  string  $pattern
     * @param  string  $subject
     * @return string
     */
    public static function match($pattern, $subject)
    {
        preg_match($pattern, $subject, $matches);

        if (! $matches) {
            return '';
        }

        return $matches[1] ?? $matches[0];
    }

    /**
     * Determine if a given string matches a given pattern.
     *
     * @param  string|iterable<string>  $pattern
     * @param  string  $value
     * @return ($pattern is array{} ? false : bool)
     */
    public static function isMatch($pattern, $value)
    {
        $value = (string) $value;

        if (! is_iterable($pattern)) {
            $pattern = [$pattern];
        }

        foreach ($pattern as $pattern) {
            $pattern = (string) $pattern;

            if (preg_match($pattern, $value) === 1) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get the string matching the given pattern.
     *
     * @param  string  $pattern
     * @param  string  $subject
     * @return \Illuminate\Support\Collection
     */
    public static function matchAll($pattern, $subject)
    {
        preg_match_all($pattern, $subject, $matches);

        if (empty($matches[0])) {
            return new Collection;
        }

        return new Collection($matches[1] ?? $matches[0]);
    }

    /**
     * Remove all non-numeric characters from a string.
     *
     * @param  string  $value
     * @return string
     */
    public static function numbers($value)
    {
        return preg_replace('/[^0-9]/', '', $value);
    }

    /**
     * Pad both sides of a string with another.
     *
     * @param  string  $value
     * @param  int  $length
     * @param  string  $pad
     * @return string
     */
    public static function padBoth($value, $length, $pad = ' ')
    {
        return mb_str_pad($value, $length, $pad, STR_PAD_BOTH);
    }

    /**
     * Pad the left side of a string with another.
     *
     * @param  string  $value
     * @param  int  $length
     * @param  string  $pad
     * @return string
     */
    public static function padLeft($value, $length, $pad = ' ')
    {
        return mb_str_pad($value, $length, $pad, STR_PAD_LEFT);
    }

    /**
     * Pad the right side of a string with another.
     *
     * @param  string  $value
     * @param  int  $length
     * @param  string  $pad
     * @return string
     */
    public static function padRight($value, $length, $pad = ' ')
    {
        return mb_str_pad($value, $length, $pad, STR_PAD_RIGHT);
    }

    /**
     * Parse a Class[@]method style callback into class and method.
     *
     * @param  string  $callback
     * @param  string|null  $default
     * @return array<int, string|null>
     */
    public static function parseCallback($callback, $default = null)
    {
        if (static::contains($callback, "@anonymous\0")) {
            if (static::substrCount($callback, '@') > 1) {
                return [
                    static::beforeLast($callback, '@'),
                    static::afterLast($callback, '@'),
                ];
            }

            return [$callback, $default];
        }

        return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
    }

    /**
     * Get the plural form of an English word.
     *
     * @param  string  $value
     * @param  int|array|\Countable  $count
     * @param  bool  $prependCount
     * @return string
     */
    public static function plural($value, $count = 2, $prependCount = false)
    {
        if (is_countable($count)) {
            $count = count($count);
        }

        return ($prependCount ? Number::format($count).' ' : '').Pluralizer::plural($value, $count);
    }

    /**
     * Pluralize the last word of an English, studly caps case string.
     *
     * @param  string  $value
     * @param  int|array|\Countable  $count
     * @return string
     */
    public static function pluralStudly($value, $count = 2)
    {
        $parts = preg_split('/(.)(?=[A-Z])/u', $value, -1, PREG_SPLIT_DELIM_CAPTURE);

        $lastWord = array_pop($parts);

        return implode('', $parts).self::plural($lastWord, $count);
    }

    /**
     * Pluralize the last word of an English, Pascal caps case string.
     *
     * @param  string  $value
     * @param  int|array|\Countable  $count
     * @return string
     */
    public static function pluralPascal($value, $count = 2)
    {
        return static::pluralStudly($value, $count);
    }

    /**
     * Generate a random, secure password.
     *
     * @param  int  $length
     * @param  bool  $letters
     * @param  bool  $numbers
     * @param  bool  $symbols
     * @param  bool  $spaces
     * @return ($letters is false ? ($numbers is true ? ($symbols is false ? ($spaces is false ? numeric-string : string) : string) : string) : string)
     */
    public static function password($length = 32, $letters = true, $numbers = true, $symbols = true, $spaces = false)
    {
        $password = new Collection();

        $options = (new Collection([
            'letters' => $letters === true ? [
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
                'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
                'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            ] : null,
            'numbers' => $numbers === true ? [
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            ] : null,
            'symbols' => $symbols === true ? [
                '~', '!', '#', '$', '%', '^', '&', '*', '(', ')', '-',
                '_', '.', ',', '<', '>', '?', '/', '\\', '{', '}', '[',
                ']', '|', ':', ';',
            ] : null,
            'spaces' => $spaces === true ? [' '] : null,
        ]))
            ->filter()
            ->each(fn ($c) => $password->push($c[random_int(0, count($c) - 1)]))
            ->flatten();

        $length = $length - $password->count();

        return $password->merge($options->pipe(
            fn ($c) => Collection::times($length, fn () => $c[random_int(0, $c->count() - 1)])
        ))->shuffle()->implode('');
    }

    /**
     * Find the multi-byte safe position of the first occurrence of a given substring in a string.
     *
     * @param  string  $haystack
     * @param  string  $needle
     * @param  int  $offset
     * @param  string|null  $encoding
     * @return ($haystack is '' ? false : ($needle is '' ? false : int|false))
     */
    public static function position($haystack, $needle, $offset = 0, $encoding = null)
    {
        return mb_strpos($haystack, (string) $needle, $offset, $encoding);
    }

    /**
     * Generate a more truly "random" alpha-numeric string.
     *
     * @param  int  $length
     * @return string
     */
    public static function random($length = 16)
    {
        return (static::$randomStringFactory ?? function ($length) {
            $string = '';

            while (($len = strlen($string)) < $length) {
                $size = $length - $len;

                $bytesSize = (int) ceil($size / 3) * 3;

                $bytes = random_bytes($bytesSize);

                $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
            }

            return $string;
        })($length);
    }

    /**
     * Set the callable that will be used to generate random strings.
     *
     * @param  (callable(int): string)|null  $factory
     * @return void
     */
    public static function createRandomStringsUsing(?callable $factory = null)
    {
        static::$randomStringFactory = $factory;
    }

    /**
     * Set the sequence that will be used to generate random strings.
     *
     * @param  string[]  $sequence
     * @param  (callable(int): string)|null  $whenMissing
     * @return void
     */
    public static function createRandomStringsUsingSequence(array $sequence, $whenMissing = null)
    {
        $next = 0;

        $whenMissing ??= function ($length) use (&$next) {
            $factoryCache = static::$randomStringFactory;

            static::$randomStringFactory = null;

            $randomString = static::random($length);

            static::$randomStringFactory = $factoryCache;

            $next++;

            return $randomString;
        };

        static::createRandomStringsUsing(function ($length) use (&$next, $sequence, $whenMissing) {
            if (array_key_exists($next, $sequence)) {
                return $sequence[$next++];
            }

            return $whenMissing($length);
        });
    }

    /**
     * Indicate that random strings should be created normally and not using a custom factory.
     *
     * @return void
     */
    public static function createRandomStringsNormally()
    {
        static::$randomStringFactory = null;
    }

    /**
     * Repeat the given string.
     *
     * @param  string  $string
     * @param  int  $times
     * @return string
     */
    public static function repeat(string $string, int $times)
    {
        return str_repeat($string, $times);
    }

    /**
     * Replace a given value in the string sequentially with an array.
     *
     * @param  string  $search
     * @param  iterable<string>  $replace
     * @param  string  $subject
     * @return string
     */
    public static function replaceArray($search, $replace, $subject)
    {
        if ($replace instanceof Traversable) {
            $replace = iterator_to_array($replace);
        }

        $segments = explode($search, $subject);

        $result = array_shift($segments);

        foreach ($segments as $segment) {
            $result .= self::toStringOr(array_shift($replace) ?? $search, $search).$segment;
        }

        return $result;
    }

    /**
     * Convert the given value to a string or return the given fallback on failure.
     *
     * @param  mixed  $value
     * @param  string  $fallback
     * @return string
     */
    private static function toStringOr($value, $fallback)
    {
        try {
            return (string) $value;
        } catch (Throwable) {
            return $fallback;
        }
    }

    /**
     * Replace the given value in the given string.
     *
     * @param  string|iterable<string>  $search
     * @param  string|iterable<string>  $replace
     * @param  string|iterable<string>  $subject
     * @param  bool  $caseSensitive
     * @return ($subject is string ? string : string[])
     */
    public static function replace($search, $replace, $subject, $caseSensitive = true)
    {
        if ($search instanceof Traversable) {
            $search = iterator_to_array($search);
        }

        if ($replace instanceof Traversable) {
            $replace = iterator_to_array($replace);
        }

        if ($subject instanceof Traversable) {
            $subject = iterator_to_array($subject);
        }

        return $caseSensitive
            ? str_replace($search, $replace, $subject)
            : str_ireplace($search, $replace, $subject);
    }

    /**
     * Replace the first occurrence of a given value in the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @param  string  $subject
     * @return string
     */
    public static function replaceFirst($search, $replace, $subject)
    {
        $search = (string) $search;

        if ($search === '') {
            return $subject;
        }

        $position = strpos($subject, $search);

        if ($position !== false) {
            return substr_replace($subject, $replace, $position, strlen($search));
        }

        return $subject;
    }

    /**
     * Replace the first occurrence of the given value if it appears at the start of the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @param  string  $subject
     * @return string
     */
    public static function replaceStart($search, $replace, $subject)
    {
        $search = (string) $search;

        if ($search === '') {
            return $subject;
        }

        if (static::startsWith($subject, $search)) {
            return static::replaceFirst($search, $replace, $subject);
        }

        return $subject;
    }

    /**
     * Replace the last occurrence of a given value in the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @param  string  $subject
     * @return string
     */
    public static function replaceLast($search, $replace, $subject)
    {
        $search = (string) $search;

        if ($search === '') {
            return $subject;
        }

        $position = strrpos($subject, $search);

        if ($position !== false) {
            return substr_replace($subject, $replace, $position, strlen($search));
        }

        return $subject;
    }

    /**
     * Replace the last occurrence of a given value if it appears at the end of the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @param  string  $subject
     * @return string
     */
    public static function replaceEnd($search, $replace, $subject)
    {
        $search = (string) $search;

        if ($search === '') {
            return $subject;
        }

        if (static::endsWith($subject, $search)) {
            return static::replaceLast($search, $replace, $subject);
        }

        return $subject;
    }

    /**
     * Replace the patterns matching the given regular expression.
     *
     * @param  string|string[]  $pattern
     * @param  (\Closure(array): string)|string[]|string  $replace
     * @param  string[]|string  $subject
     * @param  int  $limit
     * @return ($subject is array ? string[]|null : string|null)
     */
    public static function replaceMatches($pattern, $replace, $subject, $limit = -1)
    {
        if ($replace instanceof Closure) {
            return preg_replace_callback($pattern, $replace, $subject, $limit);
        }

        return preg_replace($pattern, $replace, $subject, $limit);
    }

    /**
     * Remove any occurrence of the given string in the subject.
     *
     * @param  string|iterable<string>  $search
     * @param  string|iterable<string>  $subject
     * @param  bool  $caseSensitive
     * @return string
     */
    public static function remove($search, $subject, $caseSensitive = true)
    {
        if ($search instanceof Traversable) {
            $search = iterator_to_array($search);
        }

        return $caseSensitive
            ? str_replace($search, '', $subject)
            : str_ireplace($search, '', $subject);
    }

    /**
     * Reverse the given string.
     *
     * @param  string  $value
     * @return string
     */
    public static function reverse(string $value)
    {
        return implode('', array_reverse(mb_str_split($value)));
    }

    /**
     * Begin a string with a single instance of a given value.
     *
     * @param  string  $value
     * @param  string  $prefix
     * @return ($value is '' ? ($prefix is '' ? '' : non-empty-string): non-empty-string)
     */
    public static function start($value, $prefix)
    {
        $quoted = preg_quote($prefix, '/');

        return $prefix.preg_replace('/^(?:'.$quoted.')+/u', '', $value);
    }

    /**
     * Convert the given string to upper-case.
     *
     * @param  string  $value
     * @return ($value is '' ? '' : non-empty-string&uppercase-string)
     */
    public static function upper($value)
    {
        return mb_strtoupper($value, 'UTF-8');
    }

    /**
     * Convert the given string to proper case.
     *
     * @param  string  $value
     * @return string
     */
    public static function title($value)
    {
        return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
    }

    /**
     * Convert the given string to proper case for each word.
     *
     * @param  string  $value
     * @return string
     */
    public static function headline($value)
    {
        $parts = preg_split('/\s+/u', $value, -1, PREG_SPLIT_NO_EMPTY);

        $parts = count($parts) > 1
            ? array_map(static::title(...), $parts)
            : array_map(static::title(...), static::ucsplit(implode('_', $parts)));

        $collapsed = static::replace(['-', '_', ' '], '_', implode('_', $parts));

        return implode(' ', array_filter(explode('_', $collapsed)));
    }

    /**
     * Get the "initials" representing each word in the provided string, optionally capitalizing.
     *
     * @param  string  $value
     * @param  bool  $capitalize
     * @return string
     */
    public static function initials($value, $capitalize = false)
    {
        $parts = preg_split('/\s+/u', $value, -1, PREG_SPLIT_NO_EMPTY);

        $parts = array_map(fn ($part) => mb_substr($part, 0, 1), $parts);

        $initials = implode('', $parts);

        return $capitalize ? static::upper($initials) : $initials;
    }

    /**
     * Convert the given string to APA-style title case.
     *
     * See: https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case
     *
     * @param  string  $value
     * @return string
     */
    public static function apa($value)
    {
        if (trim($value) === '') {
            return $value;
        }

        $minorWords = [
            'and', 'as', 'but', 'for', 'if', 'nor', 'or', 'so', 'yet', 'a', 'an',
            'the', 'at', 'by', 'in', 'of', 'off', 'on', 'per', 'to', 'up', 'via',
            'et', 'ou', 'un', 'une', 'la', 'le', 'les', 'de', 'du', 'des', 'par', 'à',
        ];

        $endPunctuation = ['.', '!', '?', ':', '—', ','];

        $words = preg_split('/\s+/u', $value, -1, PREG_SPLIT_NO_EMPTY);
        $wordCount = count($words);

        for ($i = 0; $i < $wordCount; $i++) {
            $lowercaseWord = mb_strtolower($words[$i]);

            if (str_contains($lowercaseWord, '-')) {
                $hyphenatedWords = explode('-', $lowercaseWord);

                $hyphenatedWords = array_map(function ($part) use ($minorWords) {
                    return (in_array($part, $minorWords) && mb_strlen($part) <= 3)
                        ? $part
                        : mb_strtoupper(mb_substr($part, 0, 1)).mb_substr($part, 1);
                }, $hyphenatedWords);

                $words[$i] = implode('-', $hyphenatedWords);
            } else {
                if (in_array($lowercaseWord, $minorWords) &&
                    mb_strlen($lowercaseWord) <= 3 &&
                    ! ($i === 0 || in_array(mb_substr($words[$i - 1], -1), $endPunctuation))) {
                    $words[$i] = $lowercaseWord;
                } else {
                    $words[$i] = mb_strtoupper(mb_substr($lowercaseWord, 0, 1)).mb_substr($lowercaseWord, 1);
                }
            }
        }

        return implode(' ', $words);
    }

    /**
     * Get the singular form of an English word.
     *
     * @param  string  $value
     * @return string
     */
    public static function singular($value)
    {
        return Pluralizer::singular($value);
    }

    /**
     * Generate a URL friendly "slug" from a given string.
     *
     * @param  string  $title
     * @param  string  $separator
     * @param  string|null  $language
     * @param  array<string, string>  $dictionary
     * @return string
     */
    public static function slug($title, $separator = '-', $language = 'en', $dictionary = ['@' => 'at'])
    {
        $title = $language ? static::ascii($title, $language) : $title;

        // Convert all dashes/underscores into separator
        $flip = $separator === '-' ? '_' : '-';

        $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title);

        // Replace dictionary words
        foreach ($dictionary as $key => $value) {
            $dictionary[$key] = $separator.$value.$separator;
        }

        $title = str_replace(array_keys($dictionary), array_values($dictionary), $title);

        // Remove all characters that are not the separator, letters, numbers, or whitespace
        $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', static::lower($title));

        // Replace all separator characters and whitespace by a single separator
        $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title);

        return trim($title, $separator);
    }

    /**
     * Convert a string to snake case.
     *
     * @param  string  $value
     * @param  string  $delimiter
     * @return string
     */
    public static function snake($value, $delimiter = '_')
    {
        $key = $value;

        if (isset(static::$snakeCache[$key][$delimiter])) {
            return static::$snakeCache[$key][$delimiter];
        }

        if (! ctype_lower($value)) {
            $value = preg_replace('/\s+/u', '', ucwords($value));

            $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value));
        }

        return static::$snakeCache[$key][$delimiter] = $value;
    }

    /**
     * Remove all whitespace from both ends of a string.
     *
     * @param  string  $value
     * @param  string|null  $charlist
     * @return string
     */
    public static function trim($value, $charlist = null)
    {
        if ($charlist === null) {
            $trimDefaultCharacters = " \n\r\t\v\0";

            return preg_replace('~^[\s'.self::INVISIBLE_CHARACTERS.$trimDefaultCharacters.']+|[\s'.self::INVISIBLE_CHARACTERS.$trimDefaultCharacters.']+$~u', '', $value) ?? trim($value);
        }

        return trim($value, $charlist);
    }

    /**
     * Remove all whitespace from the beginning of a string.
     *
     * @param  string  $value
     * @param  string|null  $charlist
     * @return string
     */
    public static function ltrim($value, $charlist = null)
    {
        if ($charlist === null) {
            $ltrimDefaultCharacters = " \n\r\t\v\0";

            return preg_replace('~^[\s'.self::INVISIBLE_CHARACTERS.$ltrimDefaultCharacters.']+~u', '', $value) ?? ltrim($value);
        }

        return ltrim($value, $charlist);
    }

    /**
     * Remove all whitespace from the end of a string.
     *
     * @param  string  $value
     * @param  string|null  $charlist
     * @return string
     */
    public static function rtrim($value, $charlist = null)
    {
        if ($charlist === null) {
            $rtrimDefaultCharacters = " \n\r\t\v\0";

            return preg_replace('~[\s'.self::INVISIBLE_CHARACTERS.$rtrimDefaultCharacters.']+$~u', '', $value) ?? rtrim($value);
        }

        return rtrim($value, $charlist);
    }

    /**
     * Remove all "extra" blank space from the given string.
     *
     * @param  string  $value
     * @return string
     */
    public static function squish($value)
    {
        return preg_replace('~(\s|\x{3164}|\x{1160})+~u', ' ', static::trim($value));
    }

    /**
     * Determine if a given string starts with a given substring.
     *
     * @param  string  $haystack
     * @param  string|iterable<string>  $needles
     * @return ($needles is array{} ? false : ($haystack is non-empty-string ? bool : false))
     *
     * @phpstan-assert-if-true =non-empty-string $haystack
     */
    public static function startsWith($haystack, $needles)
    {
        if (is_null($haystack)) {
            return false;
        }

        if (! is_iterable($needles)) {
            $needles = [$needles];
        }

        foreach ($needles as $needle) {
            if ((string) $needle !== '' && str_starts_with($haystack, $needle)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if a given string doesn't start with a given substring.
     *
     * @param  string  $haystack
     * @param  string|iterable<string>  $needles
     * @return ($needles is array{} ? true : ($haystack is non-empty-string ? bool : true))
     *
     * @phpstan-assert-if-false =non-empty-string $haystack
     */
    public static function doesntStartWith($haystack, $needles)
    {
        return ! static::startsWith($haystack, $needles);
    }

    /**
     * Convert a value to studly caps case.
     *
     * @param  string  $value
     * @return ($value is '' ? '' : string)
     */
    public static function studly($value)
    {
        $key = $value;

        if (isset(static::$studlyCache[$key])) {
            return static::$studlyCache[$key];
        }

        $words = preg_split('/\s+/u', static::replace(['-', '_'], ' ', $value), -1, PREG_SPLIT_NO_EMPTY);

        $studlyWords = array_map(fn ($word) => static::ucfirst($word), $words);

        return static::$studlyCache[$key] = implode('', $studlyWords);
    }

    /**
     * Convert a value to Pascal case.
     *
     * @param  string  $value
     * @return ($value is '' ? '' : string)
     */
    public static function pascal($value)
    {
        return static::studly($value);
    }

    /**
     * Returns the portion of the string specified by the start and length parameters.
     *
     * @param  string  $string
     * @param  int  $start
     * @param  int|null  $length
     * @param  string  $encoding
     * @return string
     */
    public static function substr($string, $start, $length = null, $encoding = 'UTF-8')
    {
        return mb_substr($string, $start, $length, $encoding);
    }

    /**
     * Returns the number of substring occurrences.
     *
     * @param  string  $haystack
     * @param  string  $needle
     * @param  int  $offset
     * @param  int|null  $length
     * @return int
     */
    public static function substrCount($haystack, $needle, $offset = 0, $length = null)
    {
        if (! is_null($length)) {
            return substr_count($haystack, $needle, $offset, $length);
        }

        return substr_count($haystack, $needle, $offset);
    }

    /**
     * Replace text within a portion of a string.
     *
     * @param  string|string[]  $string
     * @param  string|string[]  $replace
     * @param  int|int[]  $offset
     * @param  int|int[]|null  $length
     * @return string|string[]
     */
    public static function substrReplace($string, $replace, $offset = 0, $length = null)
    {
        if ($length === null) {
            $length = static::length($string);
        }

        return mb_substr($string, 0, $offset)
            .$replace
            .mb_substr(mb_substr($string, $offset), $length);
    }

    /**
     * Swap multiple keywords in a string with other keywords.
     *
     * @param  array<string, string>  $map
     * @param  string  $subject
     * @return string
     */
    public static function swap(array $map, $subject)
    {
        return strtr($subject, $map);
    }

    /**
     * Take the first or last {$limit} characters of a string.
     *
     * @param  string  $string
     * @param  int  $limit
     * @return string
     */
    public static function take($string, int $limit): string
    {
        if ($limit < 0) {
            return static::substr($string, $limit);
        }

        return static::substr($string, 0, $limit);
    }

    /**
     * Convert the given string to Base64 encoding.
     *
     * @param  string  $string
     * @return ($string is '' ? '' : string)
     */
    public static function toBase64($string): string
    {
        return base64_encode($string);
    }

    /**
     * Decode the given Base64 encoded string.
     *
     * @param  string  $string
     * @param  bool  $strict
     * @return ($strict is true ? ($string is '' ? '' : string|false) : ($string is '' ? '' : string))
     */
    public static function fromBase64($string, $strict = false)
    {
        return base64_decode($string, $strict);
    }

    /**
     * Make a string's first character lowercase.
     *
     * @param  string  $string
     * @return ($string is '' ? '' : non-empty-string)
     */
    public static function lcfirst($string)
    {
        return static::lower(static::substr($string, 0, 1)).static::substr($string, 1);
    }

    /**
     * Make a string's first character uppercase.
     *
     * @param  string  $string
     * @return ($string is '' ? '' : non-empty-string)
     */
    public static function ucfirst($string)
    {
        return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
    }

    /**
     * Capitalize the first character of each word in a string.
     *
     * @param  string  $string
     * @param  string  $separators
     * @return ($string is '' ? '' : non-empty-string)
     */
    public static function ucwords($string, $separators = " \t\r\n\f\v")
    {
        $pattern = '/(^|['.preg_quote($separators, '/').'])(\p{Ll})/u';

        return preg_replace_callback($pattern, function ($matches) {
            return $matches[1].mb_strtoupper($matches[2]);
        }, $string);
    }

    /**
     * Split a string into pieces by uppercase characters.
     *
     * @param  string  $string
     * @return ($string is '' ? array{} : string[])
     */
    public static function ucsplit($string)
    {
        return preg_split('/(?=\p{Lu})/u', $string, -1, PREG_SPLIT_NO_EMPTY);
    }

    /**
     * Get the number of words a string contains.
     *
     * @param  string  $string
     * @param  string|null  $characters
     * @return non-negative-int
     */
    public static function wordCount($string, $characters = null)
    {
        return str_word_count($string, 0, $characters);
    }

    /**
     * Wrap a string to a given number of characters.
     *
     * @param  string  $string
     * @param  int  $characters
     * @param  string  $break
     * @param  bool  $cutLongWords
     * @return string
     */
    public static function wordWrap($string, $characters = 75, $break = "\n", $cutLongWords = false)
    {
        return wordwrap($string, $characters, $break, $cutLongWords);
    }

    /**
     * Generate a UUID (version 4).
     *
     * @return \Ramsey\Uuid\UuidInterface
     */
    public static function uuid()
    {
        return static::$uuidFactory
            ? call_user_func(static::$uuidFactory)
            : Uuid::uuid4();
    }

    /**
     * Generate a UUID (version 7).
     *
     * @param  \DateTimeInterface|null  $time
     * @return \Ramsey\Uuid\UuidInterface
     */
    public static function uuid7($time = null)
    {
        return static::$uuidFactory
            ? call_user_func(static::$uuidFactory)
            : Uuid::uuid7($time);
    }

    /**
     * Generate a time-ordered UUID.
     *
     * @return \Ramsey\Uuid\UuidInterface
     */
    public static function orderedUuid()
    {
        if (static::$uuidFactory) {
            return call_user_func(static::$uuidFactory);
        }

        $factory = new UuidFactory;

        $factory->setRandomGenerator(new CombGenerator(
            $factory->getRandomGenerator(),
            $factory->getNumberConverter()
        ));

        $factory->setCodec(new TimestampFirstCombCodec(
            $factory->getUuidBuilder()
        ));

        return $factory->uuid4();
    }

    /**
     * Set the callable that will be used to generate UUIDs.
     *
     * @param  (callable(): \Ramsey\Uuid\UuidInterface)|null  $factory
     * @return void
     */
    public static function createUuidsUsing(?callable $factory = null)
    {
        static::$uuidFactory = $factory;
    }

    /**
     * Set the sequence that will be used to generate UUIDs.
     *
     * @param  \Ramsey\Uuid\UuidInterface[]  $sequence
     * @param  (callable(): \Ramsey\Uuid\UuidInterface)|null  $whenMissing
     * @return void
     */
    public static function createUuidsUsingSequence(array $sequence, $whenMissing = null)
    {
        $next = 0;

        $whenMissing ??= function () use (&$next) {
            $factoryCache = static::$uuidFactory;

            static::$uuidFactory = null;

            $uuid = static::uuid();

            static::$uuidFactory = $factoryCache;

            $next++;

            return $uuid;
        };

        static::createUuidsUsing(function () use (&$next, $sequence, $whenMissing) {
            if (array_key_exists($next, $sequence)) {
                return $sequence[$next++];
            }

            return $whenMissing();
        });
    }

    /**
     * Always return the same UUID when generating new UUIDs.
     *
     * @param  (\Closure(\Ramsey\Uuid\UuidInterface): mixed)|null  $callback
     * @return \Ramsey\Uuid\UuidInterface
     */
    public static function freezeUuids(?Closure $callback = null)
    {
        $uuid = Str::uuid();

        Str::createUuidsUsing(fn () => $uuid);

        if ($callback !== null) {
            try {
                $callback($uuid);
            } finally {
                Str::createUuidsNormally();
            }
        }

        return $uuid;
    }

    /**
     * Indicate that UUIDs should be created normally and not using a custom factory.
     *
     * @return void
     */
    public static function createUuidsNormally()
    {
        static::$uuidFactory = null;
    }

    /**
     * Generate a ULID.
     *
     * @param  \DateTimeInterface|null  $time
     * @return \Symfony\Component\Uid\Ulid
     */
    public static function ulid($time = null)
    {
        if (static::$ulidFactory) {
            return call_user_func(static::$ulidFactory);
        }

        if ($time === null) {
            return new Ulid();
        }

        return new Ulid(Ulid::generate($time));
    }

    /**
     * Indicate that ULIDs should be created normally and not using a custom factory.
     *
     * @return void
     */
    public static function createUlidsNormally()
    {
        static::$ulidFactory = null;
    }

    /**
     * Set the callable that will be used to generate ULIDs.
     *
     * @param  (callable(): \Symfony\Component\Uid\Ulid)|null  $factory
     * @return void
     */
    public static function createUlidsUsing(?callable $factory = null)
    {
        static::$ulidFactory = $factory;
    }

    /**
     * Set the sequence that will be used to generate ULIDs.
     *
     * @param  \Symfony\Component\Uid\Ulid[]  $sequence
     * @param  (callable(): \Symfony\Component\Uid\Ulid)|null  $whenMissing
     * @return void
     */
    public static function createUlidsUsingSequence(array $sequence, $whenMissing = null)
    {
        $next = 0;

        $whenMissing ??= function () use (&$next) {
            $factoryCache = static::$ulidFactory;

            static::$ulidFactory = null;

            $ulid = static::ulid();

            static::$ulidFactory = $factoryCache;

            $next++;

            return $ulid;
        };

        static::createUlidsUsing(function () use (&$next, $sequence, $whenMissing) {
            if (array_key_exists($next, $sequence)) {
                return $sequence[$next++];
            }

            return $whenMissing();
        });
    }

    /**
     * Always return the same ULID when generating new ULIDs.
     *
     * @param  (Closure(Ulid): mixed)|null  $callback
     * @return Ulid
     */
    public static function freezeUlids(?Closure $callback = null)
    {
        $ulid = Str::ulid();

        Str::createUlidsUsing(fn () => $ulid);

        if ($callback !== null) {
            try {
                $callback($ulid);
            } finally {
                Str::createUlidsNormally();
            }
        }

        return $ulid;
    }

    /**
     * Remove all strings from the casing caches.
     *
     * @return void
     */
    public static function flushCache()
    {
        static::$snakeCache = [];
        static::$camelCache = [];
        static::$studlyCache = [];
    }

    /**
     * Return all factory functions to their default state.
     *
     * @return void
     */
    public static function resetFactoryState()
    {
        static::createRandomStringsNormally();
        static::createUlidsNormally();
        static::createUuidsNormally();
    }
}
<?php

namespace Illuminate\Support;

use ArrayAccess;
use Closure;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Dumpable;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Support\Traits\Tappable;
use JsonSerializable;
use Stringable as BaseStringable;

class Stringable implements JsonSerializable, ArrayAccess, BaseStringable
{
    use Conditionable, Dumpable, Macroable, Tappable;

    /**
     * The underlying string value.
     *
     * @var string
     */
    protected $value;

    /**
     * Create a new instance of the class.
     *
     * @param  string  $value
     */
    public function __construct($value = '')
    {
        $this->value = (string) $value;
    }

    /**
     * Return the remainder of a string after the first occurrence of a given value.
     *
     * @param  string  $search
     * @return static
     */
    public function after($search)
    {
        return new static(Str::after($this->value, $search));
    }

    /**
     * Return the remainder of a string after the last occurrence of a given value.
     *
     * @param  string  $search
     * @return static
     */
    public function afterLast($search)
    {
        return new static(Str::afterLast($this->value, $search));
    }

    /**
     * Append the given values to the string.
     *
     * @param  array|string  ...$values
     * @return static
     */
    public function append(...$values)
    {
        return new static($this->value.implode('', $values));
    }

    /**
     * Append a new line to the string.
     *
     * @param  int  $count
     * @return $this
     */
    public function newLine($count = 1)
    {
        return $this->append(str_repeat(PHP_EOL, $count));
    }

    /**
     * Transliterate a UTF-8 value to ASCII.
     *
     * @param  string  $language
     * @return static
     */
    public function ascii($language = 'en')
    {
        return new static(Str::ascii($this->value, $language));
    }

    /**
     * Get the trailing name component of the path.
     *
     * @param  string  $suffix
     * @return static
     */
    public function basename($suffix = '')
    {
        return new static(basename($this->value, $suffix));
    }

    /**
     * Get the character at the specified index.
     *
     * @param  int  $index
     * @return string|false
     */
    public function charAt($index)
    {
        return Str::charAt($this->value, $index);
    }

    /**
     * Remove the given string if it exists at the start of the current string.
     *
     * @param  string|array  $needle
     * @return static
     */
    public function chopStart($needle)
    {
        return new static(Str::chopStart($this->value, $needle));
    }

    /**
     * Remove the given string if it exists at the end of the current string.
     *
     * @param  string|array  $needle
     * @return static
     */
    public function chopEnd($needle)
    {
        return new static(Str::chopEnd($this->value, $needle));
    }

    /**
     * Get the basename of the class path.
     *
     * @return static
     */
    public function classBasename()
    {
        return new static(class_basename($this->value));
    }

    /**
     * Get the portion of a string before the first occurrence of a given value.
     *
     * @param  string  $search
     * @return static
     */
    public function before($search)
    {
        return new static(Str::before($this->value, $search));
    }

    /**
     * Get the portion of a string before the last occurrence of a given value.
     *
     * @param  string  $search
     * @return static
     */
    public function beforeLast($search)
    {
        return new static(Str::beforeLast($this->value, $search));
    }

    /**
     * Get the portion of a string between two given values.
     *
     * @param  string  $from
     * @param  string  $to
     * @return static
     */
    public function between($from, $to)
    {
        return new static(Str::between($this->value, $from, $to));
    }

    /**
     * Get the smallest possible portion of a string between two given values.
     *
     * @param  string  $from
     * @param  string  $to
     * @return static
     */
    public function betweenFirst($from, $to)
    {
        return new static(Str::betweenFirst($this->value, $from, $to));
    }

    /**
     * Convert a value to camel case.
     *
     * @return static
     */
    public function camel()
    {
        return new static(Str::camel($this->value));
    }

    /**
     * Determine if a given string contains a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  bool  $ignoreCase
     * @return bool
     */
    public function contains($needles, $ignoreCase = false)
    {
        return Str::contains($this->value, $needles, $ignoreCase);
    }

    /**
     * Determine if a given string contains all array values.
     *
     * @param  iterable<string>  $needles
     * @param  bool  $ignoreCase
     * @return bool
     */
    public function containsAll($needles, $ignoreCase = false)
    {
        return Str::containsAll($this->value, $needles, $ignoreCase);
    }

    /**
     * Determine if a given string doesn't contain a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  bool  $ignoreCase
     * @return bool
     */
    public function doesntContain($needles, $ignoreCase = false)
    {
        return Str::doesntContain($this->value, $needles, $ignoreCase);
    }

    /**
     * Convert the case of a string.
     *
     * @param  int  $mode
     * @param  string|null  $encoding
     * @return static
     */
    public function convertCase(int $mode = MB_CASE_FOLD, ?string $encoding = 'UTF-8')
    {
        return new static(Str::convertCase($this->value, $mode, $encoding));
    }

    /**
     * Replace consecutive instances of a given character with a single character.
     *
     * @param  array<string>|string  $characters
     * @return static
     */
    public function deduplicate(array|string $characters = ' ')
    {
        return new static(Str::deduplicate($this->value, $characters));
    }

    /**
     * Get the parent directory's path.
     *
     * @param  int  $levels
     * @return static
     */
    public function dirname($levels = 1)
    {
        return new static(dirname($this->value, $levels));
    }

    /**
     * Determine if a given string ends with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @return bool
     */
    public function endsWith($needles)
    {
        return Str::endsWith($this->value, $needles);
    }

    /**
     * Determine if a given string doesn't end with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @return bool
     */
    public function doesntEndWith($needles)
    {
        return Str::doesntEndWith($this->value, $needles);
    }

    /**
     * Determine if the string is an exact match with the given value.
     *
     * @param  \Illuminate\Support\Stringable|string  $value
     * @return bool
     */
    public function exactly($value)
    {
        if ($value instanceof Stringable) {
            $value = $value->toString();
        }

        return $this->value === $value;
    }

    /**
     * Extracts an excerpt from text that matches the first instance of a phrase.
     *
     * @param  string  $phrase
     * @param  array  $options
     * @return string|null
     */
    public function excerpt($phrase = '', $options = [])
    {
        return Str::excerpt($this->value, $phrase, $options);
    }

    /**
     * Explode the string into a collection.
     *
     * @param  string  $delimiter
     * @param  int  $limit
     * @return \Illuminate\Support\Collection<int, string>
     */
    public function explode($delimiter, $limit = PHP_INT_MAX)
    {
        return new Collection(explode($delimiter, $this->value, $limit));
    }

    /**
     * Split a string using a regular expression or by length.
     *
     * @param  string|int  $pattern
     * @param  int  $limit
     * @param  int  $flags
     * @return \Illuminate\Support\Collection<int, string>
     */
    public function split($pattern, $limit = -1, $flags = 0)
    {
        if (filter_var($pattern, FILTER_VALIDATE_INT) !== false) {
            return new Collection(mb_str_split($this->value, $pattern));
        }

        $segments = preg_split($pattern, $this->value, $limit, $flags);

        return ! empty($segments) ? new Collection($segments) : new Collection;
    }

    /**
     * Cap a string with a single instance of a given value.
     *
     * @param  string  $cap
     * @return static
     */
    public function finish($cap)
    {
        return new static(Str::finish($this->value, $cap));
    }

    /**
     * Determine if a given string matches a given pattern.
     *
     * @param  string|iterable<string>  $pattern
     * @param  bool  $ignoreCase
     * @return bool
     */
    public function is($pattern, $ignoreCase = false)
    {
        return Str::is($pattern, $this->value, $ignoreCase);
    }

    /**
     * Determine if a given string is 7 bit ASCII.
     *
     * @return bool
     */
    public function isAscii()
    {
        return Str::isAscii($this->value);
    }

    /**
     * Determine if a given string is valid JSON.
     *
     * @return bool
     */
    public function isJson()
    {
        return Str::isJson($this->value);
    }

    /**
     * Determine if a given value is a valid URL.
     *
     * @param  array  $protocols
     * @return bool
     */
    public function isUrl(array $protocols = [])
    {
        return Str::isUrl($this->value, $protocols);
    }

    /**
     * Determine if a given string is a valid UUID.
     *
     * @param  int<0, 8>|'max'|null  $version
     * @return bool
     */
    public function isUuid($version = null)
    {
        return Str::isUuid($this->value, $version);
    }

    /**
     * Determine if a given string is a valid ULID.
     *
     * @return bool
     */
    public function isUlid()
    {
        return Str::isUlid($this->value);
    }

    /**
     * Determine if the given string is empty.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return $this->value === '';
    }

    /**
     * Determine if the given string is not empty.
     *
     * @return bool
     */
    public function isNotEmpty()
    {
        return ! $this->isEmpty();
    }

    /**
     * Convert a string to kebab case.
     *
     * @return static
     */
    public function kebab()
    {
        return new static(Str::kebab($this->value));
    }

    /**
     * Return the length of the given string.
     *
     * @param  string|null  $encoding
     * @return int
     */
    public function length($encoding = null)
    {
        return Str::length($this->value, $encoding);
    }

    /**
     * Limit the number of characters in a string.
     *
     * @param  int  $limit
     * @param  string  $end
     * @param  bool  $preserveWords
     * @return static
     */
    public function limit($limit = 100, $end = '...', $preserveWords = false)
    {
        return new static(Str::limit($this->value, $limit, $end, $preserveWords));
    }

    /**
     * Convert the given string to lower-case.
     *
     * @return static
     */
    public function lower()
    {
        return new static(Str::lower($this->value));
    }

    /**
     * Convert GitHub flavored Markdown into HTML.
     *
     * @param  array  $options
     * @param  array  $extensions
     * @return static
     */
    public function markdown(array $options = [], array $extensions = [])
    {
        return new static(Str::markdown($this->value, $options, $extensions));
    }

    /**
     * Convert inline Markdown into HTML.
     *
     * @param  array  $options
     * @param  array  $extensions
     * @return static
     */
    public function inlineMarkdown(array $options = [], array $extensions = [])
    {
        return new static(Str::inlineMarkdown($this->value, $options, $extensions));
    }

    /**
     * Masks a portion of a string with a repeated character.
     *
     * @param  string  $character
     * @param  int  $index
     * @param  int|null  $length
     * @param  string  $encoding
     * @return static
     */
    public function mask($character, $index, $length = null, $encoding = 'UTF-8')
    {
        return new static(Str::mask($this->value, $character, $index, $length, $encoding));
    }

    /**
     * Get the string matching the given pattern.
     *
     * @param  string  $pattern
     * @return static
     */
    public function match($pattern)
    {
        return new static(Str::match($pattern, $this->value));
    }

    /**
     * Determine if a given string matches a given pattern.
     *
     * @param  string|iterable<string>  $pattern
     * @return bool
     */
    public function isMatch($pattern)
    {
        return Str::isMatch($pattern, $this->value);
    }

    /**
     * Get the string matching the given pattern.
     *
     * @param  string  $pattern
     * @return \Illuminate\Support\Collection
     */
    public function matchAll($pattern)
    {
        return Str::matchAll($pattern, $this->value);
    }

    /**
     * Determine if the string matches the given pattern.
     *
     * @param  string  $pattern
     * @return bool
     */
    public function test($pattern)
    {
        return $this->isMatch($pattern);
    }

    /**
     * Remove all non-numeric characters from a string.
     *
     * @return static
     */
    public function numbers()
    {
        return new static(Str::numbers($this->value));
    }

    /**
     * Pad both sides of the string with another.
     *
     * @param  int  $length
     * @param  string  $pad
     * @return static
     */
    public function padBoth($length, $pad = ' ')
    {
        return new static(Str::padBoth($this->value, $length, $pad));
    }

    /**
     * Pad the left side of the string with another.
     *
     * @param  int  $length
     * @param  string  $pad
     * @return static
     */
    public function padLeft($length, $pad = ' ')
    {
        return new static(Str::padLeft($this->value, $length, $pad));
    }

    /**
     * Pad the right side of the string with another.
     *
     * @param  int  $length
     * @param  string  $pad
     * @return static
     */
    public function padRight($length, $pad = ' ')
    {
        return new static(Str::padRight($this->value, $length, $pad));
    }

    /**
     * Parse a Class@method style callback into class and method.
     *
     * @param  string|null  $default
     * @return array<int, string|null>
     */
    public function parseCallback($default = null)
    {
        return Str::parseCallback($this->value, $default);
    }

    /**
     * Call the given callback and return a new string.
     *
     * @param  callable  $callback
     * @return static
     */
    public function pipe(callable $callback)
    {
        return new static($callback($this));
    }

    /**
     * Get the plural form of an English word.
     *
     * @param  int|array|\Countable  $count
     * @param  bool  $prependCount
     * @return static
     */
    public function plural($count = 2, $prependCount = false)
    {
        return new static(Str::plural($this->value, $count, $prependCount));
    }

    /**
     * Pluralize the last word of an English, studly caps case string.
     *
     * @param  int|array|\Countable  $count
     * @return static
     */
    public function pluralStudly($count = 2)
    {
        return new static(Str::pluralStudly($this->value, $count));
    }

    /**
     * Pluralize the last word of an English, Pascal caps case string.
     *
     * @param  int|array|\Countable  $count
     * @return static
     */
    public function pluralPascal($count = 2)
    {
        return new static(Str::pluralStudly($this->value, $count));
    }

    /**
     * Find the multi-byte safe position of the first occurrence of the given substring.
     *
     * @param  string  $needle
     * @param  int  $offset
     * @param  string|null  $encoding
     * @return int|false
     */
    public function position($needle, $offset = 0, $encoding = null)
    {
        return Str::position($this->value, $needle, $offset, $encoding);
    }

    /**
     * Prepend the given values to the string.
     *
     * @param  string  ...$values
     * @return static
     */
    public function prepend(...$values)
    {
        return new static(implode('', $values).$this->value);
    }

    /**
     * Remove any occurrence of the given string in the subject.
     *
     * @param  string|iterable<string>  $search
     * @param  bool  $caseSensitive
     * @return static
     */
    public function remove($search, $caseSensitive = true)
    {
        return new static(Str::remove($search, $this->value, $caseSensitive));
    }

    /**
     * Reverse the string.
     *
     * @return static
     */
    public function reverse()
    {
        return new static(Str::reverse($this->value));
    }

    /**
     * Repeat the string.
     *
     * @param  int  $times
     * @return static
     */
    public function repeat(int $times)
    {
        return new static(str_repeat($this->value, $times));
    }

    /**
     * Replace the given value in the given string.
     *
     * @param  string|iterable<string>  $search
     * @param  string|iterable<string>  $replace
     * @param  bool  $caseSensitive
     * @return static
     */
    public function replace($search, $replace, $caseSensitive = true)
    {
        return new static(Str::replace($search, $replace, $this->value, $caseSensitive));
    }

    /**
     * Replace a given value in the string sequentially with an array.
     *
     * @param  string  $search
     * @param  iterable<string>  $replace
     * @return static
     */
    public function replaceArray($search, $replace)
    {
        return new static(Str::replaceArray($search, $replace, $this->value));
    }

    /**
     * Replace the first occurrence of a given value in the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @return static
     */
    public function replaceFirst($search, $replace)
    {
        return new static(Str::replaceFirst($search, $replace, $this->value));
    }

    /**
     * Replace the first occurrence of the given value if it appears at the start of the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @return static
     */
    public function replaceStart($search, $replace)
    {
        return new static(Str::replaceStart($search, $replace, $this->value));
    }

    /**
     * Replace the last occurrence of a given value in the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @return static
     */
    public function replaceLast($search, $replace)
    {
        return new static(Str::replaceLast($search, $replace, $this->value));
    }

    /**
     * Replace the last occurrence of a given value if it appears at the end of the string.
     *
     * @param  string  $search
     * @param  string  $replace
     * @return static
     */
    public function replaceEnd($search, $replace)
    {
        return new static(Str::replaceEnd($search, $replace, $this->value));
    }

    /**
     * Replace the patterns matching the given regular expression.
     *
     * @param  array|string  $pattern
     * @param  \Closure|string[]|string  $replace
     * @param  int  $limit
     * @return static
     */
    public function replaceMatches($pattern, $replace, $limit = -1)
    {
        if ($replace instanceof Closure) {
            return new static(preg_replace_callback($pattern, $replace, $this->value, $limit));
        }

        return new static(preg_replace($pattern, $replace, $this->value, $limit));
    }

    /**
     * Parse input from a string to a collection, according to a format.
     *
     * @param  string  $format
     * @return \Illuminate\Support\Collection
     */
    public function scan($format)
    {
        return new Collection(sscanf($this->value, $format));
    }

    /**
     * Remove all "extra" blank space from the given string.
     *
     * @return static
     */
    public function squish()
    {
        return new static(Str::squish($this->value));
    }

    /**
     * Begin a string with a single instance of a given value.
     *
     * @param  string  $prefix
     * @return static
     */
    public function start($prefix)
    {
        return new static(Str::start($this->value, $prefix));
    }

    /**
     * Strip HTML and PHP tags from the given string.
     *
     * @param  string[]|string|null  $allowedTags
     * @return static
     */
    public function stripTags($allowedTags = null)
    {
        return new static(strip_tags($this->value, $allowedTags));
    }

    /**
     * Convert the given string to upper-case.
     *
     * @return static
     */
    public function upper()
    {
        return new static(Str::upper($this->value));
    }

    /**
     * Convert the given string to proper case.
     *
     * @return static
     */
    public function title()
    {
        return new static(Str::title($this->value));
    }

    /**
     * Convert the given string to proper case for each word.
     *
     * @return static
     */
    public function headline()
    {
        return new static(Str::headline($this->value));
    }

    /**
     * Convert the given string to only its initials.
     *
     * @param  bool  $capitalize
     * @return static
     */
    public function initials($capitalize = false)
    {
        return new static(Str::initials($this->value, $capitalize));
    }

    /**
     * Convert the given string to APA-style title case.
     *
     * @return static
     */
    public function apa()
    {
        return new static(Str::apa($this->value));
    }

    /**
     * Transliterate a string to its closest ASCII representation.
     *
     * @param  string|null  $unknown
     * @param  bool|null  $strict
     * @return static
     */
    public function transliterate($unknown = '?', $strict = false)
    {
        return new static(Str::transliterate($this->value, $unknown, $strict));
    }

    /**
     * Get the singular form of an English word.
     *
     * @return static
     */
    public function singular()
    {
        return new static(Str::singular($this->value));
    }

    /**
     * Generate a URL friendly "slug" from a given string.
     *
     * @param  string  $separator
     * @param  string|null  $language
     * @param  array<string, string>  $dictionary
     * @return static
     */
    public function slug($separator = '-', $language = 'en', $dictionary = ['@' => 'at'])
    {
        return new static(Str::slug($this->value, $separator, $language, $dictionary));
    }

    /**
     * Convert a string to snake case.
     *
     * @param  string  $delimiter
     * @return static
     */
    public function snake($delimiter = '_')
    {
        return new static(Str::snake($this->value, $delimiter));
    }

    /**
     * Determine if a given string starts with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @return bool
     */
    public function startsWith($needles)
    {
        return Str::startsWith($this->value, $needles);
    }

    /**
     * Determine if a given string doesn't start with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @return bool
     */
    public function doesntStartWith($needles)
    {
        return Str::doesntStartWith($this->value, $needles);
    }

    /**
     * Convert a value to studly caps case.
     *
     * @return static
     */
    public function studly()
    {
        return new static(Str::studly($this->value));
    }

    /**
     * Convert the string to Pascal case.
     *
     * @return static
     */
    public function pascal()
    {
        return new static(Str::pascal($this->value));
    }

    /**
     * Returns the portion of the string specified by the start and length parameters.
     *
     * @param  int  $start
     * @param  int|null  $length
     * @param  string  $encoding
     * @return static
     */
    public function substr($start, $length = null, $encoding = 'UTF-8')
    {
        return new static(Str::substr($this->value, $start, $length, $encoding));
    }

    /**
     * Returns the number of substring occurrences.
     *
     * @param  string  $needle
     * @param  int  $offset
     * @param  int|null  $length
     * @return int
     */
    public function substrCount($needle, $offset = 0, $length = null)
    {
        return Str::substrCount($this->value, $needle, $offset, $length);
    }

    /**
     * Replace text within a portion of a string.
     *
     * @param  string|string[]  $replace
     * @param  int|int[]  $offset
     * @param  int|int[]|null  $length
     * @return static
     */
    public function substrReplace($replace, $offset = 0, $length = null)
    {
        return new static(Str::substrReplace($this->value, $replace, $offset, $length));
    }

    /**
     * Swap multiple keywords in a string with other keywords.
     *
     * @param  array  $map
     * @return static
     */
    public function swap(array $map)
    {
        return new static(strtr($this->value, $map));
    }

    /**
     * Take the first or last {$limit} characters.
     *
     * @param  int  $limit
     * @return static
     */
    public function take(int $limit)
    {
        if ($limit < 0) {
            return $this->substr($limit);
        }

        return $this->substr(0, $limit);
    }

    /**
     * Trim the string of the given characters.
     *
     * @param  string|null  $characters
     * @return static
     */
    public function trim($characters = null)
    {
        return new static(Str::trim(...array_merge([$this->value], func_get_args())));
    }

    /**
     * Left trim the string of the given characters.
     *
     * @param  string|null  $characters
     * @return static
     */
    public function ltrim($characters = null)
    {
        return new static(Str::ltrim(...array_merge([$this->value], func_get_args())));
    }

    /**
     * Right trim the string of the given characters.
     *
     * @param  string|null  $characters
     * @return static
     */
    public function rtrim($characters = null)
    {
        return new static(Str::rtrim(...array_merge([$this->value], func_get_args())));
    }

    /**
     * Make a string's first character lowercase.
     *
     * @return static
     */
    public function lcfirst()
    {
        return new static(Str::lcfirst($this->value));
    }

    /**
     * Make a string's first character uppercase.
     *
     * @return static
     */
    public function ucfirst()
    {
        return new static(Str::ucfirst($this->value));
    }

    /**
     * Capitalize the first character of each word in a string.
     *
     * @param  string  $separators
     * @return static
     */
    public function ucwords($separators = " \t\r\n\f\v")
    {
        return new static(Str::ucwords($this->value, $separators));
    }

    /**
     * Split a string by uppercase characters.
     *
     * @return \Illuminate\Support\Collection<int, string>
     */
    public function ucsplit()
    {
        return new Collection(Str::ucsplit($this->value));
    }

    /**
     * Execute the given callback if the string contains a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenContains($needles, $callback, $default = null)
    {
        return $this->when($this->contains($needles), $callback, $default);
    }

    /**
     * Execute the given callback if the string contains all array values.
     *
     * @param  iterable<string>  $needles
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenContainsAll(array $needles, $callback, $default = null)
    {
        return $this->when($this->containsAll($needles), $callback, $default);
    }

    /**
     * Execute the given callback if the string is empty.
     *
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenEmpty($callback, $default = null)
    {
        return $this->when($this->isEmpty(), $callback, $default);
    }

    /**
     * Execute the given callback if the string is not empty.
     *
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenNotEmpty($callback, $default = null)
    {
        return $this->when($this->isNotEmpty(), $callback, $default);
    }

    /**
     * Execute the given callback if the string ends with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenEndsWith($needles, $callback, $default = null)
    {
        return $this->when($this->endsWith($needles), $callback, $default);
    }

    /**
     * Execute the given callback if the string doesn't end with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenDoesntEndWith($needles, $callback, $default = null)
    {
        return $this->when($this->doesntEndWith($needles), $callback, $default);
    }

    /**
     * Execute the given callback if the string is an exact match with the given value.
     *
     * @param  string  $value
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenExactly($value, $callback, $default = null)
    {
        return $this->when($this->exactly($value), $callback, $default);
    }

    /**
     * Execute the given callback if the string is not an exact match with the given value.
     *
     * @param  string  $value
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenNotExactly($value, $callback, $default = null)
    {
        return $this->when(! $this->exactly($value), $callback, $default);
    }

    /**
     * Execute the given callback if the string matches a given pattern.
     *
     * @param  string|iterable<string>  $pattern
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenIs($pattern, $callback, $default = null)
    {
        return $this->when($this->is($pattern), $callback, $default);
    }

    /**
     * Execute the given callback if the string is 7 bit ASCII.
     *
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenIsAscii($callback, $default = null)
    {
        return $this->when($this->isAscii(), $callback, $default);
    }

    /**
     * Execute the given callback if the string is a valid UUID.
     *
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenIsUuid($callback, $default = null)
    {
        return $this->when($this->isUuid(), $callback, $default);
    }

    /**
     * Execute the given callback if the string is a valid ULID.
     *
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenIsUlid($callback, $default = null)
    {
        return $this->when($this->isUlid(), $callback, $default);
    }

    /**
     * Execute the given callback if the string starts with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenStartsWith($needles, $callback, $default = null)
    {
        return $this->when($this->startsWith($needles), $callback, $default);
    }

    /**
     * Execute the given callback if the string doesn't start with a given substring.
     *
     * @param  string|iterable<string>  $needles
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenDoesntStartWith($needles, $callback, $default = null)
    {
        return $this->when($this->doesntStartWith($needles), $callback, $default);
    }

    /**
     * Execute the given callback if the string matches the given pattern.
     *
     * @param  string  $pattern
     * @param  callable  $callback
     * @param  callable|null  $default
     * @return static
     */
    public function whenTest($pattern, $callback, $default = null)
    {
        return $this->when($this->test($pattern), $callback, $default);
    }

    /**
     * Limit the number of words in a string.
     *
     * @param  int  $words
     * @param  string  $end
     * @return static
     */
    public function words($words = 100, $end = '...')
    {
        return new static(Str::words($this->value, $words, $end));
    }

    /**
     * Get the number of words a string contains.
     *
     * @param  string|null  $characters
     * @return int
     */
    public function wordCount($characters = null)
    {
        return Str::wordCount($this->value, $characters);
    }

    /**
     * Wrap a string to a given number of characters.
     *
     * @param  int  $characters
     * @param  string  $break
     * @param  bool  $cutLongWords
     * @return static
     */
    public function wordWrap($characters = 75, $break = "\n", $cutLongWords = false)
    {
        return new static(Str::wordWrap($this->value, $characters, $break, $cutLongWords));
    }

    /**
     * Wrap the string with the given strings.
     *
     * @param  string  $before
     * @param  string|null  $after
     * @return static
     */
    public function wrap($before, $after = null)
    {
        return new static(Str::wrap($this->value, $before, $after));
    }

    /**
     * Unwrap the string with the given strings.
     *
     * @param  string  $before
     * @param  string|null  $after
     * @return static
     */
    public function unwrap($before, $after = null)
    {
        return new static(Str::unwrap($this->value, $before, $after));
    }

    /**
     * Convert the string into a `HtmlString` instance.
     *
     * @return \Illuminate\Support\HtmlString
     */
    public function toHtmlString()
    {
        return new HtmlString($this->value);
    }

    /**
     * Convert the string to Base64 encoding.
     *
     * @return static
     */
    public function toBase64()
    {
        return new static(base64_encode($this->value));
    }

    /**
     * Decode the Base64 encoded string.
     *
     * @param  bool  $strict
     * @return static
     */
    public function fromBase64($strict = false)
    {
        return new static(base64_decode($this->value, $strict));
    }

    /**
     * Hash the string using the given algorithm.
     *
     * @param  string  $algorithm
     * @return static
     */
    public function hash(string $algorithm)
    {
        return new static(hash($algorithm, $this->value));
    }

    /**
     * Encrypt the string.
     *
     * @param  bool  $serialize
     * @return static
     */
    public function encrypt(bool $serialize = false)
    {
        return new static(encrypt($this->value, $serialize));
    }

    /**
     * Decrypt the string.
     *
     * @param  bool  $serialize
     * @return static
     */
    public function decrypt(bool $serialize = false)
    {
        return new static(decrypt($this->value, $serialize));
    }

    /**
     * Dump the string.
     *
     * @param  mixed  ...$args
     * @return $this
     */
    public function dump(...$args)
    {
        dump($this->value, ...$args);

        return $this;
    }

    /**
     * Get the underlying string value.
     *
     * @return string
     */
    public function value()
    {
        return $this->toString();
    }

    /**
     * Get the underlying string value.
     *
     * @return string
     */
    public function toString()
    {
        return $this->value;
    }

    /**
     * Get the underlying string value as an integer.
     *
     * @param  int  $base
     * @return int
     */
    public function toInteger($base = 10)
    {
        return intval($this->value, $base);
    }

    /**
     * Get the underlying string value as a float.
     *
     * @return float
     */
    public function toFloat()
    {
        return (float) $this->value;
    }

    /**
     * Get the underlying string value as a boolean.
     *
     * Returns true when value is "1", "true", "on", and "yes". Otherwise, returns false.
     *
     * @return bool
     */
    public function toBoolean()
    {
        return filter_var($this->value, FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * Get the underlying string value as a Carbon instance.
     *
     * @param  string|null  $format
     * @param  string|null  $tz
     * @return \Illuminate\Support\Carbon
     *
     * @throws \Carbon\Exceptions\InvalidFormatException
     */
    public function toDate($format = null, $tz = null)
    {
        if (is_null($format)) {
            return Date::parse($this->value, $tz);
        }

        return Date::createFromFormat($format, $this->value, $tz);
    }

    /**
     * Get the underlying string value as a Uri instance.
     *
     * @return \Illuminate\Support\Uri
     */
    public function toUri()
    {
        return Uri::of($this->value);
    }

    /**
     * Convert the object to a string when JSON encoded.
     *
     * @return string
     */
    public function jsonSerialize(): string
    {
        return $this->__toString();
    }

    /**
     * Determine if the given offset exists.
     *
     * @param  mixed  $offset
     * @return bool
     */
    public function offsetExists(mixed $offset): bool
    {
        return isset($this->value[$offset]);
    }

    /**
     * Get the value at the given offset.
     *
     * @param  mixed  $offset
     * @return string
     */
    public function offsetGet(mixed $offset): string
    {
        return $this->value[$offset];
    }

    /**
     * Set the value at the given offset.
     *
     * @param  mixed  $offset
     * @return void
     */
    public function offsetSet(mixed $offset, mixed $value): void
    {
        $this->value[$offset] = $value;
    }

    /**
     * Unset the value at the given offset.
     *
     * @param  mixed  $offset
     * @return void
     */
    public function offsetUnset(mixed $offset): void
    {
        unset($this->value[$offset]);
    }

    /**
     * Proxy dynamic properties onto methods.
     *
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {
        return $this->{$key}();
    }

    /**
     * Get the raw string value.
     *
     * @return string
     */
    public function __toString()
    {
        return (string) $this->value;
    }
}
<?php

namespace Illuminate\Support;

use RuntimeException;

class Lottery
{
    /**
     * The number of expected wins.
     *
     * @var int|float
     */
    protected $chances;

    /**
     * The number of potential opportunities to win.
     *
     * @var int|null
     */
    protected $outOf;

    /**
     * The winning callback.
     *
     * @var null|callable
     */
    protected $winner;

    /**
     * The losing callback.
     *
     * @var null|callable
     */
    protected $loser;

    /**
     * The factory that should be used to generate results.
     *
     * @var callable|null
     */
    protected static $resultFactory;

    /**
     * Create a new Lottery instance.
     *
     * @param  int|float  $chances
     * @param  int<1, max>|null  $outOf
     *
     * @throws \RuntimeException
     */
    public function __construct($chances, $outOf = null)
    {
        if ($outOf === null && is_float($chances) && $chances > 1) {
            throw new RuntimeException('Float must not be greater than 1.');
        }

        if ($outOf !== null && $outOf < 1) {
            throw new RuntimeException('Lottery "out of" value must be greater than or equal to 1.');
        }

        $this->chances = $chances;

        $this->outOf = $outOf;
    }

    /**
     * Create a new Lottery instance.
     *
     * @param  int|float  $chances
     * @param  int|null  $outOf
     * @return static
     */
    public static function odds($chances, $outOf = null)
    {
        return new static($chances, $outOf);
    }

    /**
     * Set the winner callback.
     *
     * @param  callable  $callback
     * @return $this
     */
    public function winner($callback)
    {
        $this->winner = $callback;

        return $this;
    }

    /**
     * Set the loser callback.
     *
     * @param  callable  $callback
     * @return $this
     */
    public function loser($callback)
    {
        $this->loser = $callback;

        return $this;
    }

    /**
     * Run the lottery.
     *
     * @param  mixed  ...$args
     * @return mixed
     */
    public function __invoke(...$args)
    {
        return $this->runCallback(...$args);
    }

    /**
     * Run the lottery.
     *
     * @param  null|int  $times
     * @return mixed
     */
    public function choose($times = null)
    {
        if ($times === null) {
            return $this->runCallback();
        }

        $results = [];

        for ($i = 0; $i < $times; $i++) {
            $results[] = $this->runCallback();
        }

        return $results;
    }

    /**
     * Run the winner or loser callback, randomly.
     *
     * @param  mixed  ...$args
     * @return callable
     */
    protected function runCallback(...$args)
    {
        return $this->wins()
            ? ($this->winner ?? fn () => true)(...$args)
            : ($this->loser ?? fn () => false)(...$args);
    }

    /**
     * Determine if the lottery "wins" or "loses".
     *
     * @return bool
     */
    protected function wins()
    {
        return static::resultFactory()($this->chances, $this->outOf);
    }

    /**
     * The factory that determines the lottery result.
     *
     * @return callable
     */
    protected static function resultFactory()
    {
        return static::$resultFactory ?? fn ($chances, $outOf) => $outOf === null
            ? random_int(0, PHP_INT_MAX) / PHP_INT_MAX <= $chances
            : random_int(1, $outOf) <= $chances;
    }

    /**
     * Force the lottery to always result in a win.
     *
     * @param  callable|null  $callback
     * @return void
     */
    public static function alwaysWin($callback = null)
    {
        self::setResultFactory(fn () => true);

        if ($callback === null) {
            return;
        }

        $callback();

        static::determineResultNormally();
    }

    /**
     * Force the lottery to always result in a lose.
     *
     * @param  callable|null  $callback
     * @return void
     */
    public static function alwaysLose($callback = null)
    {
        self::setResultFactory(fn () => false);

        if ($callback === null) {
            return;
        }

        $callback();

        static::determineResultNormally();
    }

    /**
     * Set the sequence that will be used to determine lottery results.
     *
     * @param  array  $sequence
     * @param  callable|null  $whenMissing
     * @return void
     */
    public static function fix($sequence, $whenMissing = null)
    {
        static::forceResultWithSequence($sequence, $whenMissing);
    }

    /**
     * Set the sequence that will be used to determine lottery results.
     *
     * @param  array  $sequence
     * @param  callable|null  $whenMissing
     * @return void
     */
    public static function forceResultWithSequence($sequence, $whenMissing = null)
    {
        $next = 0;

        $whenMissing ??= function ($chances, $outOf) use (&$next) {
            $factoryCache = static::$resultFactory;

            static::$resultFactory = null;

            $result = static::resultFactory()($chances, $outOf);

            static::$resultFactory = $factoryCache;

            $next++;

            return $result;
        };

        static::setResultFactory(function ($chances, $outOf) use (&$next, $sequence, $whenMissing) {
            if (array_key_exists($next, $sequence)) {
                return $sequence[$next++];
            }

            return $whenMissing($chances, $outOf);
        });
    }

    /**
     * Indicate that the lottery results should be determined normally.
     *
     * @return void
     */
    public static function determineResultsNormally()
    {
        static::determineResultNormally();
    }

    /**
     * Indicate that the lottery results should be determined normally.
     *
     * @return void
     */
    public static function determineResultNormally()
    {
        static::$resultFactory = null;
    }

    /**
     * Set the factory that should be used to determine the lottery results.
     *
     * @param  callable  $factory
     * @return void
     */
    public static function setResultFactory($factory)
    {
        self::$resultFactory = $factory;
    }
}
<?php

namespace Illuminate\Support\Traits;

use BadMethodCallException;
use Closure;
use ReflectionClass;
use ReflectionMethod;
use RuntimeException;
use Throwable;

trait Macroable
{
    /**
     * The registered string macros.
     *
     * @var array
     */
    protected static $macros = [];

    /**
     * Register a custom macro.
     *
     * @param  string  $name
     * @param  object|callable  $macro
     *
     * @param-closure-this static  $macro
     *
     * @return void
     */
    public static function macro($name, $macro)
    {
        static::$macros[$name] = $macro;
    }

    /**
     * Mix another object into the class.
     *
     * @param  object  $mixin
     * @param  bool  $replace
     * @return void
     *
     * @throws \ReflectionException
     */
    public static function mixin($mixin, $replace = true)
    {
        $methods = (new ReflectionClass($mixin))->getMethods(
            ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
        );

        foreach ($methods as $method) {
            if ($replace || ! static::hasMacro($method->name)) {
                static::macro($method->name, $method->invoke($mixin));
            }
        }
    }

    /**
     * Checks if macro is registered.
     *
     * @param  string  $name
     * @return bool
     */
    public static function hasMacro($name)
    {
        return isset(static::$macros[$name]);
    }

    /**
     * Flush the existing macros.
     *
     * @return void
     */
    public static function flushMacros()
    {
        static::$macros = [];
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public static function __callStatic($method, $parameters)
    {
        if (! static::hasMacro($method)) {
            throw new BadMethodCallException(sprintf(
                'Method %s::%s does not exist.', static::class, $method
            ));
        }

        $macro = static::$macros[$method];

        if ($macro instanceof Closure) {
            $macro = $macro->bindTo(null, static::class);
        }

        return $macro(...$parameters);
    }

    /**
     * Dynamically handle calls to the class.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public function __call($method, $parameters)
    {
        if (! static::hasMacro($method)) {
            throw new BadMethodCallException(sprintf(
                'Method %s::%s does not exist.', static::class, $method
            ));
        }

        $macro = static::$macros[$method];

        if ($macro instanceof Closure) {
            try {
                $macro = $macro->bindTo($this, static::class) ?? throw new RuntimeException;
            } catch (Throwable) {
                $macro = $macro->bindTo(null, static::class);
            }
        }

        return $macro(...$parameters);
    }
}
<?php

namespace Illuminate\Support;

use ReflectionAttribute;
use ReflectionClass;
use ReflectionEnum;
use ReflectionMethod;
use ReflectionNamedType;
use ReflectionUnionType;

class Reflector
{
    /**
     * This is a PHP 7.4 compatible implementation of is_callable.
     *
     * @param  mixed  $var
     * @param  bool  $syntaxOnly
     * @return bool
     */
    public static function isCallable($var, $syntaxOnly = false)
    {
        if (! is_array($var)) {
            return is_callable($var, $syntaxOnly);
        }

        if (! isset($var[0], $var[1]) || ! is_string($var[1] ?? null)) {
            return false;
        }

        if ($syntaxOnly &&
            (is_string($var[0]) || is_object($var[0])) &&
            is_string($var[1])) {
            return true;
        }

        $class = is_object($var[0]) ? get_class($var[0]) : $var[0];

        $method = $var[1];

        if (! class_exists($class)) {
            return false;
        }

        if (method_exists($class, $method)) {
            return (new ReflectionMethod($class, $method))->isPublic();
        }

        if (is_object($var[0]) && method_exists($class, '__call')) {
            return (new ReflectionMethod($class, '__call'))->isPublic();
        }

        if (! is_object($var[0]) && method_exists($class, '__callStatic')) {
            return (new ReflectionMethod($class, '__callStatic'))->isPublic();
        }

        return false;
    }

    /**
     * Get the specified class attribute, optionally following an inheritance chain.
     *
     * @template TAttribute of object
     *
     * @param  object|class-string  $objectOrClass
     * @param  class-string<TAttribute>  $attribute
     * @param  bool  $ascend
     * @return TAttribute|null
     */
    public static function getClassAttribute($objectOrClass, $attribute, $ascend = false)
    {
        return static::getClassAttributes($objectOrClass, $attribute, $ascend)->flatten()->first();
    }

    /**
     * Get the specified class attribute(s), optionally following an inheritance chain.
     *
     * @template TTarget of object
     * @template TAttribute of object
     *
     * @param  TTarget|class-string<TTarget>  $objectOrClass
     * @param  class-string<TAttribute>  $attribute
     * @param  bool  $includeParents
     * @return ($includeParents is true ? Collection<class-string<contravariant TTarget>, Collection<int, TAttribute>> : Collection<int, TAttribute>)
     */
    public static function getClassAttributes($objectOrClass, $attribute, $includeParents = false)
    {
        $reflectionClass = new ReflectionClass($objectOrClass);

        $attributes = [];

        do {
            $attributes[$reflectionClass->name] = new Collection(array_map(
                fn (ReflectionAttribute $reflectionAttribute) => $reflectionAttribute->newInstance(),
                $reflectionClass->getAttributes($attribute)
            ));
        } while ($includeParents && false !== $reflectionClass = $reflectionClass->getParentClass());

        return $includeParents ? new Collection($attributes) : array_first($attributes);
    }

    /**
     * Get the class name of the given parameter's type, if possible.
     *
     * @param  \ReflectionParameter  $parameter
     * @return string|null
     */
    public static function getParameterClassName($parameter)
    {
        $type = $parameter->getType();

        if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) {
            return;
        }

        return static::getTypeName($parameter, $type);
    }

    /**
     * Get the class names of the given parameter's type, including union types.
     *
     * @param  \ReflectionParameter  $parameter
     * @return array
     */
    public static function getParameterClassNames($parameter)
    {
        $type = $parameter->getType();

        if (! $type instanceof ReflectionUnionType) {
            return array_filter([static::getParameterClassName($parameter)]);
        }

        $unionTypes = [];

        foreach ($type->getTypes() as $listedType) {
            if (! $listedType instanceof ReflectionNamedType || $listedType->isBuiltin()) {
                continue;
            }

            $unionTypes[] = static::getTypeName($parameter, $listedType);
        }

        return array_filter($unionTypes);
    }

    /**
     * Get the given type's class name.
     *
     * @param  \ReflectionParameter  $parameter
     * @param  \ReflectionNamedType  $type
     * @return string
     */
    protected static function getTypeName($parameter, $type)
    {
        $name = $type->getName();

        if (! is_null($class = $parameter->getDeclaringClass())) {
            if ($name === 'self') {
                return $class->getName();
            }

            if ($name === 'parent' && $parent = $class->getParentClass()) {
                return $parent->getName();
            }
        }

        return $name;
    }

    /**
     * Determine if the parameter's type is a subclass of the given type.
     *
     * @param  \ReflectionParameter  $parameter
     * @param  string  $className
     * @return bool
     */
    public static function isParameterSubclassOf($parameter, $className)
    {
        $paramClassName = static::getParameterClassName($parameter);

        return $paramClassName
            && (class_exists($paramClassName) || interface_exists($paramClassName))
            && (new ReflectionClass($paramClassName))->isSubclassOf($className);
    }

    /**
     * Determine if the parameter's type is a Backed Enum with a string backing type.
     *
     * @param  \ReflectionParameter  $parameter
     * @return bool
     */
    public static function isParameterBackedEnumWithStringBackingType($parameter)
    {
        if (! $parameter->getType() instanceof ReflectionNamedType) {
            return false;
        }

        $backedEnumClass = $parameter->getType()?->getName();

        if (is_null($backedEnumClass)) {
            return false;
        }

        if (enum_exists($backedEnumClass)) {
            $reflectionBackedEnum = new ReflectionEnum($backedEnumClass);

            return $reflectionBackedEnum->isBacked()
                && $reflectionBackedEnum->getBackingType()->getName() == 'string';
        }

        return false;
    }
}
<?php

namespace Illuminate\Support\Traits;

use Closure;
use Illuminate\Support\Collection;
use Illuminate\Support\Reflector;
use ReflectionFunction;
use ReflectionIntersectionType;
use ReflectionUnionType;
use RuntimeException;

trait ReflectsClosures
{
    /**
     * Get the class name of the first parameter of the given Closure.
     *
     * @param  \Closure  $closure
     * @return string
     *
     * @throws \ReflectionException
     * @throws \RuntimeException
     */
    protected function firstClosureParameterType(Closure $closure)
    {
        $types = array_values($this->closureParameterTypes($closure));

        if (! $types) {
            throw new RuntimeException('The given Closure has no parameters.');
        }

        if ($types[0] === null) {
            throw new RuntimeException('The first parameter of the given Closure is missing a type hint.');
        }

        return $types[0];
    }

    /**
     * Get the class names of the first parameter of the given Closure, including union types.
     *
     * @param  \Closure  $closure
     * @return array
     *
     * @throws \ReflectionException
     * @throws \RuntimeException
     */
    protected function firstClosureParameterTypes(Closure $closure)
    {
        $reflection = new ReflectionFunction($closure);

        $types = (new Collection($reflection->getParameters()))
            ->mapWithKeys(function ($parameter) {
                if ($parameter->isVariadic()) {
                    return [$parameter->getName() => null];
                }

                return [$parameter->getName() => Reflector::getParameterClassNames($parameter)];
            })
            ->filter()
            ->values()
            ->all();

        if (empty($types)) {
            throw new RuntimeException('The given Closure has no parameters.');
        }

        if (isset($types[0]) && empty($types[0])) {
            throw new RuntimeException('The first parameter of the given Closure is missing a type hint.');
        }

        return $types[0];
    }

    /**
     * Get the class names / types of the parameters of the given Closure.
     *
     * @param  \Closure  $closure
     * @return array
     *
     * @throws \ReflectionException
     */
    protected function closureParameterTypes(Closure $closure)
    {
        $reflection = new ReflectionFunction($closure);

        return (new Collection($reflection->getParameters()))
            ->mapWithKeys(function ($parameter) {
                if ($parameter->isVariadic()) {
                    return [$parameter->getName() => null];
                }

                return [$parameter->getName() => Reflector::getParameterClassName($parameter)];
            })
            ->all();
    }

    /**
     * Get the class names / types of the return type of the given Closure.
     *
     * @param  \Closure  $closure
     * @return list<class-string>
     *
     * @throws \ReflectionException
     */
    protected function closureReturnTypes(Closure $closure)
    {
        $reflection = new ReflectionFunction($closure);

        if ($reflection->getReturnType() === null ||
            $reflection->getReturnType() instanceof ReflectionIntersectionType) {
            return [];
        }

        $types = $reflection->getReturnType() instanceof ReflectionUnionType
            ? $reflection->getReturnType()->getTypes()
            : [$reflection->getReturnType()];

        return (new Collection($types))
            ->reject(fn ($type) => $type->isBuiltin())
            ->reject(fn ($type) => in_array($type->getName(), ['static', 'self']))
            ->map(fn ($type) => $type->getName())
            ->values()
            ->all();
    }
}
<?php

use Illuminate\Support\Traits\ReflectsClosures;

if (! function_exists('lazy')) {
    /**
     * Create a lazy instance.
     *
     * @template TValue of object
     *
     * @param  class-string<TValue>|(\Closure(TValue): mixed)  $class
     * @param  (\Closure(TValue): mixed)|int  $callback
     * @param  int  $options
     * @param  array<string, mixed>  $eager
     * @return TValue
     */
    function lazy($class, $callback = 0, $options = 0, $eager = [])
    {
        static $closureReflector;

        $closureReflector ??= new class
        {
            use ReflectsClosures;

            public function typeFromParameter($callback)
            {
                return $this->firstClosureParameterType($callback);
            }
        };

        [$class, $callback, $options] = is_string($class)
            ? [$class, $callback, $options]
            : [$closureReflector->typeFromParameter($class), $class, $callback ?: $options];

        $reflectionClass = new ReflectionClass($class);

        $instance = $reflectionClass->newLazyGhost(function ($instance) use ($callback) {
            $result = $callback($instance);

            if (is_array($result)) {
                $instance->__construct(...$result);
            }
        }, $options);

        foreach ($eager as $property => $value) {
            $reflectionClass->getProperty($property)->setRawValueWithoutLazyInitialization($instance, $value);
        }

        return $instance;
    }
}

if (! function_exists('proxy')) {
    /**
     * Create a lazy proxy instance.
     *
     * @template TValue of object
     *
     * @param  class-string<TValue>|(\Closure(TValue): TValue)  $class
     * @param  (\Closure(TValue): TValue)|int  $callback
     * @param  int  $options
     * @param  array<string, mixed>  $eager
     * @return TValue
     */
    function proxy($class, $callback = 0, $options = 0, $eager = [])
    {
        static $closureReflector;

        $closureReflector = new class
        {
            use ReflectsClosures;

            public function get($callback)
            {
                return $this->closureReturnTypes($callback)[0] ?? $this->firstClosureParameterType($callback);
            }
        };

        [$class, $callback, $options] = is_string($class)
            ? [$class, $callback, $options]
            : [$closureReflector->get($class), $class, $callback ?: $options];

        $reflectionClass = new ReflectionClass($class);

        $proxy = $reflectionClass->newLazyProxy(function () use ($callback, $eager, &$proxy) {
            $instance = $callback($proxy, $eager);

            return $instance;
        }, $options);

        foreach ($eager as $property => $value) {
            $reflectionClass->getProperty($property)->setRawValueWithoutLazyInitialization($proxy, $value);
        }

        return $proxy;
    }
}
<?php

namespace Illuminate\Filesystem;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\PathTraversalDetected;

class ReceiveFile
{
    /**
     * Create a new invokable controller to receive files.
     */
    public function __construct(
        protected string $disk,
        protected array $config,
        protected bool $isProduction,
    ) {
        //
    }

    /**
     * Handle the incoming request.
     */
    public function __invoke(Request $request, string $path): Response
    {
        abort_unless(
            $this->hasValidSignature($request),
            $this->isProduction ? 404 : 403
        );

        try {
            Storage::disk($this->disk)->put($path, $request->getContent());

            return response()->noContent();
        } catch (PathTraversalDetected) {
            abort(404);
        }
    }

    /**
     * Determine if the request has a valid signature if applicable.
     */
    protected function hasValidSignature(Request $request): bool
    {
        return $request->boolean('upload') && $request->hasValidRelativeSignature();
    }
}
<?php

namespace Illuminate\Filesystem;

if (! function_exists('Illuminate\Filesystem\join_paths')) {
    /**
     * Join the given paths together.
     *
     * @param  string|null  $basePath
     * @param  string  ...$paths
     */
    function join_paths($basePath, ...$paths): string
    {
        foreach ($paths as $index => $path) {
            if (empty($path) && $path !== '0') {
                unset($paths[$index]);
            } else {
                $paths[$index] = DIRECTORY_SEPARATOR.ltrim($path, DIRECTORY_SEPARATOR);
            }
        }

        return $basePath.implode('', $paths);
    }
}
<?php

namespace Illuminate\Filesystem;

use Aws\S3\S3Client;
use Closure;
use Illuminate\Contracts\Filesystem\Factory as FactoryContract;
use Illuminate\Support\Arr;
use Illuminate\Support\RebindsCallbacksToSelf;
use InvalidArgumentException;
use League\Flysystem\AwsS3V3\AwsS3V3Adapter as S3Adapter;
use League\Flysystem\AwsS3V3\PortableVisibilityConverter as AwsS3PortableVisibilityConverter;
use League\Flysystem\Filesystem as Flysystem;
use League\Flysystem\FilesystemAdapter as FlysystemAdapter;
use League\Flysystem\Ftp\FtpAdapter;
use League\Flysystem\Ftp\FtpConnectionOptions;
use League\Flysystem\Local\LocalFilesystemAdapter as LocalAdapter;
use League\Flysystem\PathPrefixing\PathPrefixedAdapter;
use League\Flysystem\PhpseclibV3\SftpAdapter;
use League\Flysystem\PhpseclibV3\SftpConnectionProvider;
use League\Flysystem\ReadOnly\ReadOnlyFilesystemAdapter;
use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
use League\Flysystem\Visibility;
use ReflectionException;
use RuntimeException;

use function Illuminate\Support\enum_value;

/**
 * @mixin \Illuminate\Contracts\Filesystem\Filesystem
 * @mixin \Illuminate\Filesystem\FilesystemAdapter
 */
class FilesystemManager implements FactoryContract
{
    use RebindsCallbacksToSelf;

    /**
     * The application instance.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected $app;

    /**
     * The array of resolved filesystem drivers.
     *
     * @var array
     */
    protected $disks = [];

    /**
     * The registered custom driver creators.
     *
     * @var array
     */
    protected $customCreators = [];

    /**
     * Create a new filesystem manager instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     */
    public function __construct($app)
    {
        $this->app = $app;
    }

    /**
     * Get a filesystem instance.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function drive($name = null)
    {
        return $this->disk($name);
    }

    /**
     * Get a filesystem instance.
     *
     * @param  \UnitEnum|string|null  $name
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function disk($name = null)
    {
        $name = enum_value($name) ?: $this->getDefaultDriver();

        return $this->disks[$name] = $this->get($name);
    }

    /**
     * Get a default cloud filesystem instance.
     *
     * @return \Illuminate\Contracts\Filesystem\Cloud
     */
    public function cloud()
    {
        $name = $this->getDefaultCloudDriver();

        return $this->disks[$name] = $this->get($name);
    }

    /**
     * Build an on-demand disk.
     *
     * @param  string|array  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function build($config)
    {
        return $this->resolve('ondemand', is_array($config) ? $config : [
            'driver' => 'local',
            'root' => $config,
        ]);
    }

    /**
     * Attempt to get the disk from the local cache.
     *
     * @param  string  $name
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    protected function get($name)
    {
        return $this->disks[$name] ?? $this->resolve($name);
    }

    /**
     * Resolve the given disk.
     *
     * @param  string  $name
     * @param  array|null  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     *
     * @throws \InvalidArgumentException
     */
    protected function resolve($name, $config = null)
    {
        $config ??= $this->getConfig($name);

        if (empty($config['driver'])) {
            throw new InvalidArgumentException("Disk [{$name}] does not have a configured driver.");
        }

        $driver = $config['driver'];

        if (isset($this->customCreators[$driver])) {
            return $this->callCustomCreator($config);
        }

        $driverMethod = 'create'.ucfirst($driver).'Driver';

        if (! method_exists($this, $driverMethod)) {
            throw new InvalidArgumentException("Driver [{$driver}] is not supported.");
        }

        return $this->{$driverMethod}($config, $name);
    }

    /**
     * Call a custom driver creator.
     *
     * @param  array  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    protected function callCustomCreator(array $config)
    {
        return $this->customCreators[$config['driver']]($this->app, $config);
    }

    /**
     * Create an instance of the local driver.
     *
     * @param  array  $config
     * @param  string  $name
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function createLocalDriver(array $config, string $name = 'local')
    {
        $visibility = PortableVisibilityConverter::fromArray(
            $config['permissions'] ?? [],
            $config['directory_visibility'] ?? $config['visibility'] ?? Visibility::PRIVATE
        );

        $links = ($config['links'] ?? null) === 'skip'
            ? LocalAdapter::SKIP_LINKS
            : LocalAdapter::DISALLOW_LINKS;

        $adapter = new LocalAdapter(
            $config['root'], $visibility, $config['lock'] ?? LOCK_EX, $links
        );

        return (new LocalFilesystemAdapter(
            $this->createFlysystem($adapter, $config), $adapter, $config
        ))->diskName(
            $name
        )->shouldServeSignedUrls(
            $config['serve'] ?? false,
            fn () => $this->app['url'],
        );
    }

    /**
     * Create an instance of the ftp driver.
     *
     * @param  array  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function createFtpDriver(array $config)
    {
        if (! isset($config['root'])) {
            $config['root'] = '';
        }

        $adapter = new FtpAdapter(FtpConnectionOptions::fromArray($config));

        return new FilesystemAdapter($this->createFlysystem($adapter, $config), $adapter, $config);
    }

    /**
     * Create an instance of the sftp driver.
     *
     * @param  array  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     */
    public function createSftpDriver(array $config)
    {
        $provider = SftpConnectionProvider::fromArray($config);

        $root = $config['root'] ?? '';

        $visibility = PortableVisibilityConverter::fromArray(
            $config['permissions'] ?? []
        );

        $adapter = new SftpAdapter($provider, $root, $visibility);

        return new FilesystemAdapter($this->createFlysystem($adapter, $config), $adapter, $config);
    }

    /**
     * Create an instance of the Amazon S3 driver.
     *
     * @param  array  $config
     * @return \Illuminate\Contracts\Filesystem\Cloud
     */
    public function createS3Driver(array $config)
    {
        $s3Config = $this->formatS3Config($config);

        $root = (string) ($s3Config['root'] ?? '');

        $visibility = new AwsS3PortableVisibilityConverter(
            $config['visibility'] ?? Visibility::PUBLIC
        );

        $streamReads = $s3Config['stream_reads'] ?? false;

        $client = new S3Client($s3Config);

        $adapter = new S3Adapter($client, $s3Config['bucket'], $root, $visibility, null, $config['options'] ?? [], $streamReads);

        return new AwsS3V3Adapter(
            $this->createFlysystem($adapter, $config), $adapter, $s3Config, $client
        );
    }

    /**
     * Format the given S3 configuration with the default options.
     *
     * @param  array  $config
     * @return array
     */
    protected function formatS3Config(array $config)
    {
        $config += ['version' => 'latest'];

        if (! empty($config['key']) && ! empty($config['secret'])) {
            $config['credentials'] = Arr::only($config, ['key', 'secret']);

            if (! empty($config['token'])) {
                $config['credentials']['token'] = $config['token'];
            }
        }

        return Arr::except($config, ['token']);
    }

    /**
     * Create a scoped driver.
     *
     * @param  array  $config
     * @return \Illuminate\Contracts\Filesystem\Filesystem
     *
     * @throws \InvalidArgumentException
     */
    public function createScopedDriver(array $config)
    {
        if (empty($config['disk'])) {
            throw new InvalidArgumentException('Scoped disk is missing "disk" configuration option.');
        } elseif (empty($config['prefix'])) {
            throw new InvalidArgumentException('Scoped disk is missing "prefix" configuration option.');
        }

        return $this->build(tap(
            is_string($config['disk']) ? $this->getConfig($config['disk']) : $config['disk'],
            function (&$parent) use ($config) {
                if (empty($parent['prefix'])) {
                    $parent['prefix'] = $config['prefix'];
                } else {
                    $separator = $parent['directory_separator'] ?? DIRECTORY_SEPARATOR;

                    $parentPrefix = rtrim($parent['prefix'], $separator);
                    $scopedPrefix = ltrim($config['prefix'], $separator);

                    $parent['prefix'] = "{$parentPrefix}{$separator}{$scopedPrefix}";
                }

                if (isset($config['visibility'])) {
                    $parent['visibility'] = $config['visibility'];
                }

                if (isset($config['throw'])) {
                    $parent['throw'] = $config['throw'];
                }
            }
        ));
    }

    /**
     * Create a Flysystem instance with the given adapter.
     *
     * @param  \League\Flysystem\FilesystemAdapter  $adapter
     * @param  array  $config
     * @return \League\Flysystem\FilesystemOperator
     */
    protected function createFlysystem(FlysystemAdapter $adapter, array $config)
    {
        if ($config['read-only'] ?? false) {
            $adapter = new ReadOnlyFilesystemAdapter($adapter);
        }

        if (! empty($config['prefix'])) {
            $adapter = new PathPrefixedAdapter($adapter, $config['prefix']);
        }

        if (str_contains($config['endpoint'] ?? '', 'r2.cloudflarestorage.com')) {
            $config['retain_visibility'] = false;
        }

        return new Flysystem($adapter, Arr::only($config, [
            'directory_visibility',
            'disable_asserts',
            'retain_visibility',
            'temporary_url',
            'url',
            'visibility',
        ]));
    }

    /**
     * Set the given disk instance.
     *
     * @param  string  $name
     * @param  mixed  $disk
     * @return $this
     */
    public function set($name, $disk)
    {
        $this->disks[$name] = $disk;

        return $this;
    }

    /**
     * Get the filesystem connection configuration.
     *
     * @param  string  $name
     * @return array
     */
    protected function getConfig($name)
    {
        return $this->app['config']["filesystems.disks.{$name}"] ?: [];
    }

    /**
     * Get the default driver name.
     *
     * @return string
     */
    public function getDefaultDriver()
    {
        return $this->app['config']['filesystems.default'];
    }

    /**
     * Get the default cloud driver name.
     *
     * @return string
     */
    public function getDefaultCloudDriver()
    {
        return $this->app['config']['filesystems.cloud'] ?? 's3';
    }

    /**
     * Unset the given disk instances.
     *
     * @param  array|string  $disk
     * @return $this
     */
    public function forgetDisk($disk)
    {
        foreach ((array) $disk as $diskName) {
            unset($this->disks[$diskName]);
        }

        return $this;
    }

    /**
     * Disconnect the given disk and remove from local cache.
     *
     * @param  string|null  $name
     * @return void
     */
    public function purge($name = null)
    {
        $name ??= $this->getDefaultDriver();

        unset($this->disks[$name]);
    }

    /**
     * Register a custom driver creator Closure.
     *
     * @param  string  $driver
     * @param  \Closure  $callback
     *
     * @param-closure-this  $this  $callback
     *
     * @return $this
     */
    public function extend($driver, Closure $callback)
    {
        try {
            $callback = $this->bindCallbackToSelf($callback) ?? throw new RuntimeException('Unable to bind custom driver callback');
        } catch (ReflectionException $e) {
            throw new RuntimeException('Unable to bind custom driver callback', previous: $e);
        }

        $this->customCreators[$driver] = $callback;

        return $this;
    }

    /**
     * Set the application instance used by the manager.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return $this
     */
    public function setApplication($app)
    {
        $this->app = $app;

        return $this;
    }

    /**
     * Dynamically call the default driver instance.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->disk()->$method(...$parameters);
    }
}
<?php

namespace Illuminate\Filesystem;

use Closure;
use Illuminate\Container\Container;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Contracts\Filesystem\Cloud as CloudFilesystemContract;
use Illuminate\Contracts\Filesystem\Filesystem as FilesystemContract;
use Illuminate\Http\File;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use League\Flysystem\FilesystemAdapter as FlysystemAdapter;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\Ftp\FtpAdapter;
use League\Flysystem\Local\LocalFilesystemAdapter as LocalAdapter;
use League\Flysystem\PathPrefixer;
use League\Flysystem\PhpseclibV3\SftpAdapter;
use League\Flysystem\StorageAttributes;
use League\Flysystem\UnableToCopyFile;
use League\Flysystem\UnableToCreateDirectory;
use League\Flysystem\UnableToDeleteDirectory;
use League\Flysystem\UnableToDeleteFile;
use League\Flysystem\UnableToMoveFile;
use League\Flysystem\UnableToProvideChecksum;
use League\Flysystem\UnableToReadFile;
use League\Flysystem\UnableToRetrieveMetadata;
use League\Flysystem\UnableToSetVisibility;
use League\Flysystem\UnableToWriteFile;
use League\Flysystem\Visibility;
use PHPUnit\Framework\Assert as PHPUnit;
use Psr\Http\Message\StreamInterface;
use RuntimeException;
use Symfony\Component\HttpFoundation\StreamedResponse;

/**
 * @mixin \League\Flysystem\FilesystemOperator
 */
class FilesystemAdapter implements CloudFilesystemContract
{
    use Conditionable;
    use Macroable {
        __call as macroCall;
    }

    /**
     * The Flysystem filesystem implementation.
     *
     * @var \League\Flysystem\FilesystemOperator
     */
    protected $driver;

    /**
     * The Flysystem adapter implementation.
     *
     * @var \League\Flysystem\FilesystemAdapter
     */
    protected $adapter;

    /**
     * The filesystem configuration.
     *
     * @var array
     */
    protected $config;

    /**
     * The Flysystem PathPrefixer instance.
     *
     * @var \League\Flysystem\PathPrefixer
     */
    protected $prefixer;

    /**
     * The file server callback.
     *
     * @var \Closure|null
     */
    protected $serveCallback;

    /**
     * The temporary URL builder callback.
     *
     * @var \Closure|null
     */
    protected $temporaryUrlCallback;

    /**
     * The temporary upload URL builder callback.
     *
     * @var \Closure|null
     */
    protected $temporaryUploadUrlCallback;

    /**
     * Create a new filesystem adapter instance.
     *
     * @param  \League\Flysystem\FilesystemOperator  $driver
     * @param  \League\Flysystem\FilesystemAdapter  $adapter
     * @param  array  $config
     */
    public function __construct(FilesystemOperator $driver, FlysystemAdapter $adapter, array $config = [])
    {
        $this->driver = $driver;
        $this->adapter = $adapter;
        $this->config = $config;
        $separator = $config['directory_separator'] ?? DIRECTORY_SEPARATOR;

        $this->prefixer = new PathPrefixer($config['root'] ?? '', $separator);

        if (isset($config['prefix'])) {
            $this->prefixer = new PathPrefixer($this->prefixer->prefixPath($config['prefix']), $separator);
        }
    }

    /**
     * Assert that the given file or directory exists.
     *
     * @param  string|array  $path
     * @param  string|null  $content
     * @return $this
     */
    public function assertExists($path, $content = null)
    {
        clearstatcache();

        $paths = Arr::wrap($path);

        foreach ($paths as $path) {
            PHPUnit::assertTrue(
                $this->exists($path), "Unable to find a file or directory at path [{$path}]."
            );

            if (! is_null($content)) {
                $actual = $this->get($path);

                PHPUnit::assertSame(
                    $content,
                    $actual,
                    "File or directory [{$path}] was found, but content [{$actual}] does not match [{$content}]."
                );
            }
        }

        return $this;
    }

    /**
     * Assert that the number of files in path equals the expected count.
     *
     * @param  string  $path
     * @param  int  $count
     * @param  bool  $recursive
     * @return $this
     */
    public function assertCount($path, $count, $recursive = false)
    {
        clearstatcache();

        $actual = count($this->files($path, $recursive));

        PHPUnit::assertEquals(
            $count, $actual, "Expected [{$count}] files at [{$path}], but found [{$actual}]."
        );

        return $this;
    }

    /**
     * Assert that the given file or directory does not exist.
     *
     * @param  string|array  $path
     * @return $this
     */
    public function assertMissing($path)
    {
        clearstatcache();

        $paths = Arr::wrap($path);

        foreach ($paths as $path) {
            PHPUnit::assertFalse(
                $this->exists($path), "Found unexpected file or directory at path [{$path}]."
            );
        }

        return $this;
    }

    /**
     * Assert that the given directory is empty.
     *
     * @param  string  $path
     * @return $this
     */
    public function assertDirectoryEmpty($path)
    {
        PHPUnit::assertEmpty(
            $this->allFiles($path), "Directory [{$path}] is not empty."
        );

        return $this;
    }

    /**
     * Determine if a file or directory exists.
     *
     * @param  string  $path
     * @return bool
     */
    public function exists($path)
    {
        return $this->driver->has($path);
    }

    /**
     * Determine if a file or directory is missing.
     *
     * @param  string  $path
     * @return bool
     */
    public function missing($path)
    {
        return ! $this->exists($path);
    }

    /**
     * Determine if a file exists.
     *
     * @param  string  $path
     * @return bool
     */
    public function fileExists($path)
    {
        return $this->driver->fileExists($path);
    }

    /**
     * Determine if a file is missing.
     *
     * @param  string  $path
     * @return bool
     */
    public function fileMissing($path)
    {
        return ! $this->fileExists($path);
    }

    /**
     * Determine if a directory exists.
     *
     * @param  string  $path
     * @return bool
     */
    public function directoryExists($path)
    {
        return $this->driver->directoryExists($path);
    }

    /**
     * Determine if a directory is missing.
     *
     * @param  string  $path
     * @return bool
     */
    public function directoryMissing($path)
    {
        return ! $this->directoryExists($path);
    }

    /**
     * Get the full path to the file that exists at the given relative path.
     *
     * @param  string  $path
     * @return string
     */
    public function path($path)
    {
        return $this->prefixer->prefixPath($path);
    }

    /**
     * Get the contents of a file.
     *
     * @param  string  $path
     * @return string|null
     */
    public function get($path)
    {
        try {
            return $this->driver->read($path);
        } catch (UnableToReadFile $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);
        }
    }

    /**
     * Get the contents of a file as decoded JSON.
     *
     * @param  string  $path
     * @param  int  $flags
     * @return array|null
     */
    public function json($path, $flags = 0)
    {
        $content = $this->get($path);

        return is_null($content) ? null : json_decode($content, true, 512, $flags);
    }

    /**
     * Create a streamed response for a given file.
     *
     * @param  string  $path
     * @param  string|null  $name
     * @param  array  $headers
     * @param  string|null  $disposition
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     *
     * @throws UnableToRetrieveMetadata
     */
    public function response($path, $name = null, array $headers = [], $disposition = 'inline')
    {
        $response = new StreamedResponse;

        $headers['Content-Type'] ??= $this->mimeType($path);
        $headers['Content-Length'] ??= $this->size($path);

        if (! array_key_exists('Content-Disposition', $headers)) {
            $filename = $name ?? basename($path);

            $disposition = $response->headers->makeDisposition(
                $disposition, $filename, $this->fallbackName($filename)
            );

            $headers['Content-Disposition'] = $disposition;
        }

        $response->headers->replace($headers);

        $response->setCallback(function () use ($path) {
            $stream = $this->readStream($path);
            fpassthru($stream);
            fclose($stream);
        });

        return $response;
    }

    /**
     * Create a streamed download response for a given file.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $path
     * @param  string|null  $name
     * @param  array  $headers
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     *
     * @throws UnableToRetrieveMetadata
     */
    public function serve(Request $request, $path, $name = null, array $headers = [])
    {
        return isset($this->serveCallback)
            ? call_user_func($this->serveCallback, $request, $path, $headers)
            : $this->response($path, $name, $headers);
    }

    /**
     * Create a streamed download response for a given file.
     *
     * @param  string  $path
     * @param  string|null  $name
     * @param  array  $headers
     * @return \Symfony\Component\HttpFoundation\StreamedResponse
     *
     * @throws UnableToRetrieveMetadata
     */
    public function download($path, $name = null, array $headers = [])
    {
        return $this->response($path, $name, $headers, 'attachment');
    }

    /**
     * Convert the string to ASCII characters that are equivalent to the given name.
     *
     * @param  string  $name
     * @return string
     */
    protected function fallbackName($name)
    {
        return str_replace('%', '', Str::ascii($name));
    }

    /**
     * Write the contents of a file.
     *
     * @param  string  $path
     * @param  \Psr\Http\Message\StreamInterface|\Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|resource  $contents
     * @param  mixed  $options
     * @return string|bool
     */
    public function put($path, $contents, $options = [])
    {
        $options = is_string($options)
            ? ['visibility' => $options]
            : (array) $options;

        // If the given contents is actually a file or uploaded file instance than we will
        // automatically store the file using a stream. This provides a convenient path
        // for the developer to store streams without managing them manually in code.
        if ($contents instanceof File ||
            $contents instanceof UploadedFile) {
            return $this->putFile($path, $contents, $options);
        }

        try {
            if ($contents instanceof StreamInterface) {
                $this->driver->writeStream($path, $contents->detach(), $options);

                return true;
            }

            is_resource($contents)
                ? $this->driver->writeStream($path, $contents, $options)
                : $this->driver->write($path, $contents, $options);
        } catch (UnableToWriteFile|UnableToSetVisibility $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Store the uploaded file on the disk.
     *
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string  $path
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|array|null  $file
     * @param  mixed  $options
     * @return string|false
     */
    public function putFile($path, $file = null, $options = [])
    {
        if (is_null($file) || is_array($file)) {
            [$path, $file, $options] = ['', $path, $file ?? []];
        }

        $file = is_string($file) ? new File($file) : $file;

        return $this->putFileAs($path, $file, $file->hashName(), $options);
    }

    /**
     * Store the uploaded file on the disk with a given name.
     *
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string  $path
     * @param  \Illuminate\Http\File|\Illuminate\Http\UploadedFile|string|array|null  $file
     * @param  string|array|null  $name
     * @param  mixed  $options
     * @return string|false
     */
    public function putFileAs($path, $file, $name = null, $options = [])
    {
        if (is_null($name) || is_array($name)) {
            [$path, $file, $name, $options] = ['', $path, $file, $name ?? []];
        }

        $stream = fopen(is_string($file) ? $file : $file->getRealPath(), 'r');

        // Next, we will format the path of the file and store the file using a stream since
        // they provide better performance than alternatives. Once we write the file this
        // stream will get closed automatically by us so the developer doesn't have to.
        $result = $this->put(
            $path = trim($path.'/'.$name, '/'), $stream, $options
        );

        if (is_resource($stream)) {
            fclose($stream);
        }

        return $result ? $path : false;
    }

    /**
     * Get the visibility for the given path.
     *
     * @param  string  $path
     * @return string
     */
    public function getVisibility($path)
    {
        if ($this->driver->visibility($path) == Visibility::PUBLIC) {
            return FilesystemContract::VISIBILITY_PUBLIC;
        }

        return FilesystemContract::VISIBILITY_PRIVATE;
    }

    /**
     * Set the visibility for the given path.
     *
     * @param  string  $path
     * @param  string  $visibility
     * @return bool
     */
    public function setVisibility($path, $visibility)
    {
        try {
            $this->driver->setVisibility($path, $this->parseVisibility($visibility));
        } catch (UnableToSetVisibility $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Prepend to a file.
     *
     * @param  string  $path
     * @param  string  $data
     * @param  string  $separator
     * @return bool
     */
    public function prepend($path, $data, $separator = PHP_EOL)
    {
        if ($this->fileExists($path)) {
            return $this->put($path, $data.$separator.$this->get($path));
        }

        return $this->put($path, $data);
    }

    /**
     * Append to a file.
     *
     * @param  string  $path
     * @param  string  $data
     * @param  string  $separator
     * @return bool
     */
    public function append($path, $data, $separator = PHP_EOL)
    {
        if ($this->fileExists($path)) {
            return $this->put($path, $this->get($path).$separator.$data);
        }

        return $this->put($path, $data);
    }

    /**
     * Delete the file at a given path.
     *
     * @param  string|array  $paths
     * @return bool
     */
    public function delete($paths)
    {
        $paths = is_array($paths) ? $paths : func_get_args();

        $success = true;

        foreach ($paths as $path) {
            try {
                $this->driver->delete($path);
            } catch (UnableToDeleteFile $e) {
                throw_if($this->throwsExceptions(), $e);

                $this->report($e);

                $success = false;
            }
        }

        return $success;
    }

    /**
     * Copy a file to a new location.
     *
     * @param  string  $from
     * @param  string  $to
     * @return bool
     */
    public function copy($from, $to)
    {
        try {
            $this->driver->copy($from, $to);
        } catch (UnableToCopyFile $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Move a file to a new location.
     *
     * @param  string  $from
     * @param  string  $to
     * @return bool
     */
    public function move($from, $to)
    {
        try {
            $this->driver->move($from, $to);
        } catch (UnableToMoveFile $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Get the file size of a given file.
     *
     * @param  string  $path
     * @return int
     */
    public function size($path)
    {
        return $this->driver->fileSize($path);
    }

    /**
     * Get the checksum for a file.
     *
     * @return string|false
     *
     * @throws UnableToProvideChecksum
     */
    public function checksum(string $path, array $options = [])
    {
        try {
            return $this->driver->checksum($path, $options);
        } catch (UnableToProvideChecksum $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }
    }

    /**
     * Get the mime-type of a given file.
     *
     * @param  string  $path
     * @return string|false
     *
     * @throws UnableToRetrieveMetadata
     */
    public function mimeType($path)
    {
        try {
            return $this->driver->mimeType($path);
        } catch (UnableToRetrieveMetadata $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);
        }

        return false;
    }

    /**
     * Get the file's last modification time.
     *
     * @param  string  $path
     * @return int
     */
    public function lastModified($path)
    {
        return $this->driver->lastModified($path);
    }

    /**
     * {@inheritdoc}
     */
    public function readStream($path)
    {
        try {
            return $this->driver->readStream($path);
        } catch (UnableToReadFile $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function writeStream($path, $resource, array $options = [])
    {
        try {
            $this->driver->writeStream($path, $resource, $options);
        } catch (UnableToWriteFile|UnableToSetVisibility $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Get the URL for the file at the given path.
     *
     * @param  string  $path
     * @return string
     *
     * @throws \RuntimeException
     */
    public function url($path)
    {
        if (isset($this->config['prefix'])) {
            $path = $this->concatPathToUrl($this->config['prefix'], $path);
        }

        $adapter = $this->adapter;

        if (method_exists($adapter, 'getUrl')) {
            return $adapter->getUrl($path);
        } elseif (method_exists($this->driver, 'getUrl')) {
            return $this->driver->getUrl($path);
        } elseif ($adapter instanceof FtpAdapter || $adapter instanceof SftpAdapter) {
            return $this->getFtpUrl($path);
        } elseif ($adapter instanceof LocalAdapter) {
            return $this->getLocalUrl($path);
        } else {
            throw new RuntimeException('This driver does not support retrieving URLs.');
        }
    }

    /**
     * Get the URL for the file at the given path.
     *
     * @param  string  $path
     * @return string
     */
    protected function getFtpUrl($path)
    {
        return isset($this->config['url'])
            ? $this->concatPathToUrl($this->config['url'], $path)
            : $path;
    }

    /**
     * Get the URL for the file at the given path.
     *
     * @param  string  $path
     * @return string
     */
    protected function getLocalUrl($path)
    {
        // If an explicit base URL has been set on the disk configuration then we will use
        // it as the base URL instead of the default path. This allows the developer to
        // have full control over the base path for this filesystem's generated URLs.
        if (isset($this->config['url'])) {
            return $this->concatPathToUrl($this->config['url'], $path);
        }

        $path = '/storage/'.$path;

        // If the path contains "storage/public", it probably means the developer is using
        // the default disk to generate the path instead of the "public" disk like they
        // are really supposed to use. We will remove the public from this path here.
        if (str_contains($path, '/storage/public/')) {
            return Str::replaceFirst('/public/', '/', $path);
        }

        return $path;
    }

    /**
     * Determine if temporary URLs can be generated.
     *
     * @return bool
     */
    public function providesTemporaryUrls()
    {
        return method_exists($this->adapter, 'getTemporaryUrl') || isset($this->temporaryUrlCallback);
    }

    /**
     * Determine if temporary upload URLs can be generated.
     *
     * @return bool
     */
    public function providesTemporaryUploadUrls()
    {
        return method_exists($this->adapter, 'temporaryUploadUrl') || isset($this->temporaryUploadUrlCallback);
    }

    /**
     * Get a temporary URL for the file at the given path.
     *
     * @param  string  $path
     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return string
     *
     * @throws \RuntimeException
     */
    public function temporaryUrl($path, $expiration, array $options = [])
    {
        if (method_exists($this->adapter, 'getTemporaryUrl')) {
            return $this->adapter->getTemporaryUrl($path, $expiration, $options);
        }

        if ($this->temporaryUrlCallback) {
            return $this->temporaryUrlCallback->bindTo($this, static::class)(
                $path, $expiration, $options
            );
        }

        throw new RuntimeException('This driver does not support creating temporary URLs.');
    }

    /**
     * Get a temporary upload URL for the file at the given path.
     *
     * @param  string  $path
     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return array
     *
     * @throws \RuntimeException
     */
    public function temporaryUploadUrl($path, $expiration, array $options = [])
    {
        if (method_exists($this->adapter, 'temporaryUploadUrl')) {
            return $this->adapter->temporaryUploadUrl($path, $expiration, $options);
        }

        if ($this->temporaryUploadUrlCallback) {
            return $this->temporaryUploadUrlCallback->bindTo($this, static::class)(
                $path, $expiration, $options
            );
        }

        throw new RuntimeException('This driver does not support creating temporary upload URLs.');
    }

    /**
     * Concatenate a path to a URL.
     *
     * @param  string  $url
     * @param  string  $path
     * @return string
     */
    protected function concatPathToUrl($url, $path)
    {
        return rtrim($url, '/').'/'.ltrim($path, '/');
    }

    /**
     * Replace the scheme, host and port of the given UriInterface with values from the given URL.
     *
     * @param  \Psr\Http\Message\UriInterface  $uri
     * @param  string  $url
     * @return \Psr\Http\Message\UriInterface
     */
    protected function replaceBaseUrl($uri, $url)
    {
        $parsed = parse_url($url);

        return $uri
            ->withScheme($parsed['scheme'])
            ->withHost($parsed['host'])
            ->withPort($parsed['port'] ?? null);
    }

    /**
     * Get an array of all files in a directory.
     *
     * @param  string|null  $directory
     * @param  bool  $recursive
     * @return array
     */
    public function files($directory = null, $recursive = false)
    {
        return $this->driver->listContents($directory ?? '', $recursive)
            ->filter(function (StorageAttributes $attributes) {
                return $attributes->isFile();
            })
            ->sortByPath()
            ->map(function (StorageAttributes $attributes) {
                return $attributes->path();
            })
            ->toArray();
    }

    /**
     * Get all of the files from the given directory (recursive).
     *
     * @param  string|null  $directory
     * @return array
     */
    public function allFiles($directory = null)
    {
        return $this->files($directory, true);
    }

    /**
     * Get all of the directories within a given directory.
     *
     * @param  string|null  $directory
     * @param  bool  $recursive
     * @return array
     */
    public function directories($directory = null, $recursive = false)
    {
        return $this->driver->listContents($directory ?? '', $recursive)
            ->filter(function (StorageAttributes $attributes) {
                return $attributes->isDir();
            })
            ->map(function (StorageAttributes $attributes) {
                return $attributes->path();
            })
            ->toArray();
    }

    /**
     * Get all the directories within a given directory (recursive).
     *
     * @param  string|null  $directory
     * @return array
     */
    public function allDirectories($directory = null)
    {
        return $this->directories($directory, true);
    }

    /**
     * Create a directory.
     *
     * @param  string  $path
     * @return bool
     */
    public function makeDirectory($path)
    {
        try {
            $this->driver->createDirectory($path);
        } catch (UnableToCreateDirectory|UnableToSetVisibility $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Recursively delete a directory.
     *
     * @param  string  $directory
     * @return bool
     */
    public function deleteDirectory($directory)
    {
        try {
            $this->driver->deleteDirectory($directory);
        } catch (UnableToDeleteDirectory $e) {
            throw_if($this->throwsExceptions(), $e);

            $this->report($e);

            return false;
        }

        return true;
    }

    /**
     * Get the Flysystem driver.
     *
     * @return \League\Flysystem\FilesystemOperator
     */
    public function getDriver()
    {
        return $this->driver;
    }

    /**
     * Get the Flysystem adapter.
     *
     * @return \League\Flysystem\FilesystemAdapter
     */
    public function getAdapter()
    {
        return $this->adapter;
    }

    /**
     * Get the configuration values.
     *
     * @return array
     */
    public function getConfig()
    {
        return $this->config;
    }

    /**
     * Parse the given visibility value.
     *
     * @param  string|null  $visibility
     * @return string|null
     *
     * @throws \InvalidArgumentException
     */
    protected function parseVisibility($visibility)
    {
        if (is_null($visibility)) {
            return;
        }

        return match ($visibility) {
            FilesystemContract::VISIBILITY_PUBLIC => Visibility::PUBLIC,
            FilesystemContract::VISIBILITY_PRIVATE => Visibility::PRIVATE,
            default => throw new InvalidArgumentException("Unknown visibility: {$visibility}."),
        };
    }

    /**
     * Define a custom callback that generates file download responses.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public function serveUsing(Closure $callback)
    {
        $this->serveCallback = $callback;
    }

    /**
     * Define a custom temporary URL builder callback.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public function buildTemporaryUrlsUsing(Closure $callback)
    {
        $this->temporaryUrlCallback = $callback;
    }

    /**
     * Define a custom temporary upload URL builder callback.
     *
     * @param  \Closure  $callback
     * @return void
     */
    public function buildTemporaryUploadUrlsUsing(Closure $callback)
    {
        $this->temporaryUploadUrlCallback = $callback;
    }

    /**
     * Determine if Flysystem exceptions should be thrown.
     *
     * @return bool
     */
    protected function throwsExceptions(): bool
    {
        return (bool) ($this->config['throw'] ?? false);
    }

    /**
     * Report the exception.
     *
     * @param  \Throwable  $exception
     * @return void
     *
     * @throws \Throwable
     */
    protected function report($exception)
    {
        if ($this->shouldReport() && Container::getInstance()->bound(ExceptionHandler::class)) {
            Container::getInstance()->make(ExceptionHandler::class)->report($exception);
        }
    }

    /**
     * Determine if Flysystem exceptions should be reported.
     *
     * @return bool
     */
    protected function shouldReport(): bool
    {
        return (bool) ($this->config['report'] ?? false);
    }

    /**
     * Pass dynamic methods call onto Flysystem.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public function __call($method, $parameters)
    {
        if (static::hasMacro($method)) {
            return $this->macroCall($method, $parameters);
        }

        return $this->driver->{$method}(...$parameters);
    }
}
<?php

namespace Illuminate\Filesystem;

use Illuminate\Contracts\Foundation\CachesRoutes;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use InvalidArgumentException;

class FilesystemServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the filesystem.
     *
     * @return void
     */
    public function boot()
    {
        $this->serveFiles();
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerNativeFilesystem();
        $this->registerFlysystem();
    }

    /**
     * Register the native filesystem implementation.
     *
     * @return void
     */
    protected function registerNativeFilesystem()
    {
        $this->app->singleton('files', function () {
            return new Filesystem;
        });
    }

    /**
     * Register the driver based filesystem.
     *
     * @return void
     */
    protected function registerFlysystem()
    {
        $this->registerManager();

        $this->app->singleton('filesystem.disk', function ($app) {
            return $app['filesystem']->disk($this->getDefaultDriver());
        });

        $this->app->singleton('filesystem.cloud', function ($app) {
            return $app['filesystem']->disk($this->getCloudDriver());
        });
    }

    /**
     * Register the filesystem manager.
     *
     * @return void
     */
    protected function registerManager()
    {
        $this->app->singleton('filesystem', function ($app) {
            return new FilesystemManager($app);
        });
    }

    /**
     * Register protected file serving.
     *
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    protected function serveFiles()
    {
        if ($this->app instanceof CachesRoutes && $this->app->routesAreCached()) {
            return;
        }

        $served = [];

        foreach ($this->app['config']['filesystems.disks'] ?? [] as $disk => $config) {
            if (! $this->shouldServeFiles($config)) {
                continue;
            }

            $this->app->booted(function ($app) use ($disk, $config, &$served) {
                $uri = isset($config['url'])
                    ? rtrim(parse_url($config['url'])['path'], '/')
                    : '/storage';

                if (isset($served[$uri])) {
                    throw new InvalidArgumentException(
                        "The [{$disk}] disk conflicts with the [{$served[$uri]}] disk at [{$uri}]. Each served disk must have a unique URL."
                    );
                }

                $served[$uri] = $disk;

                $isProduction = $app->isProduction();

                Route::get($uri.'/{path}', function (Request $request, string $path) use ($disk, $config, $isProduction) {
                    return (new ServeFile(
                        $disk,
                        $config,
                        $isProduction
                    ))($request, $path);
                })->where('path', '.*')->name('storage.'.$disk);

                Route::put($uri.'/{path}', function (Request $request, string $path) use ($disk, $config, $isProduction) {
                    return (new ReceiveFile(
                        $disk,
                        $config,
                        $isProduction
                    ))($request, $path);
                })->where('path', '.*')->name('storage.'.$disk.'.upload');
            });
        }
    }

    /**
     * Determine if the disk is serveable.
     *
     * @param  array  $config
     * @return bool
     */
    protected function shouldServeFiles(array $config)
    {
        return $config['driver'] === 'local' && ($config['serve'] ?? false);
    }

    /**
     * Get the default file driver.
     *
     * @return string
     */
    protected function getDefaultDriver()
    {
        return $this->app['config']['filesystems.default'];
    }

    /**
     * Get the default cloud based file driver.
     *
     * @return string
     */
    protected function getCloudDriver()
    {
        return $this->app['config']['filesystems.cloud'];
    }
}
<?php

namespace Illuminate\Filesystem;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\PathTraversalDetected;

class ServeFile
{
    /**
     * Create a new invokable controller to serve files.
     */
    public function __construct(
        protected string $disk,
        protected array $config,
        protected bool $isProduction,
    ) {
        //
    }

    /**
     * Handle the incoming request.
     */
    public function __invoke(Request $request, string $path)
    {
        abort_unless(
            $this->hasValidSignature($request),
            $this->isProduction ? 404 : 403
        );
        try {
            abort_unless(Storage::disk($this->disk)->exists($path), 404);

            $headers = [
                'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
                'Content-Security-Policy' => "default-src 'none'; style-src 'unsafe-inline'; sandbox",
            ];

            return tap(
                Storage::disk($this->disk)->serve($request, $path, headers: $headers),
                function ($response) use ($headers) {
                    if (! $response->headers->has('Content-Security-Policy')) {
                        $response->headers->replace($headers);
                    }
                }
            );
        } catch (PathTraversalDetected) {
            abort(404);
        }
    }

    /**
     * Determine if the request has a valid signature if applicable.
     */
    protected function hasValidSignature(Request $request): bool
    {
        return ! $request->boolean('upload') && (
            ($this->config['visibility'] ?? 'private') === 'public' ||
            $request->hasValidRelativeSignature()
        );
    }
}
<?php

namespace Illuminate\Filesystem;

use Illuminate\Contracts\Filesystem\LockTimeoutException;

class LockableFile
{
    /**
     * The file resource.
     *
     * @var resource
     */
    protected $handle;

    /**
     * The file path.
     *
     * @var string
     */
    protected $path;

    /**
     * Indicates if the file is locked.
     *
     * @var bool
     */
    protected $isLocked = false;

    /**
     * Create a new File instance.
     *
     * @param  string  $path
     * @param  string  $mode
     */
    public function __construct($path, $mode)
    {
        $this->path = $path;

        $this->ensureDirectoryExists($path);
        $this->createResource($path, $mode);
    }

    /**
     * Create the file's directory if necessary.
     *
     * @param  string  $path
     * @return void
     */
    protected function ensureDirectoryExists($path)
    {
        if (! file_exists(dirname($path))) {
            @mkdir(dirname($path), 0777, true);
        }
    }

    /**
     * Create the file resource.
     *
     * @param  string  $path
     * @param  string  $mode
     * @return void
     *
     * @throws \Exception
     */
    protected function createResource($path, $mode)
    {
        $this->handle = fopen($path, $mode);
    }

    /**
     * Read the file contents.
     *
     * @param  int|null  $length
     * @return string
     */
    public function read($length = null)
    {
        clearstatcache(true, $this->path);

        return fread($this->handle, $length ?? ($this->size() ?: 1));
    }

    /**
     * Get the file size.
     *
     * @return int
     */
    public function size()
    {
        return filesize($this->path);
    }

    /**
     * Write to the file.
     *
     * @param  string  $contents
     * @return $this
     */
    public function write($contents)
    {
        fwrite($this->handle, $contents);

        fflush($this->handle);

        return $this;
    }

    /**
     * Truncate the file.
     *
     * @return $this
     */
    public function truncate()
    {
        rewind($this->handle);

        ftruncate($this->handle, 0);

        return $this;
    }

    /**
     * Get a shared lock on the file.
     *
     * @param  bool  $block
     * @return $this
     *
     * @throws \Illuminate\Contracts\Filesystem\LockTimeoutException
     */
    public function getSharedLock($block = false)
    {
        if (! flock($this->handle, LOCK_SH | ($block ? 0 : LOCK_NB))) {
            throw new LockTimeoutException("Unable to acquire file lock at path [{$this->path}].");
        }

        $this->isLocked = true;

        return $this;
    }

    /**
     * Get an exclusive lock on the file.
     *
     * @param  bool  $block
     * @return $this
     *
     * @throws \Illuminate\Contracts\Filesystem\LockTimeoutException
     */
    public function getExclusiveLock($block = false)
    {
        if (! flock($this->handle, LOCK_EX | ($block ? 0 : LOCK_NB))) {
            throw new LockTimeoutException("Unable to acquire file lock at path [{$this->path}].");
        }

        $this->isLocked = true;

        return $this;
    }

    /**
     * Release the lock on the file.
     *
     * @return $this
     */
    public function releaseLock()
    {
        flock($this->handle, LOCK_UN);

        $this->isLocked = false;

        return $this;
    }

    /**
     * Close the file.
     *
     * @return bool
     */
    public function close()
    {
        if ($this->isLocked) {
            $this->releaseLock();
        }

        return fclose($this->handle);
    }
}
<?php

namespace Illuminate\Filesystem;

use Aws\S3\S3Client;
use Illuminate\Support\Traits\Conditionable;
use League\Flysystem\FilesystemAdapter as FlysystemAdapter;
use League\Flysystem\FilesystemOperator;

class AwsS3V3Adapter extends FilesystemAdapter
{
    use Conditionable;

    /**
     * The AWS S3 client.
     *
     * @var \Aws\S3\S3Client
     */
    protected $client;

    /**
     * Create a new AwsS3V3FilesystemAdapter instance.
     *
     * @param  \League\Flysystem\FilesystemOperator  $driver
     * @param  \League\Flysystem\FilesystemAdapter  $adapter
     * @param  array  $config
     * @param  \Aws\S3\S3Client  $client
     */
    public function __construct(FilesystemOperator $driver, FlysystemAdapter $adapter, array $config, S3Client $client)
    {
        $config['directory_separator'] = '/';

        parent::__construct($driver, $adapter, $config);

        $this->client = $client;
    }

    /**
     * Get the URL for the file at the given path.
     *
     * @param  string  $path
     * @return string
     *
     * @throws \RuntimeException
     */
    public function url($path)
    {
        // If an explicit base URL has been set on the disk configuration then we will use
        // it as the base URL instead of the default path. This allows the developer to
        // have full control over the base path for this filesystem's generated URLs.
        if (isset($this->config['url'])) {
            return $this->concatPathToUrl($this->config['url'], $this->prefixer->prefixPath($path));
        }

        return $this->client->getObjectUrl(
            $this->config['bucket'], $this->prefixer->prefixPath($path)
        );
    }

    /**
     * Determine if temporary URLs can be generated.
     *
     * @return bool
     */
    public function providesTemporaryUrls()
    {
        return true;
    }

    /**
     * Get a temporary URL for the file at the given path.
     *
     * @param  string  $path
     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return string
     */
    public function temporaryUrl($path, $expiration, array $options = [])
    {
        $command = $this->client->getCommand('GetObject', array_merge([
            'Bucket' => $this->config['bucket'],
            'Key' => $this->prefixer->prefixPath($path),
        ], $options));

        $uri = $this->client->createPresignedRequest(
            $command, $expiration, $options
        )->getUri();

        // If an explicit base URL has been set on the disk configuration then we will use
        // it as the base URL instead of the default path. This allows the developer to
        // have full control over the base path for this filesystem's generated URLs.
        if (isset($this->config['temporary_url'])) {
            $uri = $this->replaceBaseUrl($uri, $this->config['temporary_url']);
        }

        return (string) $uri;
    }

    /**
     * Get a temporary upload URL for the file at the given path.
     *
     * @param  string  $path
     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return array
     */
    public function temporaryUploadUrl($path, $expiration, array $options = [])
    {
        $command = $this->client->getCommand('PutObject', array_merge([
            'Bucket' => $this->config['bucket'],
            'Key' => $this->prefixer->prefixPath($path),
        ], $options));

        $signedRequest = $this->client->createPresignedRequest(
            $command, $expiration, $options
        );

        $uri = $signedRequest->getUri();

        // If an explicit base URL has been set on the disk configuration then we will use
        // it as the base URL instead of the default path. This allows the developer to
        // have full control over the base path for this filesystem's generated URLs.
        if (isset($this->config['temporary_url'])) {
            $uri = $this->replaceBaseUrl($uri, $this->config['temporary_url']);
        }

        return [
            'url' => (string) $uri,
            'headers' => $signedRequest->getHeaders(),
        ];
    }

    /**
     * Get the underlying S3 client.
     *
     * @return \Aws\S3\S3Client
     */
    public function getClient()
    {
        return $this->client;
    }
}
<?php

namespace Illuminate\Filesystem;

use Closure;
use Illuminate\Support\Traits\Conditionable;
use RuntimeException;

class LocalFilesystemAdapter extends FilesystemAdapter
{
    use Conditionable;

    /**
     * The name of the filesystem disk.
     *
     * @var string
     */
    protected $disk;

    /**
     * Indicates if signed URLs should serve corresponding files.
     *
     * @var bool
     */
    protected $shouldServeSignedUrls = false;

    /**
     * The Closure that should be used to resolve the URL generator.
     *
     * @var \Closure
     */
    protected $urlGeneratorResolver;

    /**
     * Determine if temporary URLs can be generated.
     *
     * @return bool
     */
    public function providesTemporaryUrls()
    {
        return $this->temporaryUrlCallback || (
            $this->shouldServeSignedUrls && $this->urlGeneratorResolver instanceof Closure
        );
    }

    /**
     * Determine if temporary upload URLs can be generated.
     *
     * @return bool
     */
    public function providesTemporaryUploadUrls()
    {
        return $this->temporaryUploadUrlCallback || (
            $this->shouldServeSignedUrls && $this->urlGeneratorResolver instanceof Closure
        );
    }

    /**
     * Get a temporary URL for the file at the given path.
     *
     * @param  string  $path
     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return string
     *
     * @throws \RuntimeException
     */
    public function temporaryUrl($path, $expiration, array $options = [])
    {
        if ($this->temporaryUrlCallback) {
            return $this->temporaryUrlCallback->bindTo($this, static::class)(
                $path, $expiration, $options
            );
        }

        if (! $this->providesTemporaryUrls()) {
            throw new RuntimeException('This driver does not support creating temporary URLs.');
        }

        $url = call_user_func($this->urlGeneratorResolver);

        return $url->to($url->temporarySignedRoute(
            'storage.'.$this->disk,
            $expiration,
            ['path' => $path],
            absolute: false
        ));
    }

    /**
     * Get a temporary upload URL for the file at the given path.
     *
     * @param  string  $path
     * @param  \DateTimeInterface  $expiration
     * @param  array  $options
     * @return array
     *
     * @throws \RuntimeException
     */
    public function temporaryUploadUrl($path, $expiration, array $options = [])
    {
        if ($this->temporaryUploadUrlCallback) {
            return $this->temporaryUploadUrlCallback->bindTo($this, static::class)(
                $path, $expiration, $options
            );
        }

        if (! $this->providesTemporaryUploadUrls()) {
            throw new RuntimeException('This driver does not support creating temporary upload URLs.');
        }

        $url = call_user_func($this->urlGeneratorResolver);

        return [
            'url' => $url->to($url->temporarySignedRoute(
                'storage.'.$this->disk.'.upload',
                $expiration,
                ['path' => $path, 'upload' => true],
                absolute: false
            )),
            'headers' => [],
        ];
    }

    /**
     * Specify the name of the disk the adapter is managing.
     *
     * @param  string  $disk
     * @return $this
     */
    public function diskName(string $disk)
    {
        $this->disk = $disk;

        return $this;
    }

    /**
     * Indicate that signed URLs should serve the corresponding files.
     *
     * @param  bool  $serve
     * @param  \Closure|null  $urlGeneratorResolver
     * @return $this
     */
    public function shouldServeSignedUrls(bool $serve = true, ?Closure $urlGeneratorResolver = null)
    {
        $this->shouldServeSignedUrls = $serve;
        $this->urlGeneratorResolver = $urlGeneratorResolver;

        return $this;
    }
}
<?php

namespace Illuminate\Filesystem;

use ErrorException;
use FilesystemIterator;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Macroable;
use RuntimeException;
use SplFileObject;
use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Mime\MimeTypes;

class Filesystem
{
    use Conditionable, Macroable;

    /**
     * Determine if a file or directory exists.
     *
     * @param  string  $path
     * @return bool
     */
    public function exists($path)
    {
        return file_exists($path);
    }

    /**
     * Determine if a file or directory is missing.
     *
     * @param  string  $path
     * @return bool
     */
    public function missing($path)
    {
        return ! $this->exists($path);
    }

    /**
     * Get the contents of a file.
     *
     * @param  string  $path
     * @param  bool  $lock
     * @return string
     *
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public function get($path, $lock = false)
    {
        if ($this->isFile($path)) {
            return $lock ? $this->sharedGet($path) : file_get_contents($path);
        }

        throw new FileNotFoundException("File does not exist at path {$path}.");
    }

    /**
     * Get the contents of a file as decoded JSON.
     *
     * @param  string  $path
     * @param  int  $flags
     * @param  bool  $lock
     * @return array
     *
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public function json($path, $flags = 0, $lock = false)
    {
        return json_decode($this->get($path, $lock), true, 512, $flags);
    }

    /**
     * Get contents of a file with shared access.
     *
     * @param  string  $path
     * @return string
     */
    public function sharedGet($path)
    {
        $contents = '';

        $handle = fopen($path, 'rb');

        if ($handle) {
            try {
                if (flock($handle, LOCK_SH)) {
                    clearstatcache(true, $path);

                    $contents = stream_get_contents($handle);

                    flock($handle, LOCK_UN);
                }
            } finally {
                fclose($handle);
            }
        }

        return $contents;
    }

    /**
     * Get the returned value of a file.
     *
     * @param  string  $path
     * @param  array  $data
     * @return mixed
     *
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public function getRequire($path, array $data = [])
    {
        if ($this->isFile($path)) {
            $__path = $path;
            $__data = $data;

            return (static function () use ($__path, $__data) {
                extract($__data, EXTR_SKIP);

                return require $__path;
            })();
        }

        throw new FileNotFoundException("File does not exist at path {$path}.");
    }

    /**
     * Require the given file once.
     *
     * @param  string  $path
     * @param  array  $data
     * @return mixed
     *
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public function requireOnce($path, array $data = [])
    {
        if ($this->isFile($path)) {
            $__path = $path;
            $__data = $data;

            return (static function () use ($__path, $__data) {
                extract($__data, EXTR_SKIP);

                return require_once $__path;
            })();
        }

        throw new FileNotFoundException("File does not exist at path {$path}.");
    }

    /**
     * Get the contents of a file one line at a time.
     *
     * @param  string  $path
     * @return \Illuminate\Support\LazyCollection
     *
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public function lines($path)
    {
        if (! $this->isFile($path)) {
            throw new FileNotFoundException(
                "File does not exist at path {$path}."
            );
        }

        return new LazyCollection(function () use ($path) {
            $file = new SplFileObject($path);

            $file->setFlags(SplFileObject::DROP_NEW_LINE);

            while (! $file->eof()) {
                yield $file->fgets();
            }
        });
    }

    /**
     * Get the hash of the file at the given path.
     *
     * @param  string  $path
     * @param  string  $algorithm
     * @return string|false
     */
    public function hash($path, $algorithm = 'md5')
    {
        return hash_file($algorithm, $path);
    }

    /**
     * Write the contents of a file.
     *
     * @param  string  $path
     * @param  string  $contents
     * @param  bool  $lock
     * @return int|bool
     */
    public function put($path, $contents, $lock = false)
    {
        return file_put_contents($path, $contents, $lock ? LOCK_EX : 0);
    }

    /**
     * Write the contents of a file, replacing it atomically if it already exists.
     *
     * @param  string  $path
     * @param  string  $content
     * @param  int|null  $mode
     * @return void
     */
    public function replace($path, $content, $mode = null)
    {
        // If the path already exists and is a symlink, get the real path...
        clearstatcache(true, $path);

        $path = realpath($path) ?: $path;

        $tempPath = tempnam(dirname($path), basename($path));

        // Fix permissions of tempPath because `tempnam()` creates it with permissions set to 0600...
        if (! is_null($mode)) {
            @chmod($tempPath, $mode);
        } else {
            @chmod($tempPath, 0777 - umask());
        }

        file_put_contents($tempPath, $content);

        rename($tempPath, $path);
    }

    /**
     * Replace a given string within a given file.
     *
     * @param  array|string  $search
     * @param  array|string  $replace
     * @param  string  $path
     * @return void
     */
    public function replaceInFile($search, $replace, $path)
    {
        file_put_contents($path, str_replace($search, $replace, file_get_contents($path)));
    }

    /**
     * Prepend to a file.
     *
     * @param  string  $path
     * @param  string  $data
     * @return int
     */
    public function prepend($path, $data)
    {
        if ($this->exists($path)) {
            return $this->put($path, $data.$this->get($path));
        }

        return $this->put($path, $data);
    }

    /**
     * Append to a file.
     *
     * @param  string  $path
     * @param  string  $data
     * @param  bool  $lock
     * @return int
     */
    public function append($path, $data, $lock = false)
    {
        return file_put_contents($path, $data, FILE_APPEND | ($lock ? LOCK_EX : 0));
    }

    /**
     * Get or set UNIX mode of a file or directory.
     *
     * @param  string  $path
     * @param  int|null  $mode
     * @return mixed
     */
    public function chmod($path, $mode = null)
    {
        if ($mode) {
            return chmod($path, $mode);
        }

        return substr(sprintf('%o', fileperms($path)), -4);
    }

    /**
     * Delete the file at a given path.
     *
     * @param  string|array  $paths
     * @return bool
     */
    public function delete($paths)
    {
        $paths = is_array($paths) ? $paths : func_get_args();

        $success = true;

        foreach ($paths as $path) {
            try {
                if (@unlink($path)) {
                    clearstatcache(false, $path);
                } else {
                    $success = false;
                }
            } catch (ErrorException) {
                $success = false;
            }
        }

        return $success;
    }

    /**
     * Move a file to a new location.
     *
     * @param  string  $path
     * @param  string  $target
     * @return bool
     */
    public function move($path, $target)
    {
        return rename($path, $target);
    }

    /**
     * Copy a file to a new location.
     *
     * @param  string  $path
     * @param  string  $target
     * @return bool
     */
    public function copy($path, $target)
    {
        return copy($path, $target);
    }

    /**
     * Create a symlink to the target file or directory. On Windows, a hard link is created if the target is a file.
     *
     * @param  string  $target
     * @param  string  $link
     * @return bool|null
     */
    public function link($target, $link)
    {
        if (! windows_os()) {
            if (function_exists('symlink')) {
                return symlink($target, $link);
            } else {
                return exec('ln -s '.escapeshellarg($target).' '.escapeshellarg($link)) !== false;
            }
        }

        $mode = $this->isDirectory($target) ? 'J' : 'H';

        exec("mklink /{$mode} ".escapeshellarg($link).' '.escapeshellarg($target));
    }

    /**
     * Create a relative symlink to the target file or directory.
     *
     * @param  string  $target
     * @param  string  $link
     * @return void
     *
     * @throws \RuntimeException
     */
    public function relativeLink($target, $link)
    {
        if (! class_exists(SymfonyFilesystem::class)) {
            throw new RuntimeException(
                'To enable support for relative links, please install the symfony/filesystem package.'
            );
        }

        $relativeTarget = (new SymfonyFilesystem)->makePathRelative($target, dirname($link));

        $this->link($this->isFile($target) ? rtrim($relativeTarget, '/') : $relativeTarget, $link);
    }

    /**
     * Extract the file name from a file path.
     *
     * @param  string  $path
     * @return string
     */
    public function name($path)
    {
        return pathinfo($path, PATHINFO_FILENAME);
    }

    /**
     * Extract the trailing name component from a file path.
     *
     * @param  string  $path
     * @return string
     */
    public function basename($path)
    {
        return pathinfo($path, PATHINFO_BASENAME);
    }

    /**
     * Extract the parent directory from a file path.
     *
     * @param  string  $path
     * @return string
     */
    public function dirname($path)
    {
        return pathinfo($path, PATHINFO_DIRNAME);
    }

    /**
     * Extract the file extension from a file path.
     *
     * @param  string  $path
     * @return string
     */
    public function extension($path)
    {
        return pathinfo($path, PATHINFO_EXTENSION);
    }

    /**
     * Guess the file extension from the MIME type of a given file.
     *
     * @param  string  $path
     * @return string|null
     *
     * @throws \RuntimeException
     */
    public function guessExtension($path)
    {
        if (! class_exists(MimeTypes::class)) {
            throw new RuntimeException(
                'To enable support for guessing extensions, please install the symfony/mime package.'
            );
        }

        return (new MimeTypes)->getExtensions($this->mimeType($path))[0] ?? null;
    }

    /**
     * Get the file type of a given file.
     *
     * @param  string  $path
     * @return string|false
     */
    public function type($path)
    {
        return filetype($path);
    }

    /**
     * Get the MIME type of a given file.
     *
     * @param  string  $path
     * @return string|false
     */
    public function mimeType($path)
    {
        return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);
    }

    /**
     * Get the file size of a given file.
     *
     * @param  string  $path
     * @return int
     */
    public function size($path)
    {
        return filesize($path);
    }

    /**
     * Get the file's last modification time.
     *
     * @param  string  $path
     * @return int
     */
    public function lastModified($path)
    {
        return filemtime($path);
    }

    /**
     * Determine if the given path is a directory.
     *
     * @param  string  $directory
     * @return bool
     */
    public function isDirectory($directory)
    {
        return is_dir($directory);
    }

    /**
     * Determine if the given path is a directory that does not contain any other files or directories.
     *
     * @param  string  $directory
     * @param  bool  $ignoreDotFiles
     * @return bool
     */
    public function isEmptyDirectory($directory, $ignoreDotFiles = false)
    {
        return ! Finder::create()->ignoreDotFiles($ignoreDotFiles)->in($directory)->depth(0)->hasResults();
    }

    /**
     * Determine if the given path is readable.
     *
     * @param  string  $path
     * @return bool
     */
    public function isReadable($path)
    {
        return is_readable($path);
    }

    /**
     * Determine if the given path is writable.
     *
     * @param  string  $path
     * @return bool
     */
    public function isWritable($path)
    {
        return is_writable($path);
    }

    /**
     * Determine if two files are the same by comparing their hashes.
     *
     * @param  string  $firstFile
     * @param  string  $secondFile
     * @return bool
     */
    public function hasSameHash($firstFile, $secondFile)
    {
        $hash = @hash_file('xxh128', $firstFile);

        return $hash && hash_equals($hash, (string) @hash_file('xxh128', $secondFile));
    }

    /**
     * Determine if the given path is a file.
     *
     * @param  string  $file
     * @return bool
     */
    public function isFile($file)
    {
        return is_file($file);
    }

    /**
     * Find path names matching a given pattern.
     *
     * @param  string  $pattern
     * @param  int  $flags
     * @return array
     */
    public function glob($pattern, $flags = 0)
    {
        return glob($pattern, $flags);
    }

    /**
     * Get an array of all files in a directory.
     *
     * @param  string  $directory
     * @param  bool  $hidden
     * @return \Symfony\Component\Finder\SplFileInfo[]
     */
    public function files($directory, $hidden = false, array|string|int $depth = 0)
    {
        return iterator_to_array(
            Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->depth($depth)->sortByName(),
            false
        );
    }

    /**
     * Get all of the files from the given directory (recursive).
     *
     * @param  string  $directory
     * @param  bool  $hidden
     * @return \Symfony\Component\Finder\SplFileInfo[]
     */
    public function allFiles($directory, $hidden = false)
    {
        return $this->files($directory, $hidden, []);
    }

    /**
     * Get all of the directories within a given directory.
     *
     * @param  string  $directory
     * @return array
     */
    public function directories($directory, array|string|int $depth = 0)
    {
        $directories = [];

        foreach (Finder::create()->in($directory)->directories()->depth($depth)->sortByName() as $dir) {
            $directories[] = $dir->getPathname();
        }

        return $directories;
    }

    /**
     * Get all the directories within a given directory (recursive).
     *
     * @return array
     */
    public function allDirectories(string $directory): array
    {
        return $this->directories($directory, []);
    }

    /**
     * Ensure a directory exists.
     *
     * @param  string  $path
     * @param  int  $mode
     * @param  bool  $recursive
     * @return void
     */
    public function ensureDirectoryExists($path, $mode = 0755, $recursive = true)
    {
        if (! $this->isDirectory($path)) {
            $this->makeDirectory($path, $mode, $recursive);
        }
    }

    /**
     * Create a directory.
     *
     * @param  string  $path
     * @param  int  $mode
     * @param  bool  $recursive
     * @param  bool  $force
     * @return bool
     */
    public function makeDirectory($path, $mode = 0755, $recursive = false, $force = false)
    {
        if ($force) {
            return @mkdir($path, $mode, $recursive);
        }

        return mkdir($path, $mode, $recursive);
    }

    /**
     * Move a directory.
     *
     * @param  string  $from
     * @param  string  $to
     * @param  bool  $overwrite
     * @return bool
     */
    public function moveDirectory($from, $to, $overwrite = false)
    {
        if ($overwrite && $this->isDirectory($to) && ! $this->deleteDirectory($to)) {
            return false;
        }

        return @rename($from, $to) === true;
    }

    /**
     * Copy a directory from one location to another.
     *
     * @param  string  $directory
     * @param  string  $destination
     * @param  int|null  $options
     * @return bool
     */
    public function copyDirectory($directory, $destination, $options = null)
    {
        if (! $this->isDirectory($directory)) {
            return false;
        }

        $options = $options ?: FilesystemIterator::SKIP_DOTS;

        // If the destination directory does not actually exist, we will go ahead and
        // create it recursively, which just gets the destination prepared to copy
        // the files over. Once we make the directory we'll proceed the copying.
        $this->ensureDirectoryExists($destination, 0777);

        $items = new FilesystemIterator($directory, $options);

        foreach ($items as $item) {
            // As we spin through items, we will check to see if the current file is actually
            // a directory or a file. When it is actually a directory we will need to call
            // back into this function recursively to keep copying these nested folders.
            $target = $destination.'/'.$item->getBasename();

            if ($item->isDir()) {
                $path = $item->getPathname();

                if (! $this->copyDirectory($path, $target, $options)) {
                    return false;
                }
            }

            // If the current items is just a regular file, we will just copy this to the new
            // location and keep looping. If for some reason the copy fails we'll bail out
            // and return false, so the developer is aware that the copy process failed.
            elseif (! $this->copy($item->getPathname(), $target)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Recursively delete a directory.
     *
     * The directory itself may be optionally preserved.
     *
     * @param  string  $directory
     * @param  bool  $preserve
     * @return bool
     */
    public function deleteDirectory($directory, $preserve = false)
    {
        if (! $this->isDirectory($directory)) {
            return false;
        }

        $items = new FilesystemIterator($directory);

        foreach ($items as $item) {
            // If the item is a directory, we can just recurse into the function and
            // delete that sub-directory otherwise we'll just delete the file and
            // keep iterating through each file until the directory is cleaned.
            if ($item->isDir() && ! $item->isLink()) {
                $this->deleteDirectory($item->getPathname());
            }

            // If the item is just a file, we can go ahead and delete it since we're
            // just looping through and waxing all of the files in this directory
            // and calling directories recursively, so we delete the real path.
            else {
                $this->delete($item->getPathname());
            }
        }

        unset($items);

        if (! $preserve) {
            @rmdir($directory);
        }

        return true;
    }

    /**
     * Remove all of the directories within a given directory.
     *
     * @param  string  $directory
     * @return bool
     */
    public function deleteDirectories($directory)
    {
        $allDirectories = $this->directories($directory);

        if (! empty($allDirectories)) {
            foreach ($allDirectories as $directoryName) {
                $this->deleteDirectory($directoryName);
            }

            return true;
        }

        return false;
    }

    /**
     * Empty the specified directory of all files and folders.
     *
     * @param  string  $directory
     * @return bool
     */
    public function cleanDirectory($directory)
    {
        return $this->deleteDirectory($directory, true);
    }
}
<?php

namespace Illuminate\Support;

use ArrayAccess;
use ArrayIterator;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Support\Traits\EnumeratesValues;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Support\Traits\TransformsToResourceCollection;
use InvalidArgumentException;
use SortDirection;
use stdClass;
use Traversable;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @implements \ArrayAccess<TKey, TValue>
 * @implements \Illuminate\Support\Enumerable<TKey, TValue>
 */
class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerable
{
    /**
     * @use \Illuminate\Support\Traits\EnumeratesValues<TKey, TValue>
     */
    use EnumeratesValues, Macroable, TransformsToResourceCollection;

    /**
     * The items contained in the collection.
     *
     * @var array<TKey, TValue>
     */
    protected $items = [];

    /**
     * Create a new collection.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|null  $items
     */
    public function __construct($items = [])
    {
        $this->items = $this->getArrayableItems($items);
    }

    /**
     * Create a new instance of the collection.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|null  $items
     * @return static
     */
    protected function newInstance($items = [])
    {
        return new static($items);
    }

    /**
     * Create a collection with the given range.
     *
     * @param  int  $from
     * @param  int  $to
     * @param  int  $step
     * @return static<int, int>
     */
    public static function range($from, $to, $step = 1, ...$args)
    {
        return new static(range($from, $to, $step), ...$args);
    }

    /**
     * Get all of the items in the collection.
     *
     * @return array<TKey, TValue>
     */
    public function all()
    {
        return $this->items;
    }

    /**
     * Get a lazy collection for the items in this collection.
     *
     * @return \Illuminate\Support\LazyCollection<TKey, TValue>
     */
    public function lazy()
    {
        return new LazyCollection($this->items);
    }

    /**
     * Get the median of a given key.
     *
     * @param  string|array<array-key, string>|null  $key
     * @return float|int|null
     */
    public function median($key = null)
    {
        $values = (isset($key) ? $this->pluck($key) : $this)
            ->reject(fn ($item) => is_null($item))
            ->sort()->values();

        $count = $values->count();

        if ($count === 0) {
            return;
        }

        $middle = intdiv($count, 2);

        if ($count % 2) {
            return $values->get($middle);
        }

        return $this->newInstance([
            $values->get($middle - 1), $values->get($middle),
        ])->average();
    }

    /**
     * Get the mode of a given key.
     *
     * @param  string|array<array-key, string>|null  $key
     * @return array<int, float|int>|null
     */
    public function mode($key = null)
    {
        if ($this->count() === 0) {
            return;
        }

        $collection = isset($key) ? $this->pluck($key) : $this;

        $counts = $this->newInstance();

        $collection->each(fn ($value) => $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1);

        $sorted = $counts->sort();

        $highestValue = $sorted->last();

        return $sorted->filter(fn ($value) => $value == $highestValue)
            ->sort()->keys()->all();
    }

    /**
     * Collapse the collection of items into a single array.
     *
     * @return static<int, mixed>
     */
    public function collapse()
    {
        return $this->newInstance(Arr::collapse($this->items));
    }

    /**
     * Collapse the collection of items into a single array while preserving its keys.
     *
     * @return static<mixed, mixed>
     */
    public function collapseWithKeys()
    {
        if (! $this->items) {
            return $this->newInstance();
        }

        $results = [];

        foreach ($this->items as $key => $values) {
            if ($values instanceof Collection) {
                $values = $values->all();
            } elseif (! is_array($values)) {
                continue;
            }

            $results[$key] = $values;
        }

        if (! $results) {
            return $this->newInstance();
        }

        return $this->newInstance(array_replace(...$results));
    }

    /**
     * Determine if an item exists in the collection.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function contains($key, $operator = null, $value = null)
    {
        if (func_num_args() === 1) {
            if ($this->useAsCallable($key)) {
                return array_any($this->items, $key);
            }

            return in_array($key, $this->items);
        }

        return $this->contains($this->operatorForWhere(...func_get_args()));
    }

    /**
     * Determine if an item exists, using strict comparison.
     *
     * @param  (callable(TValue): bool)|TValue|array-key  $key
     * @param  TValue|null  $value
     * @return bool
     */
    public function containsStrict($key, $value = null)
    {
        if (func_num_args() === 2) {
            return $this->contains(fn ($item) => data_get($item, $key) === $value);
        }

        if ($this->useAsCallable($key)) {
            return ! is_null($this->first($key));
        }

        return in_array($key, $this->items, true);
    }

    /**
     * Determine if an item is not contained in the collection.
     *
     * @param  mixed  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function doesntContain($key, $operator = null, $value = null)
    {
        return ! $this->contains(...func_get_args());
    }

    /**
     * Determine if an item is not contained in the enumerable, using strict comparison.
     *
     * @param  mixed  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function doesntContainStrict($key, $operator = null, $value = null)
    {
        return ! $this->containsStrict(...func_get_args());
    }

    /**
     * Cross join with the given lists, returning all possible permutations.
     *
     * @template TCrossJoinKey
     * @template TCrossJoinValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TCrossJoinKey, TCrossJoinValue>|iterable<TCrossJoinKey, TCrossJoinValue>  ...$lists
     * @return static<int, array<int, TValue|TCrossJoinValue>>
     */
    public function crossJoin(...$lists)
    {
        return $this->newInstance(Arr::crossJoin(
            $this->items, ...array_map($this->getArrayableItems(...), $lists)
        ));
    }

    /**
     * Get the items in the collection that are not present in the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @return static
     */
    public function diff($items)
    {
        return $this->newInstance(array_diff($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Get the items in the collection that are not present in the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @param  callable(TValue, TValue): int  $callback
     * @return static
     */
    public function diffUsing($items, callable $callback)
    {
        return $this->newInstance(array_udiff($this->items, $this->getArrayableItems($items), $callback));
    }

    /**
     * Get the items in the collection whose keys and values are not present in the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function diffAssoc($items)
    {
        return $this->newInstance(array_diff_assoc($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Get the items in the collection whose keys and values are not present in the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @param  callable(TKey, TKey): int  $callback
     * @return static
     */
    public function diffAssocUsing($items, callable $callback)
    {
        return $this->newInstance(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback));
    }

    /**
     * Get the items in the collection whose keys are not present in the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, mixed>|iterable<TKey, mixed>  $items
     * @return static
     */
    public function diffKeys($items)
    {
        return $this->newInstance(array_diff_key($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Get the items in the collection whose keys are not present in the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, mixed>|iterable<TKey, mixed>  $items
     * @param  callable(TKey, TKey): int  $callback
     * @return static
     */
    public function diffKeysUsing($items, callable $callback)
    {
        return $this->newInstance(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback));
    }

    /**
     * Retrieve duplicate items from the collection.
     *
     * @template TMapValue
     *
     * @param  (callable(TValue): TMapValue)|string|null  $callback
     * @param  bool  $strict
     * @return static
     */
    public function duplicates($callback = null, $strict = false)
    {
        $items = $this->map($this->valueRetriever($callback));

        $uniqueItems = $items->unique(null, $strict);

        $compare = $this->duplicateComparator($strict);

        $duplicates = $this->newInstance();

        foreach ($items as $key => $value) {
            if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) {
                $uniqueItems->shift();
            } else {
                $duplicates[$key] = $value;
            }
        }

        return $duplicates;
    }

    /**
     * Retrieve duplicate items from the collection using strict comparison.
     *
     * @template TMapValue
     *
     * @param  (callable(TValue): TMapValue)|string|null  $callback
     * @return static
     */
    public function duplicatesStrict($callback = null)
    {
        return $this->duplicates($callback, true);
    }

    /**
     * Get the comparison function to detect duplicates.
     *
     * @param  bool  $strict
     * @return callable(TValue, TValue): bool
     */
    protected function duplicateComparator($strict)
    {
        if ($strict) {
            return fn ($a, $b) => $a === $b;
        }

        return fn ($a, $b) => $a == $b;
    }

    /**
     * Get all items except for those with the specified keys.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string  $keys
     * @return static
     */
    public function except($keys)
    {
        if (is_null($keys)) {
            return $this->newInstance($this->items);
        }

        if ($keys instanceof Enumerable) {
            $keys = $keys->all();
        } elseif (! is_array($keys)) {
            $keys = func_get_args();
        }

        return $this->newInstance(Arr::except($this->items, $keys));
    }

    /**
     * Run a filter over each of the items.
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @return static
     */
    public function filter(?callable $callback = null)
    {
        if ($callback) {
            return $this->newInstance(Arr::where($this->items, $callback));
        }

        return $this->newInstance(array_filter($this->items));
    }

    /**
     * Get the first item from the collection passing the given truth test.
     *
     * @template TFirstDefault
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @param  TFirstDefault|(\Closure(): TFirstDefault)  $default
     * @return TValue|TFirstDefault
     */
    public function first(?callable $callback = null, $default = null)
    {
        return Arr::first($this->items, $callback, $default);
    }

    /**
     * Get a flattened array of the items in the collection.
     *
     * @param  int  $depth
     * @return static<int, mixed>
     */
    public function flatten($depth = INF)
    {
        return $this->newInstance(Arr::flatten($this->items, $depth));
    }

    /**
     * Flip the items in the collection.
     *
     * @return static<TValue, TKey>
     */
    public function flip()
    {
        return $this->newInstance(array_flip($this->items));
    }

    /**
     * Remove an item from the collection by key.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TKey>|TKey  $keys
     * @return $this
     */
    public function forget($keys)
    {
        foreach ($this->getArrayableItems($keys) as $key) {
            $this->offsetUnset($key);
        }

        return $this;
    }

    /**
     * Get an item from the collection by key.
     *
     * @template TGetDefault
     *
     * @param  TKey|null  $key
     * @param  TGetDefault|(\Closure(): TGetDefault)  $default
     * @return TValue|TGetDefault
     */
    public function get($key, $default = null)
    {
        $key ??= '';

        if (array_key_exists($key, $this->items)) {
            return $this->items[$key];
        }

        return value($default);
    }

    /**
     * Get an item from the collection by key or add it to collection if it does not exist.
     *
     * @template TGetOrPutValue
     *
     * @param  mixed  $key
     * @param  TGetOrPutValue|(\Closure(): TGetOrPutValue)  $value
     * @return TValue|TGetOrPutValue
     */
    public function getOrPut($key, $value)
    {
        if (array_key_exists($key ?? '', $this->items)) {
            return $this->items[$key ?? ''];
        }

        $this->offsetSet($key, $value = value($value));

        return $value;
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function groupBy($groupBy, $preserveKeys = false)
    {
        if (! $this->useAsCallable($groupBy) && is_array($groupBy)) {
            $nextGroups = $groupBy;

            $groupBy = array_shift($nextGroups);
        }

        $groupBy = $this->valueRetriever($groupBy);

        $results = [];

        foreach ($this->items as $key => $value) {
            $groupKeys = $groupBy($value, $key);

            if (! is_array($groupKeys)) {
                $groupKeys = [$groupKeys];
            }

            foreach ($groupKeys as $groupKey) {
                $groupKey = match (true) {
                    is_bool($groupKey) => (int) $groupKey,
                    $groupKey instanceof \UnitEnum => enum_value($groupKey),
                    $groupKey instanceof \Stringable, is_null($groupKey) => (string) $groupKey,
                    default => $groupKey,
                };

                if (! array_key_exists($groupKey, $results)) {
                    $results[$groupKey] = $this->newInstance();
                }

                $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
            }
        }

        $result = $this->newInstance($results);

        if (! empty($nextGroups)) {
            return $result->map->groupBy($nextGroups, $preserveKeys);
        }

        return $result;
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function keyBy($keyBy)
    {
        $keyBy = $this->valueRetriever($keyBy);

        $results = [];

        foreach ($this->items as $key => $item) {
            $resolvedKey = $keyBy($item, $key);

            if ($resolvedKey instanceof \UnitEnum) {
                $resolvedKey = enum_value($resolvedKey);
            }

            if (is_object($resolvedKey)) {
                $resolvedKey = (string) $resolvedKey;
            }

            $results[$resolvedKey] = $item;
        }

        return $this->newInstance($results);
    }

    /**
     * Determine if an item exists in the collection by key.
     *
     * @param  TKey|array<array-key, TKey>  $key
     * @return bool
     */
    public function has($key)
    {
        $keys = is_array($key) ? $key : func_get_args();

        return array_all($keys, fn ($key) => array_key_exists($key ?? '', $this->items));
    }

    /**
     * Determine if any of the keys exist in the collection.
     *
     * @param  TKey|array<array-key, TKey>  $key
     * @return bool
     */
    public function hasAny($key)
    {
        if ($this->isEmpty()) {
            return false;
        }

        $keys = is_array($key) ? $key : func_get_args();

        return array_any($keys, fn ($key) => array_key_exists($key ?? '', $this->items));
    }

    /**
     * Concatenate values of a given key as a string.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $value
     * @param  string|null  $glue
     * @return string
     */
    public function implode($value, $glue = null)
    {
        if ($this->useAsCallable($value)) {
            return implode($glue ?? '', $this->map($value)->all());
        }

        $first = $this->first();

        if (is_array($first) || (is_object($first) && ! $first instanceof Stringable)) {
            return implode($glue ?? '', $this->pluck($value)->all());
        }

        return implode($value ?? '', $this->items);
    }

    /**
     * Intersect the collection with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function intersect($items)
    {
        return $this->newInstance(array_intersect($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Intersect the collection with the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @param  callable(TValue, TValue): int  $callback
     * @return static
     */
    public function intersectUsing($items, callable $callback)
    {
        return $this->newInstance(array_uintersect($this->items, $this->getArrayableItems($items), $callback));
    }

    /**
     * Intersect the collection with the given items with additional index check.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function intersectAssoc($items)
    {
        return $this->newInstance(array_intersect_assoc($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Intersect the collection with the given items with additional index check, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @param  callable(TValue, TValue): int  $callback
     * @return static
     */
    public function intersectAssocUsing($items, callable $callback)
    {
        return $this->newInstance(array_intersect_uassoc($this->items, $this->getArrayableItems($items), $callback));
    }

    /**
     * Intersect the collection with the given items by key.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, mixed>|iterable<TKey, mixed>  $items
     * @return static
     */
    public function intersectByKeys($items)
    {
        return $this->newInstance(array_intersect_key(
            $this->items, $this->getArrayableItems($items)
        ));
    }

    /**
     * Determine if the collection is empty or not.
     *
     * @phpstan-assert-if-true null $this->first()
     * @phpstan-assert-if-true null $this->last()
     *
     * @phpstan-assert-if-false TValue $this->first()
     * @phpstan-assert-if-false TValue $this->last()
     *
     * @return bool
     */
    public function isEmpty()
    {
        return empty($this->items);
    }

    /**
     * Determine if the collection contains exactly one item. If a callback is provided, determine if exactly one item matches the condition.
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @return bool
     *
     * @deprecated 12.49.0 Use the `hasSole()` method instead.
     */
    public function containsOneItem(?callable $callback = null): bool
    {
        return $this->hasSole($callback);
    }

    /**
     * Determine if the collection contains multiple items.
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @return bool
     *
     * @deprecated 12.50.0 Use the `hasMany()` method instead.
     */
    public function containsManyItems(?callable $callback = null): bool
    {
        return $this->hasMany($callback);
    }

    /**
     * Join all items from the collection using a string. The final items can use a separate glue string.
     *
     * @param  string  $glue
     * @param  string  $finalGlue
     * @return TValue|string
     */
    public function join($glue, $finalGlue = '')
    {
        if ($finalGlue === '') {
            return $this->implode($glue);
        }

        $count = $this->count();

        if ($count === 0) {
            return '';
        }

        if ($count === 1) {
            return $this->last();
        }

        $collection = $this->newInstance($this->items);

        $finalItem = $collection->pop();

        return $collection->implode($glue).$finalGlue.$finalItem;
    }

    /**
     * Get the keys of the collection items.
     *
     * @return static<int, TKey>
     */
    public function keys()
    {
        return $this->newInstance(array_keys($this->items));
    }

    /**
     * Get the last item from the collection.
     *
     * @template TLastDefault
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @param  TLastDefault|(\Closure(): TLastDefault)  $default
     * @return TValue|TLastDefault
     */
    public function last(?callable $callback = null, $default = null)
    {
        return Arr::last($this->items, $callback, $default);
    }

    /**
     * Get the values of a given key.
     *
     * @param  \Closure|string|int|array<array-key, string>|null  $value
     * @param  \Closure|string|null  $key
     * @return static<array-key, mixed>
     */
    public function pluck($value, $key = null)
    {
        return $this->newInstance(Arr::pluck($this->items, $value, $key));
    }

    /**
     * Run a map over each of the items.
     *
     * @template TMapValue
     *
     * @param  callable(TValue, TKey): TMapValue  $callback
     * @return static<TKey, TMapValue>
     */
    public function map(callable $callback)
    {
        return $this->newInstance(Arr::map($this->items, $callback));
    }

    /**
     * Run a dictionary map over the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapToDictionaryKey of array-key
     * @template TMapToDictionaryValue
     *
     * @param  callable(TValue, TKey): array<TMapToDictionaryKey, TMapToDictionaryValue>  $callback
     * @return static<TMapToDictionaryKey, array<int, TMapToDictionaryValue>>
     */
    public function mapToDictionary(callable $callback)
    {
        $dictionary = [];

        foreach ($this->items as $key => $item) {
            $pair = $callback($item, $key);

            $key = key($pair);

            $value = reset($pair);

            if (! isset($dictionary[$key])) {
                $dictionary[$key] = [];
            }

            $dictionary[$key][] = $value;
        }

        return $this->newInstance($dictionary);
    }

    /**
     * Run an associative map over each of the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapWithKeysKey of array-key
     * @template TMapWithKeysValue
     *
     * @param  callable(TValue, TKey): array<TMapWithKeysKey, TMapWithKeysValue>  $callback
     * @return static<TMapWithKeysKey, TMapWithKeysValue>
     */
    public function mapWithKeys(callable $callback)
    {
        return $this->newInstance(Arr::mapWithKeys($this->items, $callback));
    }

    /**
     * Merge the collection with the given items.
     *
     * @template TMergeValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TMergeValue>|iterable<TKey, TMergeValue>  $items
     * @return static<TKey, TValue|TMergeValue>
     */
    public function merge($items)
    {
        return $this->newInstance(array_merge($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Recursively merge the collection with the given items.
     *
     * @template TMergeRecursiveValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TMergeRecursiveValue>|iterable<TKey, TMergeRecursiveValue>  $items
     * @return static<TKey, TValue|TMergeRecursiveValue>
     */
    public function mergeRecursive($items)
    {
        return $this->newInstance(array_merge_recursive($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Multiply the items in the collection by the multiplier.
     *
     * @param  int  $multiplier
     * @return static
     */
    public function multiply(int $multiplier)
    {
        $new = $this->newInstance();

        for ($i = 0; $i < $multiplier; $i++) {
            $new->push(...$this->items);
        }

        return $new;
    }

    /**
     * Create a collection by using this collection for keys and another for its values.
     *
     * @template TCombineValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TCombineValue>|iterable<array-key, TCombineValue>  $values
     * @return static<TValue, TCombineValue>
     */
    public function combine($values)
    {
        return $this->newInstance(array_combine($this->all(), $this->getArrayableItems($values)));
    }

    /**
     * Union the collection with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function union($items)
    {
        return $this->newInstance($this->items + $this->getArrayableItems($items));
    }

    /**
     * Create a new collection consisting of every n-th element.
     *
     * @param  int  $step
     * @param  int  $offset
     * @return ($step is positive-int ? static : never)
     *
     * @throws \InvalidArgumentException
     */
    public function nth($step, $offset = 0)
    {
        if ($step < 1) {
            throw new InvalidArgumentException('Step value must be at least 1.');
        }

        $new = [];

        $position = 0;

        foreach ($this->slice($offset)->items as $item) {
            if ($position % $step === 0) {
                $new[] = $item;
            }

            $position++;
        }

        return $this->newInstance($new);
    }

    /**
     * Get the items with the specified keys.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string|null  $keys
     * @return static
     */
    public function only($keys)
    {
        if (is_null($keys)) {
            return $this->newInstance($this->items);
        }

        if ($keys instanceof Enumerable) {
            $keys = $keys->all();
        }

        $keys = is_array($keys) ? $keys : func_get_args();

        return $this->newInstance(Arr::only($this->items, $keys));
    }

    /**
     * Select specific values from the items within the collection.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string|null  $keys
     * @return static
     */
    public function select($keys)
    {
        if (is_null($keys)) {
            return $this->newInstance($this->items);
        }

        if ($keys instanceof Enumerable) {
            $keys = $keys->all();
        }

        $keys = is_array($keys) ? $keys : func_get_args();

        return $this->newInstance(Arr::select($this->items, $keys));
    }

    /**
     * Get and remove the last N items from the collection.
     *
     * @param  int  $count
     * @return ($count is 1 ? TValue|null : static<int, TValue>)
     */
    public function pop($count = 1)
    {
        if ($count < 1) {
            return $this->newInstance();
        }

        if ($count === 1) {
            return array_pop($this->items);
        }

        if ($this->isEmpty()) {
            return $this->newInstance();
        }

        $results = [];

        $collectionCount = $this->count();

        foreach (range(1, min($count, $collectionCount)) as $item) {
            $results[] = array_pop($this->items);
        }

        return $this->newInstance($results);
    }

    /**
     * Push an item onto the beginning of the collection.
     *
     * @param  TValue  $value
     * @param  TKey  $key
     * @return $this
     */
    public function prepend($value, $key = null)
    {
        $this->items = Arr::prepend($this->items, ...(func_num_args() > 1 ? func_get_args() : [$value]));

        return $this;
    }

    /**
     * Push one or more items onto the end of the collection.
     *
     * @param  TValue  ...$values
     * @return $this
     */
    public function push(...$values)
    {
        foreach ($values as $value) {
            $this->items[] = $value;
        }

        return $this;
    }

    /**
     * Prepend one or more items to the beginning of the collection.
     *
     * @param  TValue  ...$values
     * @return $this
     */
    public function unshift(...$values)
    {
        array_unshift($this->items, ...$values);

        return $this;
    }

    /**
     * Push all of the given items onto the collection.
     *
     * @template TConcatKey of array-key
     * @template TConcatValue
     *
     * @param  iterable<TConcatKey, TConcatValue>  $source
     * @return static<TKey|TConcatKey, TValue|TConcatValue>
     */
    public function concat($source)
    {
        $result = $this->newInstance($this);

        foreach ($source as $item) {
            $result->push($item);
        }

        return $result;
    }

    /**
     * Get and remove an item from the collection.
     *
     * @template TPullDefault
     *
     * @param  TKey  $key
     * @param  TPullDefault|(\Closure(): TPullDefault)  $default
     * @return TValue|TPullDefault
     */
    public function pull($key, $default = null)
    {
        return Arr::pull($this->items, $key, $default);
    }

    /**
     * Put an item in the collection by key.
     *
     * @param  TKey  $key
     * @param  TValue  $value
     * @return $this
     */
    public function put($key, $value)
    {
        $this->offsetSet($key, $value);

        return $this;
    }

    /**
     * Get one or a specified number of items randomly from the collection.
     *
     * @param  (callable(self<TKey, TValue>): int)|int|null  $number
     * @param  bool  $preserveKeys
     * @return ($number is null ? TValue : static<int, TValue>)
     *
     * @throws \InvalidArgumentException
     */
    public function random($number = null, $preserveKeys = false)
    {
        if (is_null($number)) {
            return Arr::random($this->items);
        }

        if (is_callable($number)) {
            return $this->newInstance(Arr::random($this->items, $number($this), $preserveKeys));
        }

        return $this->newInstance(Arr::random($this->items, $number, $preserveKeys));
    }

    /**
     * Replace the collection items with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function replace($items)
    {
        return $this->newInstance(array_replace($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Recursively replace the collection items with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function replaceRecursive($items)
    {
        return $this->newInstance(array_replace_recursive($this->items, $this->getArrayableItems($items)));
    }

    /**
     * Reverse items order.
     *
     * @return static
     */
    public function reverse()
    {
        return $this->newInstance(array_reverse($this->items, true));
    }

    /**
     * Search the collection for a given value and return the corresponding key if successful.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TKey|false
     */
    public function search($value, $strict = false)
    {
        if (! $this->useAsCallable($value)) {
            return array_search($value, $this->items, $strict);
        }

        return array_find_key($this->items, $value) ?? false;
    }

    /**
     * Get the item before the given item.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TValue|null
     */
    public function before($value, $strict = false)
    {
        $key = $this->search($value, $strict);

        if ($key === false) {
            return null;
        }

        $position = ($keys = $this->keys())->search($key);

        if ($position === 0) {
            return null;
        }

        return $this->get($keys->get($position - 1));
    }

    /**
     * Get the item after the given item.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TValue|null
     */
    public function after($value, $strict = false)
    {
        $key = $this->search($value, $strict);

        if ($key === false) {
            return null;
        }

        $position = ($keys = $this->keys())->search($key);

        if ($position === $keys->count() - 1) {
            return null;
        }

        return $this->get($keys->get($position + 1));
    }

    /**
     * Get and remove the first N items from the collection.
     *
     * @param  int<0, max>  $count
     * @return ($count is 1 ? TValue|null : static<int, TValue>)
     *
     * @throws \InvalidArgumentException
     */
    public function shift($count = 1)
    {
        if ($count < 0) {
            throw new InvalidArgumentException('Number of shifted items may not be less than zero.');
        }

        if ($this->isEmpty()) {
            return null;
        }

        if ($count === 0) {
            return $this->newInstance();
        }

        if ($count === 1) {
            return array_shift($this->items);
        }

        $results = [];

        $collectionCount = $this->count();

        foreach (range(1, min($count, $collectionCount)) as $item) {
            $results[] = array_shift($this->items);
        }

        return $this->newInstance($results);
    }

    /**
     * Shuffle the items in the collection.
     *
     * @return static
     */
    public function shuffle()
    {
        return $this->newInstance(Arr::shuffle($this->items));
    }

    /**
     * Create chunks representing a "sliding window" view of the items in the collection.
     *
     * @param  positive-int  $size
     * @param  positive-int  $step
     * @return static<int, static>
     *
     * @throws \InvalidArgumentException
     */
    public function sliding($size = 2, $step = 1)
    {
        if ($size < 1) {
            throw new InvalidArgumentException('Size value must be at least 1.');
        } elseif ($step < 1) {
            throw new InvalidArgumentException('Step value must be at least 1.');
        }

        $chunks = floor(($this->count() - $size) / $step) + 1;

        return static::times($chunks, fn ($number) => $this->slice(($number - 1) * $step, $size));
    }

    /**
     * Skip the first {$count} items.
     *
     * @param  int  $count
     * @return static
     */
    public function skip($count)
    {
        return $this->slice($count);
    }

    /**
     * Skip items in the collection until the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function skipUntil($value)
    {
        return $this->newInstance($this->lazy()->skipUntil($value)->all());
    }

    /**
     * Skip items in the collection while the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function skipWhile($value)
    {
        return $this->newInstance($this->lazy()->skipWhile($value)->all());
    }

    /**
     * Slice the underlying collection array.
     *
     * @param  int  $offset
     * @param  int|null  $length
     * @return static
     */
    public function slice($offset, $length = null)
    {
        return $this->newInstance(array_slice($this->items, $offset, $length, true));
    }

    /**
     * Split a collection into a certain number of groups.
     *
     * @param  int  $numberOfGroups
     * @return ($numberOfGroups is positive-int ? static<int, static> : never)
     *
     * @throws \InvalidArgumentException
     */
    public function split($numberOfGroups)
    {
        if ($numberOfGroups < 1) {
            throw new InvalidArgumentException('Number of groups must be at least 1.');
        }

        if ($this->isEmpty()) {
            return $this->newInstance();
        }

        $groups = $this->newInstance();

        $groupSize = floor($this->count() / $numberOfGroups);

        $remain = $this->count() % $numberOfGroups;

        $start = 0;

        for ($i = 0; $i < $numberOfGroups; $i++) {
            $size = $groupSize;

            if ($i < $remain) {
                $size++;
            }

            if ($size) {
                $groups->push($this->newInstance(array_slice($this->items, $start, $size)));

                $start += $size;
            }
        }

        return $groups;
    }

    /**
     * Split a collection into a certain number of groups, and fill the first groups completely.
     *
     * @param  int  $numberOfGroups
     * @return ($numberOfGroups is positive-int ? static<int, static> : never)
     *
     * @throws \InvalidArgumentException
     */
    public function splitIn($numberOfGroups)
    {
        if ($numberOfGroups < 1) {
            throw new InvalidArgumentException('Number of groups must be at least 1.');
        }

        return $this->chunk((int) ceil($this->count() / $numberOfGroups));
    }

    /**
     * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     * @throws \Illuminate\Support\MultipleItemsFoundException
     */
    public function sole($key = null, $operator = null, $value = null)
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        $items = $this->unless($filter == null)->filter($filter);

        $count = $items->count();

        if ($count === 0) {
            throw new ItemNotFoundException;
        }

        if ($count > 1) {
            throw new MultipleItemsFoundException($count);
        }

        return $items->first();
    }

    /**
     * Determine if the collection contains a single item, optionally matching the given criteria.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function hasSole($key = null, $operator = null, $value = null): bool
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        return $this
            ->unless($filter == null)
            ->filter($filter)
            ->count() === 1;
    }

    /**
     * Get the first item in the collection but throw an exception if no matching items exist.
     *
     * @param  (callable(TValue, TKey): bool)|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     */
    public function firstOrFail($key = null, $operator = null, $value = null)
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        $placeholder = new stdClass();

        $item = $this->first($filter, $placeholder);

        if ($item === $placeholder) {
            throw new ItemNotFoundException;
        }

        return $item;
    }

    /**
     * Chunk the collection into chunks of the given size.
     *
     * @param  int  $size
     * @param  bool  $preserveKeys
     * @return ($preserveKeys is true ? static<int, static> : static<int, static<int, TValue>>)
     */
    public function chunk($size, $preserveKeys = true)
    {
        if ($size <= 0) {
            return $this->newInstance();
        }

        $chunks = [];

        foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
            $chunks[] = $this->newInstance($chunk);
        }

        return $this->newInstance($chunks);
    }

    /**
     * Chunk the collection into chunks with a callback.
     *
     * @param  callable(TValue, TKey, static<TKey, TValue>): bool  $callback
     * @return static<int, static<TKey, TValue>>
     */
    public function chunkWhile(callable $callback)
    {
        return $this->newInstance(
            $this->lazy()->chunkWhile($callback)->mapInto(static::class)
        );
    }

    /**
     * Sort through each item with a callback.
     *
     * @param  (callable(TValue, TValue): int)|null|int  $callback
     * @return static
     */
    public function sort($callback = null)
    {
        $items = $this->items;

        $callback && is_callable($callback)
            ? uasort($items, $callback)
            : asort($items, $callback ?? SORT_REGULAR);

        return $this->newInstance($items);
    }

    /**
     * Sort items in descending order.
     *
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    public function sortDesc($options = SORT_REGULAR)
    {
        $items = $this->items;

        arsort($items, $options);

        return $this->newInstance($items);
    }

    /**
     * Sort the collection using the given callback.
     *
     * @param  array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, SortDirection|'asc'|'desc'}>|(callable(TValue, TKey): mixed)|string|int  $callback
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @param  SortDirection|bool  $descending
     * @return static
     */
    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
    {
        if (is_array($callback) && ! is_callable($callback)) {
            return $this->sortByMany($callback, $options);
        }

        $results = [];

        $callback = $this->valueRetriever($callback);

        // First we will loop through the items and get the comparator from a callback
        // function which we were given. Then, we will sort the returned values and
        // grab all the corresponding values for the sorted keys from this array.
        foreach ($this->items as $key => $value) {
            $results[$key] = $callback($value, $key);
        }

        match ($descending) {
            false, SortDirection::Ascending => asort($results, $options),
            true, SortDirection::Descending => arsort($results, $options),
        };

        // Once we have sorted all of the keys in the array, we will loop through them
        // and grab the corresponding model so we can set the underlying items list
        // to the sorted version. Then we'll just return the collection instance.
        foreach (array_keys($results) as $key) {
            $results[$key] = $this->items[$key];
        }

        return $this->newInstance($results);
    }

    /**
     * Sort the collection using multiple comparisons.
     *
     * @param  array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, SortDirection|'asc'|'desc'}>  $comparisons
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    protected function sortByMany(array $comparisons = [], int $options = SORT_REGULAR)
    {
        $items = $this->items;

        uasort($items, function ($a, $b) use ($comparisons, $options) {
            foreach ($comparisons as $comparison) {
                $comparison = Arr::wrap($comparison);

                $prop = $comparison[0];

                $direction = match (Arr::get($comparison, 1, true)) {
                    true, 'asc', SortDirection::Ascending => SortDirection::Ascending,
                    false, 'desc', SortDirection::Descending => SortDirection::Descending,
                    default => SortDirection::Descending, // for backwards compatibility
                };

                if (! is_string($prop) && is_callable($prop)) {
                    $result = $prop($a, $b);
                } else {
                    $values = [data_get($a, $prop), data_get($b, $prop)];

                    if ($direction === SortDirection::Descending) {
                        $values = array_reverse($values);
                    }

                    if (($options & SORT_FLAG_CASE) === SORT_FLAG_CASE) {
                        if (($options & SORT_NATURAL) === SORT_NATURAL) {
                            $result = strnatcasecmp($values[0], $values[1]);
                        } else {
                            $result = strcasecmp($values[0], $values[1]);
                        }
                    } else {
                        $result = match ($options) {
                            SORT_NUMERIC => (int) $values[0] <=> (int) $values[1],
                            SORT_STRING => strcmp($values[0], $values[1]),
                            SORT_NATURAL => strnatcmp((string) $values[0], (string) $values[1]),
                            SORT_LOCALE_STRING => strcoll($values[0], $values[1]),
                            default => $values[0] <=> $values[1],
                        };
                    }
                }

                if ($result === 0) {
                    continue;
                }

                return $result;
            }
        });

        return $this->newInstance($items);
    }

    /**
     * Sort the collection in descending order using the given callback.
     *
     * @param  array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, SortDirection|'asc'|'desc'}>|(callable(TValue, TKey): mixed)|string|int  $callback
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    public function sortByDesc($callback, $options = SORT_REGULAR)
    {
        if (is_array($callback) && ! is_callable($callback)) {
            foreach ($callback as $index => $key) {
                $comparison = Arr::wrap($key);

                $comparison[1] = SortDirection::Descending;

                $callback[$index] = $comparison;
            }
        }

        return $this->sortBy($callback, $options, true);
    }

    /**
     * Sort the collection keys.
     *
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @param  SortDirection|bool  $descending
     * @return static
     */
    public function sortKeys($options = SORT_REGULAR, $descending = false)
    {
        $items = $this->items;

        match ($descending) {
            false, SortDirection::Ascending => ksort($items, $options),
            true, SortDirection::Descending => krsort($items, $options),
        };

        return $this->newInstance($items);
    }

    /**
     * Sort the collection keys in descending order.
     *
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    public function sortKeysDesc($options = SORT_REGULAR)
    {
        return $this->sortKeys($options, SortDirection::Descending);
    }

    /**
     * Sort the collection keys using a callback.
     *
     * @param  callable(TKey, TKey): int  $callback
     * @return static
     */
    public function sortKeysUsing(callable $callback)
    {
        $items = $this->items;

        uksort($items, $callback);

        return $this->newInstance($items);
    }

    /**
     * Splice a portion of the underlying collection array.
     *
     * @param  int  $offset
     * @param  int|null  $length
     * @param  array<array-key, TValue>  $replacement
     * @return static
     */
    public function splice($offset, $length = null, $replacement = [])
    {
        if (func_num_args() === 1) {
            return $this->newInstance(array_splice($this->items, $offset));
        }

        return $this->newInstance(array_splice($this->items, $offset, $length, $this->getArrayableItems($replacement)));
    }

    /**
     * Take the first or last {$limit} items.
     *
     * @param  int  $limit
     * @return static
     */
    public function take($limit)
    {
        if ($limit < 0) {
            return $this->slice($limit, abs($limit));
        }

        return $this->slice(0, $limit);
    }

    /**
     * Take items in the collection until the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function takeUntil($value)
    {
        return $this->newInstance($this->lazy()->takeUntil($value)->all());
    }

    /**
     * Take items in the collection while the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function takeWhile($value)
    {
        return $this->newInstance($this->lazy()->takeWhile($value)->all());
    }

    /**
     * Transform each item in the collection using a callback.
     *
     * @template TMapValue
     *
     * @param  callable(TValue, TKey): TMapValue  $callback
     * @return $this
     *
     * @phpstan-this-out static<TKey, TMapValue>
     */
    public function transform(callable $callback)
    {
        $this->items = $this->map($callback)->all();

        return $this;
    }

    /**
     * Flatten a multi-dimensional associative array with dots.
     *
     * @param  int  $depth
     * @return static
     */
    public function dot($depth = INF)
    {
        return $this->newInstance(Arr::dot($this->all(), '', $depth));
    }

    /**
     * Convert a flatten "dot" notation array into an expanded array.
     *
     * @return static
     */
    public function undot()
    {
        return $this->newInstance(Arr::undot($this->all()));
    }

    /**
     * Return only unique items from the collection array.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $key
     * @param  bool  $strict
     * @return static
     */
    public function unique($key = null, $strict = false)
    {
        if (is_null($key) && $strict === false) {
            return $this->newInstance(array_unique($this->items, SORT_REGULAR));
        }

        $callback = $this->valueRetriever($key);

        $exists = [];

        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
            if (in_array($id = $callback($item, $key), $exists, $strict)) {
                return true;
            }

            $exists[] = $id;
        });
    }

    /**
     * Reset the keys on the underlying array.
     *
     * @return static<int, TValue>
     */
    public function values()
    {
        return $this->newInstance(array_values($this->items));
    }

    /**
     * Zip the collection together with one or more arrays.
     *
     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
     *      => [[1, 4], [2, 5], [3, 6]]
     *
     * @template TZipValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TZipValue>|iterable<array-key, TZipValue>  ...$items
     * @return static<int, static<int, TValue|TZipValue>>
     */
    public function zip($items)
    {
        $arrayableItems = array_map(fn ($items) => $this->getArrayableItems($items), func_get_args());

        $params = array_merge([fn () => $this->newInstance(func_get_args()), $this->items], $arrayableItems);

        return $this->newInstance(array_map(...$params));
    }

    /**
     * Pad collection to the specified length with a value.
     *
     * @template TPadValue
     *
     * @param  int  $size
     * @param  TPadValue  $value
     * @return static<int, TValue|TPadValue>
     */
    public function pad($size, $value)
    {
        return $this->newInstance(array_pad($this->items, $size, $value));
    }

    /**
     * Get an iterator for the items.
     *
     * @return \ArrayIterator<TKey, TValue>
     */
    public function getIterator(): Traversable
    {
        return new ArrayIterator($this->items);
    }

    /**
     * Count the number of items in the collection.
     *
     * @return int<0, max>
     */
    public function count(): int
    {
        return count($this->items);
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function countBy($countBy = null)
    {
        return $this->newInstance($this->lazy()->countBy($countBy)->all());
    }

    /**
     * Add an item to the collection.
     *
     * @param  TValue  $item
     * @return $this
     */
    public function add($item)
    {
        $this->items[] = $item;

        return $this;
    }

    /**
     * Get a base Support collection instance from this collection.
     *
     * @return \Illuminate\Support\Collection<TKey, TValue>
     */
    public function toBase()
    {
        return new self($this);
    }

    /**
     * Determine if an item exists at an offset.
     *
     * @param  TKey  $offset
     * @return bool
     */
    public function offsetExists($offset): bool
    {
        return isset($this->items[$offset]);
    }

    /**
     * Get an item at a given offset.
     *
     * @param  TKey  $offset
     * @return TValue
     */
    public function offsetGet($offset): mixed
    {
        return $this->items[$offset];
    }

    /**
     * Set the item at a given offset.
     *
     * @param  TKey|null  $offset
     * @param  TValue  $value
     * @return void
     */
    public function offsetSet($offset, $value): void
    {
        if (is_null($offset)) {
            $this->items[] = $value;
        } else {
            $this->items[$offset] = $value;
        }
    }

    /**
     * Unset the item at a given offset.
     *
     * @param  TKey  $offset
     * @return void
     */
    public function offsetUnset($offset): void
    {
        unset($this->items[$offset]);
    }
}
<?php

namespace Illuminate\Support;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @mixin \Illuminate\Support\Enumerable<TKey, TValue>
 * @mixin TValue
 */
class HigherOrderCollectionProxy
{
    /**
     * The collection being operated on.
     *
     * @var \Illuminate\Support\Enumerable<TKey, TValue>
     */
    protected $collection;

    /**
     * The method being proxied.
     *
     * @var string
     */
    protected $method;

    /**
     * Create a new proxy instance.
     *
     * @param  \Illuminate\Support\Enumerable<TKey, TValue>  $collection
     * @param  string  $method
     */
    public function __construct(Enumerable $collection, $method)
    {
        $this->method = $method;
        $this->collection = $collection;
    }

    /**
     * Proxy accessing an attribute onto the collection items.
     *
     * @param  string  $key
     * @return mixed
     */
    public function __get($key)
    {
        return $this->collection->{$this->method}(function ($value) use ($key) {
            return is_array($value) ? $value[$key] : $value->{$key};
        });
    }

    /**
     * Proxy a method call onto the collection items.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
            return is_string($value)
                ? $value::{$method}(...$parameters)
                : $value->{$method}(...$parameters);
        });
    }
}
<?php

namespace Illuminate\Support;

if (! function_exists('Illuminate\Support\enum_value')) {
    /**
     * Return a scalar value for the given value that might be an enum.
     *
     * @internal
     *
     * @template TValue
     * @template TDefault
     *
     * @param  TValue  $value
     * @param  TDefault|callable(TValue): TDefault  $default
     * @return ($value is empty ? TDefault : mixed)
     */
    function enum_value($value, $default = null)
    {
        return match (true) {
            $value instanceof \BackedEnum => $value->value,
            $value instanceof \UnitEnum => $value->name,

            default => $value ?? value($default),
        };
    }
}
<?php

namespace Illuminate\Support;

use RuntimeException;

class MultipleItemsFoundException extends RuntimeException
{
    /**
     * The number of items found.
     *
     * @var int
     */
    public $count;

    /**
     * Create a new exception instance.
     *
     * @param  int  $count
     * @param  int  $code
     * @param  \Throwable|null  $previous
     */
    public function __construct($count, $code = 0, $previous = null)
    {
        $this->count = $count;

        parent::__construct("$count items were found.", $code, $previous);
    }

    /**
     * Get the number of items found.
     *
     * @return int
     */
    public function getCount()
    {
        return $this->count;
    }
}
<?php

namespace Illuminate\Support;

use CachingIterator;
use Countable;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use IteratorAggregate;
use JsonSerializable;
use Traversable;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @extends \Illuminate\Contracts\Support\Arrayable<TKey, TValue>
 * @extends \IteratorAggregate<TKey, TValue>
 */
interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
{
    /**
     * Create a new collection instance if the value isn't one already.
     *
     * @template TMakeKey of array-key
     * @template TMakeValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TMakeKey, TMakeValue>|iterable<TMakeKey, TMakeValue>|null  $items
     * @return static<TMakeKey, TMakeValue>
     */
    public static function make($items = []);

    /**
     * Create a new instance by invoking the callback a given amount of times.
     *
     * @template TTimesValue
     *
     * @param  int  $number
     * @param  (callable(int): TTimesValue)|null  $callback
     * @return static<int, TTimesValue>
     */
    public static function times($number, ?callable $callback = null);

    /**
     * Create a collection with the given range.
     *
     * @param  int  $from
     * @param  int  $to
     * @param  int  $step
     * @return static<int, int>
     */
    public static function range($from, $to, $step = 1);

    /**
     * Wrap the given value in a collection if applicable.
     *
     * @template TWrapValue
     *
     * @param  iterable<array-key, TWrapValue>|TWrapValue  $value
     * @return static<array-key, TWrapValue>
     */
    public static function wrap($value);

    /**
     * Get the underlying items from the given collection if applicable.
     *
     * @template TUnwrapKey of array-key
     * @template TUnwrapValue
     *
     * @param  array<TUnwrapKey, TUnwrapValue>|static<TUnwrapKey, TUnwrapValue>  $value
     * @return array<TUnwrapKey, TUnwrapValue>
     */
    public static function unwrap($value);

    /**
     * Create a new instance with no items.
     *
     * @return static
     */
    public static function empty();

    /**
     * Get all items in the enumerable.
     *
     * @return array<TKey, TValue>
     */
    public function all();

    /**
     * Alias for the "avg" method.
     *
     * @param  (callable(TValue): float|int)|string|null  $callback
     * @return float|int|null
     */
    public function average($callback = null);

    /**
     * Get the median of a given key.
     *
     * @param  string|array<array-key, string>|null  $key
     * @return float|int|null
     */
    public function median($key = null);

    /**
     * Get the mode of a given key.
     *
     * @param  string|array<array-key, string>|null  $key
     * @return array<int, float|int>|null
     */
    public function mode($key = null);

    /**
     * Collapse the items into a single enumerable.
     *
     * @return static<int, mixed>
     */
    public function collapse();

    /**
     * Alias for the "contains" method.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function some($key, $operator = null, $value = null);

    /**
     * Determine if an item exists, using strict comparison.
     *
     * @param  (callable(TValue): bool)|TValue|array-key  $key
     * @param  TValue|null  $value
     * @return bool
     */
    public function containsStrict($key, $value = null);

    /**
     * Get the average value of a given key.
     *
     * @param  (callable(TValue): float|int)|string|null  $callback
     * @return float|int|null
     */
    public function avg($callback = null);

    /**
     * Determine if an item exists in the enumerable.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function contains($key, $operator = null, $value = null);

    /**
     * Determine if an item is not contained in the collection.
     *
     * @param  mixed  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function doesntContain($key, $operator = null, $value = null);

    /**
     * Cross join with the given lists, returning all possible permutations.
     *
     * @template TCrossJoinKey
     * @template TCrossJoinValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TCrossJoinKey, TCrossJoinValue>|iterable<TCrossJoinKey, TCrossJoinValue>  ...$lists
     * @return static<int, array<int, TValue|TCrossJoinValue>>
     */
    public function crossJoin(...$lists);

    /**
     * Dump the collection and end the script.
     *
     * @param  mixed  ...$args
     * @return never
     */
    public function dd(...$args);

    /**
     * Dump the collection.
     *
     * @param  mixed  ...$args
     * @return $this
     */
    public function dump(...$args);

    /**
     * Get the items that are not present in the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @return static
     */
    public function diff($items);

    /**
     * Get the items that are not present in the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @param  callable(TValue, TValue): int  $callback
     * @return static
     */
    public function diffUsing($items, callable $callback);

    /**
     * Get the items whose keys and values are not present in the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function diffAssoc($items);

    /**
     * Get the items whose keys and values are not present in the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @param  callable(TKey, TKey): int  $callback
     * @return static
     */
    public function diffAssocUsing($items, callable $callback);

    /**
     * Get the items whose keys are not present in the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, mixed>|iterable<TKey, mixed>  $items
     * @return static
     */
    public function diffKeys($items);

    /**
     * Get the items whose keys are not present in the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, mixed>|iterable<TKey, mixed>  $items
     * @param  callable(TKey, TKey): int  $callback
     * @return static
     */
    public function diffKeysUsing($items, callable $callback);

    /**
     * Retrieve duplicate items.
     *
     * @param  (callable(TValue): bool)|string|null  $callback
     * @param  bool  $strict
     * @return static
     */
    public function duplicates($callback = null, $strict = false);

    /**
     * Retrieve duplicate items using strict comparison.
     *
     * @param  (callable(TValue): bool)|string|null  $callback
     * @return static
     */
    public function duplicatesStrict($callback = null);

    /**
     * Execute a callback over each item.
     *
     * @param  callable(TValue, TKey): mixed  $callback
     * @return $this
     */
    public function each(callable $callback);

    /**
     * Execute a callback over each nested chunk of items.
     *
     * @param  callable  $callback
     * @return static
     */
    public function eachSpread(callable $callback);

    /**
     * Determine if all items pass the given truth test.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function every($key, $operator = null, $value = null);

    /**
     * Get all items except for those with the specified keys.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>  $keys
     * @return static
     */
    public function except($keys);

    /**
     * Run a filter over each of the items.
     *
     * @param  (callable(TValue): bool)|null  $callback
     * @return static
     */
    public function filter(?callable $callback = null);

    /**
     * Apply the callback if the given "value" is (or resolves to) truthy.
     *
     * @template TWhenReturnType as null
     *
     * @param  bool  $value
     * @param  (callable($this): TWhenReturnType)|null  $callback
     * @param  (callable($this): TWhenReturnType)|null  $default
     * @return $this|TWhenReturnType
     */
    public function when($value, ?callable $callback = null, ?callable $default = null);

    /**
     * Apply the callback if the collection is empty.
     *
     * @template TWhenEmptyReturnType
     *
     * @param  (callable($this): TWhenEmptyReturnType)  $callback
     * @param  (callable($this): TWhenEmptyReturnType)|null  $default
     * @return $this|TWhenEmptyReturnType
     */
    public function whenEmpty(callable $callback, ?callable $default = null);

    /**
     * Apply the callback if the collection is not empty.
     *
     * @template TWhenNotEmptyReturnType
     *
     * @param  callable($this): TWhenNotEmptyReturnType  $callback
     * @param  (callable($this): TWhenNotEmptyReturnType)|null  $default
     * @return $this|TWhenNotEmptyReturnType
     */
    public function whenNotEmpty(callable $callback, ?callable $default = null);

    /**
     * Apply the callback if the given "value" is (or resolves to) falsy.
     *
     * @template TUnlessReturnType
     *
     * @param  bool  $value
     * @param  (callable($this): TUnlessReturnType)  $callback
     * @param  (callable($this): TUnlessReturnType)|null  $default
     * @return $this|TUnlessReturnType
     */
    public function unless($value, callable $callback, ?callable $default = null);

    /**
     * Apply the callback unless the collection is empty.
     *
     * @template TUnlessEmptyReturnType
     *
     * @param  callable($this): TUnlessEmptyReturnType  $callback
     * @param  (callable($this): TUnlessEmptyReturnType)|null  $default
     * @return $this|TUnlessEmptyReturnType
     */
    public function unlessEmpty(callable $callback, ?callable $default = null);

    /**
     * Apply the callback unless the collection is not empty.
     *
     * @template TUnlessNotEmptyReturnType
     *
     * @param  callable($this): TUnlessNotEmptyReturnType  $callback
     * @param  (callable($this): TUnlessNotEmptyReturnType)|null  $default
     * @return $this|TUnlessNotEmptyReturnType
     */
    public function unlessNotEmpty(callable $callback, ?callable $default = null);

    /**
     * Filter items by the given key value pair.
     *
     * @param  string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return static
     */
    public function where($key, $operator = null, $value = null);

    /**
     * Filter items where the value for the given key is null.
     *
     * @param  string|null  $key
     * @return static
     */
    public function whereNull($key = null);

    /**
     * Filter items where the value for the given key is not null.
     *
     * @param  string|null  $key
     * @return static
     */
    public function whereNotNull($key = null);

    /**
     * Filter items by the given key value pair using strict comparison.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return static
     */
    public function whereStrict($key, $value);

    /**
     * Filter items by the given key value pair.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @param  bool  $strict
     * @return static
     */
    public function whereIn($key, $values, $strict = false);

    /**
     * Filter items by the given key value pair using strict comparison.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereInStrict($key, $values);

    /**
     * Filter items such that the value of the given key is between the given values.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereBetween($key, $values);

    /**
     * Filter items such that the value of the given key is not between the given values.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereNotBetween($key, $values);

    /**
     * Filter items by the given key value pair.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @param  bool  $strict
     * @return static
     */
    public function whereNotIn($key, $values, $strict = false);

    /**
     * Filter items by the given key value pair using strict comparison.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereNotInStrict($key, $values);

    /**
     * Filter the items, removing any items that don't match the given type(s).
     *
     * @template TWhereInstanceOf
     *
     * @param  class-string<TWhereInstanceOf>|array<array-key, class-string<TWhereInstanceOf>>  $type
     * @return static<TKey, TWhereInstanceOf>
     */
    public function whereInstanceOf($type);

    /**
     * Get the first item from the enumerable passing the given truth test.
     *
     * @template TFirstDefault
     *
     * @param  (callable(TValue,TKey): bool)|null  $callback
     * @param  TFirstDefault|(\Closure(): TFirstDefault)  $default
     * @return TValue|TFirstDefault
     */
    public function first(?callable $callback = null, $default = null);

    /**
     * Get the first item by the given key value pair.
     *
     * @param  string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue|null
     */
    public function firstWhere($key, $operator = null, $value = null);

    /**
     * Get a flattened array of the items in the collection.
     *
     * @param  int  $depth
     * @return static<int, mixed>
     */
    public function flatten($depth = INF);

    /**
     * Flip the values with their keys.
     *
     * @return static<TValue, TKey>
     */
    public function flip();

    /**
     * Get an item from the collection by key.
     *
     * @template TGetDefault
     *
     * @param  TKey  $key
     * @param  TGetDefault|(\Closure(): TGetDefault)  $default
     * @return TValue|TGetDefault
     */
    public function get($key, $default = null);

    /**
     * Group an associative array by a field or using a callback.
     *
     * @template TGroupKey of array-key|\UnitEnum|\Stringable
     *
     * @param  (callable(TValue, TKey): TGroupKey)|array|string  $groupBy
     * @param  bool  $preserveKeys
     * @return static<
     *  ($groupBy is (array|string)
     *      ? array-key
     *      : (TGroupKey is \UnitEnum ? array-key : (TGroupKey is \Stringable ? string : TGroupKey))),
     *  static<($preserveKeys is true ? TKey : int), ($groupBy is array ? mixed : TValue)>
     * >
     */
    public function groupBy($groupBy, $preserveKeys = false);

    /**
     * Key an associative array by a field or using a callback.
     *
     * @template TNewKey of array-key|\UnitEnum
     *
     * @param  (callable(TValue, TKey): TNewKey)|array|string  $keyBy
     * @return static<($keyBy is (array|string) ? array-key : (TNewKey is \UnitEnum ? array-key : TNewKey)), TValue>
     */
    public function keyBy($keyBy);

    /**
     * Determine if an item exists in the collection by key.
     *
     * @param  TKey|array<array-key, TKey>  $key
     * @return bool
     */
    public function has($key);

    /**
     * Determine if any of the keys exist in the collection.
     *
     * @param  mixed  $key
     * @return bool
     */
    public function hasAny($key);

    /**
     * Concatenate values of a given key as a string.
     *
     * @param  (callable(TValue, TKey): mixed)|string  $value
     * @param  string|null  $glue
     * @return string
     */
    public function implode($value, $glue = null);

    /**
     * Intersect the collection with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function intersect($items);

    /**
     * Intersect the collection with the given items, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @param  callable(TValue, TValue): int  $callback
     * @return static
     */
    public function intersectUsing($items, callable $callback);

    /**
     * Intersect the collection with the given items with additional index check.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function intersectAssoc($items);

    /**
     * Intersect the collection with the given items with additional index check, using the callback.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue>  $items
     * @param  callable(TValue, TValue): int  $callback
     * @return static
     */
    public function intersectAssocUsing($items, callable $callback);

    /**
     * Intersect the collection with the given items by key.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, mixed>|iterable<TKey, mixed>  $items
     * @return static
     */
    public function intersectByKeys($items);

    /**
     * Determine if the collection is empty or not.
     *
     * @return bool
     */
    public function isEmpty();

    /**
     * Determine if the collection is not empty.
     *
     * @return bool
     */
    public function isNotEmpty();

    /**
     * Determine if the collection contains a single item.
     *
     * @return bool
     */
    public function containsOneItem();

    /**
     * Determine if the collection contains multiple items.
     *
     * @return bool
     */
    public function containsManyItems();

    /**
     * Determine if the collection contains a single item, optionally matching the given criteria.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function hasSole($key = null, $operator = null, $value = null);

    /**
     * Determine if the collection contains multiple items, optionally matching the given criteria.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function hasMany($key = null, $operator = null, $value = null);

    /**
     * Join all items from the collection using a string. The final items can use a separate glue string.
     *
     * @param  string  $glue
     * @param  string  $finalGlue
     * @return string
     */
    public function join($glue, $finalGlue = '');

    /**
     * Get the keys of the collection items.
     *
     * @return static<int, TKey>
     */
    public function keys();

    /**
     * Get the last item from the collection.
     *
     * @template TLastDefault
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @param  TLastDefault|(\Closure(): TLastDefault)  $default
     * @return TValue|TLastDefault
     */
    public function last(?callable $callback = null, $default = null);

    /**
     * Run a map over each of the items.
     *
     * @template TMapValue
     *
     * @param  callable(TValue, TKey): TMapValue  $callback
     * @return static<TKey, TMapValue>
     */
    public function map(callable $callback);

    /**
     * Run a map over each nested chunk of items.
     *
     * @param  callable  $callback
     * @return static
     */
    public function mapSpread(callable $callback);

    /**
     * Run a dictionary map over the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapToDictionaryKey of array-key
     * @template TMapToDictionaryValue
     *
     * @param  callable(TValue, TKey): array<TMapToDictionaryKey, TMapToDictionaryValue>  $callback
     * @return static<TMapToDictionaryKey, array<int, TMapToDictionaryValue>>
     */
    public function mapToDictionary(callable $callback);

    /**
     * Run a grouping map over the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapToGroupsKey of array-key
     * @template TMapToGroupsValue
     *
     * @param  callable(TValue, TKey): array<TMapToGroupsKey, TMapToGroupsValue>  $callback
     * @return static<TMapToGroupsKey, static<int, TMapToGroupsValue>>
     */
    public function mapToGroups(callable $callback);

    /**
     * Run an associative map over each of the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapWithKeysKey of array-key
     * @template TMapWithKeysValue
     *
     * @param  callable(TValue, TKey): array<TMapWithKeysKey, TMapWithKeysValue>  $callback
     * @return static<TMapWithKeysKey, TMapWithKeysValue>
     */
    public function mapWithKeys(callable $callback);

    /**
     * Map a collection and flatten the result by a single level.
     *
     * @template TFlatMapKey of array-key
     * @template TFlatMapValue
     *
     * @param  callable(TValue, TKey): (\Illuminate\Support\Collection<TFlatMapKey, TFlatMapValue>|array<TFlatMapKey, TFlatMapValue>)  $callback
     * @return static<TFlatMapKey, TFlatMapValue>
     */
    public function flatMap(callable $callback);

    /**
     * Map the values into a new class.
     *
     * @template TMapIntoValue
     *
     * @param  class-string<TMapIntoValue>  $class
     * @return static<TKey, TMapIntoValue>
     */
    public function mapInto($class);

    /**
     * Merge the collection with the given items.
     *
     * @template TMergeValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TMergeValue>|iterable<TKey, TMergeValue>  $items
     * @return static<TKey, TValue|TMergeValue>
     */
    public function merge($items);

    /**
     * Recursively merge the collection with the given items.
     *
     * @template TMergeRecursiveValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TMergeRecursiveValue>|iterable<TKey, TMergeRecursiveValue>  $items
     * @return static<TKey, TValue|TMergeRecursiveValue>
     */
    public function mergeRecursive($items);

    /**
     * Create a collection by using this collection for keys and another for its values.
     *
     * @template TCombineValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TCombineValue>|iterable<array-key, TCombineValue>  $values
     * @return static<TValue, TCombineValue>
     */
    public function combine($values);

    /**
     * Union the collection with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function union($items);

    /**
     * Get the min value of a given key.
     *
     * @template TMinResult = mixed
     *
     * @param  (callable(TValue): TMinResult)|string|null  $callback
     * @return ($callback is callable ? ?TMinResult : ($callback is null ? ?TValue : mixed))
     */
    public function min($callback = null);

    /**
     * Get the max value of a given key.
     *
     * @template TMaxResult = mixed
     *
     * @param  (callable(TValue): TMaxResult)|string|null  $callback
     * @return ($callback is callable ? ?TMaxResult : ($callback is null ? ?TValue : mixed))
     */
    public function max($callback = null);

    /**
     * Create a new collection consisting of every n-th element.
     *
     * @param  int  $step
     * @param  int  $offset
     * @return static
     */
    public function nth($step, $offset = 0);

    /**
     * Get the items with the specified keys.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string  $keys
     * @return static
     */
    public function only($keys);

    /**
     * "Paginate" the collection by slicing it into a smaller collection.
     *
     * @param  int  $page
     * @param  int  $perPage
     * @return static
     */
    public function forPage($page, $perPage);

    /**
     * Partition the collection into two arrays using the given callback or key.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return static<int<0, 1>, static<TKey, TValue>>
     */
    public function partition($key, $operator = null, $value = null);

    /**
     * Push all of the given items onto the collection.
     *
     * @template TConcatKey of array-key
     * @template TConcatValue
     *
     * @param  iterable<TConcatKey, TConcatValue>  $source
     * @return static<TKey|TConcatKey, TValue|TConcatValue>
     */
    public function concat($source);

    /**
     * Get one or a specified number of items randomly from the collection.
     *
     * @param  int|null  $number
     * @return static<int, TValue>|TValue
     *
     * @throws \InvalidArgumentException
     */
    public function random($number = null);

    /**
     * Reduce the collection to a single value.
     *
     * @template TReduceInitial
     * @template TReduceReturnType
     *
     * @param  callable(TReduceInitial|TReduceReturnType, TValue, TKey): TReduceReturnType  $callback
     * @param  TReduceInitial  $initial
     * @return TReduceInitial|TReduceReturnType
     */
    public function reduce(callable $callback, $initial = null);

    /**
     * Reduce the collection to multiple aggregate values.
     *
     * @param  callable  $callback
     * @param  mixed  ...$initial
     * @return array
     *
     * @throws \UnexpectedValueException
     */
    public function reduceSpread(callable $callback, ...$initial);

    /**
     * Replace the collection items with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function replace($items);

    /**
     * Recursively replace the collection items with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function replaceRecursive($items);

    /**
     * Reverse items order.
     *
     * @return static
     */
    public function reverse();

    /**
     * Search the collection for a given value and return the corresponding key if successful.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @param  bool  $strict
     * @return TKey|false
     */
    public function search($value, $strict = false);

    /**
     * Get the item before the given item.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TValue|null
     */
    public function before($value, $strict = false);

    /**
     * Get the item after the given item.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TValue|null
     */
    public function after($value, $strict = false);

    /**
     * Shuffle the items in the collection.
     *
     * @return static
     */
    public function shuffle();

    /**
     * Create chunks representing a "sliding window" view of the items in the collection.
     *
     * @param  int  $size
     * @param  int  $step
     * @return static<int, static>
     */
    public function sliding($size = 2, $step = 1);

    /**
     * Skip the first {$count} items.
     *
     * @param  int  $count
     * @return static
     */
    public function skip($count);

    /**
     * Skip items in the collection until the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function skipUntil($value);

    /**
     * Skip items in the collection while the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function skipWhile($value);

    /**
     * Get a slice of items from the enumerable.
     *
     * @param  int  $offset
     * @param  int|null  $length
     * @return static
     */
    public function slice($offset, $length = null);

    /**
     * Split a collection into a certain number of groups.
     *
     * @param  int  $numberOfGroups
     * @return static<int, static>
     */
    public function split($numberOfGroups);

    /**
     * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.
     *
     * @param  (callable(TValue, TKey): bool)|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     * @throws \Illuminate\Support\MultipleItemsFoundException
     */
    public function sole($key = null, $operator = null, $value = null);

    /**
     * Get the first item in the collection but throw an exception if no matching items exist.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     */
    public function firstOrFail($key = null, $operator = null, $value = null);

    /**
     * Chunk the collection into chunks of the given size.
     *
     * @param  int  $size
     * @return static<int, static>
     */
    public function chunk($size);

    /**
     * Chunk the collection into chunks with a callback.
     *
     * @param  callable(TValue, TKey, static<int, TValue>): bool  $callback
     * @return static<int, static<int, TValue>>
     */
    public function chunkWhile(callable $callback);

    /**
     * Split a collection into a certain number of groups, and fill the first groups completely.
     *
     * @param  int  $numberOfGroups
     * @return static<int, static>
     */
    public function splitIn($numberOfGroups);

    /**
     * Sort through each item with a callback.
     *
     * @param  (callable(TValue, TValue): int)|null|int  $callback
     * @return static
     */
    public function sort($callback = null);

    /**
     * Sort items in descending order.
     *
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    public function sortDesc($options = SORT_REGULAR);

    /**
     * Sort the collection using the given callback.
     *
     * @param  array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, \SortDirection|'asc'|'desc'}>|(callable(TValue, TKey): mixed)|string|int  $callback
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @param  bool  $descending
     * @return static
     */
    public function sortBy($callback, $options = SORT_REGULAR, $descending = false);

    /**
     * Sort the collection in descending order using the given callback.
     *
     * @param  array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, \SortDirection|'asc'|'desc'}>|(callable(TValue, TKey): mixed)|string|int  $callback
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    public function sortByDesc($callback, $options = SORT_REGULAR);

    /**
     * Sort the collection keys.
     *
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @param  bool  $descending
     * @return static
     */
    public function sortKeys($options = SORT_REGULAR, $descending = false);

    /**
     * Sort the collection keys in descending order.
     *
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return static
     */
    public function sortKeysDesc($options = SORT_REGULAR);

    /**
     * Sort the collection keys using a callback.
     *
     * @param  callable(TKey, TKey): int  $callback
     * @return static
     */
    public function sortKeysUsing(callable $callback);

    /**
     * Get the sum of the given values.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $callback
     * @return mixed
     */
    public function sum($callback = null);

    /**
     * Take the first or last {$limit} items.
     *
     * @param  int  $limit
     * @return static
     */
    public function take($limit);

    /**
     * Take items in the collection until the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function takeUntil($value);

    /**
     * Take items in the collection while the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function takeWhile($value);

    /**
     * Pass the collection to the given callback and then return it.
     *
     * @param  callable(TValue): mixed  $callback
     * @return $this
     */
    public function tap(callable $callback);

    /**
     * Pass the enumerable to the given callback and return the result.
     *
     * @template TPipeReturnType
     *
     * @param  callable($this): TPipeReturnType  $callback
     * @return TPipeReturnType
     */
    public function pipe(callable $callback);

    /**
     * Pass the collection into a new class.
     *
     * @template TPipeIntoValue
     *
     * @param  class-string<TPipeIntoValue>  $class
     * @return TPipeIntoValue
     */
    public function pipeInto($class);

    /**
     * Pass the collection through a series of callable pipes and return the result.
     *
     * @param  array<callable>  $pipes
     * @return mixed
     */
    public function pipeThrough($pipes);

    /**
     * Get the values of a given key.
     *
     * @param  string|array<array-key, string>  $value
     * @param  string|null  $key
     * @return static<array-key, mixed>
     */
    public function pluck($value, $key = null);

    /**
     * Create a collection of all elements that do not pass a given truth test.
     *
     * @param  (callable(TValue, TKey): bool)|bool|TValue  $callback
     * @return static
     */
    public function reject($callback = true);

    /**
     * Convert a flatten "dot" notation array into an expanded array.
     *
     * @return static
     */
    public function undot();

    /**
     * Return only unique items from the collection array.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $key
     * @param  bool  $strict
     * @return static
     */
    public function unique($key = null, $strict = false);

    /**
     * Return only unique items from the collection array using strict comparison.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $key
     * @return static
     */
    public function uniqueStrict($key = null);

    /**
     * Reset the keys on the underlying array.
     *
     * @return static<int, TValue>
     */
    public function values();

    /**
     * Pad collection to the specified length with a value.
     *
     * @template TPadValue
     *
     * @param  int  $size
     * @param  TPadValue  $value
     * @return static<int, TValue|TPadValue>
     */
    public function pad($size, $value);

    /**
     * Get the values iterator.
     *
     * @return \Traversable<TKey, TValue>
     */
    public function getIterator(): Traversable;

    /**
     * Count the number of items in the collection.
     *
     * @return int
     */
    public function count(): int;

    /**
     * Count the number of items in the collection by a field or using a callback.
     *
     * @param  (callable(TValue, TKey): (array-key|\UnitEnum))|string|null  $countBy
     * @return static<array-key, int>
     */
    public function countBy($countBy = null);

    /**
     * Zip the collection together with one or more arrays.
     *
     * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
     *      => [[1, 4], [2, 5], [3, 6]]
     *
     * @template TZipValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TZipValue>|iterable<array-key, TZipValue>  ...$items
     * @return static<int, static<int, TValue|TZipValue>>
     */
    public function zip($items);

    /**
     * Collect the values into a collection.
     *
     * @return \Illuminate\Support\Collection<TKey, TValue>
     */
    public function collect();

    /**
     * Get the collection of items as a plain array.
     *
     * @return array<TKey, mixed>
     */
    public function toArray();

    /**
     * Convert the object into something JSON serializable.
     *
     * @return mixed
     */
    public function jsonSerialize(): mixed;

    /**
     * Get the collection of items as JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0);

    /**
     * Get the collection of items as pretty print formatted JSON.
     *
     *
     * @param  int  $options
     * @return string
     */
    public function toPrettyJson(int $options = 0);

    /**
     * Get a CachingIterator instance.
     *
     * @param  int  $flags
     * @return \CachingIterator
     */
    public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING);

    /**
     * Convert the collection to its string representation.
     *
     * @return string
     */
    public function __toString();

    /**
     * Indicate that the model's string representation should be escaped when __toString is invoked.
     *
     * @param  bool  $escape
     * @return $this
     */
    public function escapeWhenCastingToString($escape = true);

    /**
     * Add a method to the list of proxied methods.
     *
     * @param  string  $method
     * @return void
     */
    public static function proxy($method);

    /**
     * Dynamically access collection proxies.
     *
     * @param  string  $key
     * @return mixed
     *
     * @throws \Exception
     */
    public function __get($key);
}
<?php

namespace Illuminate\Support;

use RuntimeException;

class ItemNotFoundException extends RuntimeException
{
}
<?php

namespace Illuminate\Support\Traits;

use BackedEnum;
use CachingIterator;
use Closure;
use Exception;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Enumerable;
use Illuminate\Support\HigherOrderCollectionProxy;
use JsonSerializable;
use UnexpectedValueException;
use UnitEnum;

use function Illuminate\Support\enum_value;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $average
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $avg
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $contains
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $doesntContain
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $each
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $every
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $filter
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $first
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $flatMap
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $groupBy
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $hasMany
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $hasSole
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $keyBy
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $last
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $map
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $max
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $min
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $partition
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $percentage
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $reject
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $skipUntil
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $skipWhile
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $some
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $sortBy
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $sortByDesc
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $sum
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $takeUntil
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $takeWhile
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $unique
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $unless
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $until
 * @property-read HigherOrderCollectionProxy<TKey, TValue> $when
 */
trait EnumeratesValues
{
    use Conditionable;

    /**
     * Indicates that the object's string representation should be escaped when __toString is invoked.
     *
     * @var bool
     */
    protected $escapeWhenCastingToString = false;

    /**
     * The methods that can be proxied.
     *
     * @var array<int, string>
     */
    protected static $proxies = [
        'average',
        'avg',
        'contains',
        'doesntContain',
        'each',
        'every',
        'filter',
        'first',
        'flatMap',
        'groupBy',
        'hasMany',
        'hasSole',
        'keyBy',
        'last',
        'map',
        'max',
        'min',
        'partition',
        'percentage',
        'reject',
        'skipUntil',
        'skipWhile',
        'some',
        'sortBy',
        'sortByDesc',
        'sum',
        'takeUntil',
        'takeWhile',
        'unique',
        'unless',
        'until',
        'when',
    ];

    /**
     * Create a new collection instance if the value isn't one already.
     *
     * @template TMakeKey of array-key
     * @template TMakeValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TMakeKey, TMakeValue>|iterable<TMakeKey, TMakeValue>|null  $items
     * @return static<TMakeKey, TMakeValue>
     */
    public static function make($items = [], ...$args)
    {
        return new static($items, ...$args);
    }

    /**
     * Wrap the given value in a collection if applicable.
     *
     * @template TWrapValue
     *
     * @param  iterable<array-key, TWrapValue>|TWrapValue  $value
     * @return static<array-key, TWrapValue>
     */
    public static function wrap($value, ...$args)
    {
        return $value instanceof Enumerable
            ? new static($value, ...$args)
            : new static(Arr::wrap($value), ...$args);
    }

    /**
     * Get the underlying items from the given collection if applicable.
     *
     * @template TUnwrapKey of array-key
     * @template TUnwrapValue
     *
     * @param  array<TUnwrapKey, TUnwrapValue>|static<TUnwrapKey, TUnwrapValue>  $value
     * @return array<TUnwrapKey, TUnwrapValue>
     */
    public static function unwrap($value)
    {
        return $value instanceof Enumerable ? $value->all() : $value;
    }

    /**
     * Create a new instance with no items.
     *
     * @return static
     */
    public static function empty(...$args)
    {
        return new static([], ...$args);
    }

    /**
     * Create a new collection by invoking the callback a given amount of times.
     *
     * @template TTimesValue
     *
     * @param  int  $number
     * @param  (callable(int): TTimesValue)|null  $callback
     * @return static<int, TTimesValue>
     */
    public static function times($number, ?callable $callback = null, ...$args)
    {
        if ($number < 1) {
            return new static([], ...$args);
        }

        return static::range(1, $number, 1, ...$args)
            ->unless($callback == null)
            ->map($callback);
    }

    /**
     * Create a new collection by decoding a JSON string.
     *
     * @param  string  $json
     * @param  int  $depth
     * @param  int  $flags
     * @return static<TKey, TValue>
     */
    public static function fromJson($json, $depth = 512, $flags = 0, ...$args)
    {
        return new static(json_decode($json, true, $depth, $flags), ...$args);
    }

    /**
     * Get the average value of a given key.
     *
     * @param  (callable(TValue): float|int)|string|null  $callback
     * @return float|int|null
     */
    public function avg($callback = null)
    {
        $callback = $this->valueRetriever($callback);

        $reduced = $this->reduce(static function (&$reduce, $value) use ($callback) {
            if (! is_null($resolved = $callback($value))) {
                $reduce[0] += $resolved;
                $reduce[1]++;
            }

            return $reduce;
        }, [0, 0]);

        return $reduced[1] ? $reduced[0] / $reduced[1] : null;
    }

    /**
     * Alias for the "avg" method.
     *
     * @param  (callable(TValue): float|int)|string|null  $callback
     * @return float|int|null
     */
    public function average($callback = null)
    {
        return $this->avg($callback);
    }

    /**
     * Alias for the "contains" method.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function some($key, $operator = null, $value = null)
    {
        return $this->contains(...func_get_args());
    }

    /**
     * Dump the given arguments and terminate execution.
     *
     * @param  mixed  ...$args
     * @return never
     */
    public function dd(...$args)
    {
        dd($this->all(), ...$args);
    }

    /**
     * Dump the items.
     *
     * @param  mixed  ...$args
     * @return $this
     */
    public function dump(...$args)
    {
        dump($this->all(), ...$args);

        return $this;
    }

    /**
     * Execute a callback over each item.
     *
     * @param  callable(TValue, TKey): mixed  $callback
     * @return $this
     */
    public function each(callable $callback)
    {
        foreach ($this as $key => $item) {
            if ($callback($item, $key) === false) {
                break;
            }
        }

        return $this;
    }

    /**
     * Execute a callback over each nested chunk of items.
     *
     * @param  callable(...mixed): mixed  $callback
     * @return static
     */
    public function eachSpread(callable $callback)
    {
        return $this->each(function ($chunk, $key) use ($callback) {
            $chunk[] = $key;

            return $callback(...$chunk);
        });
    }

    /**
     * Determine if all items pass the given truth test.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function every($key, $operator = null, $value = null)
    {
        if (func_num_args() === 1) {
            $callback = $this->valueRetriever($key);

            foreach ($this as $k => $v) {
                if (! $callback($v, $k)) {
                    return false;
                }
            }

            return true;
        }

        return $this->every($this->operatorForWhere(...func_get_args()));
    }

    /**
     * Get the first item by the given key value pair.
     *
     * @param  callable|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue|null
     */
    public function firstWhere($key, $operator = null, $value = null)
    {
        return $this->first($this->operatorForWhere(...func_get_args()));
    }

    /**
     * Determine if the collection contains multiple items, optionally matching the given criteria.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function hasMany($key = null, $operator = null, $value = null): bool
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        return $this
            ->unless($filter == null)
            ->filter($filter)
            ->take(2)
            ->count() === 2;
    }

    /**
     * Get a single key's value from the first matching item in the collection.
     *
     * @template TValueDefault
     *
     * @param  string  $key
     * @param  TValueDefault|(\Closure(): TValueDefault)  $default
     * @return TValue|TValueDefault
     */
    public function value($key, $default = null)
    {
        $value = $this->first(function ($target) use ($key) {
            return data_has($target, $key);
        });

        return data_get($value, $key, $default);
    }

    /**
     * Ensure that every item in the collection is of the expected type.
     *
     * @template TEnsureOfType
     *
     * @param  class-string<TEnsureOfType>|array<array-key, class-string<TEnsureOfType>>|'string'|'int'|'float'|'bool'|'array'|'null'  $type
     * @return static<TKey, TEnsureOfType>
     *
     * @throws \UnexpectedValueException
     */
    public function ensure($type)
    {
        $allowedTypes = is_array($type) ? $type : [$type];

        return $this->each(function ($item, $index) use ($allowedTypes) {
            $itemType = get_debug_type($item);

            foreach ($allowedTypes as $allowedType) {
                if ($itemType === $allowedType || $item instanceof $allowedType) {
                    return true;
                }
            }

            throw new UnexpectedValueException(
                sprintf("Collection should only include [%s] items, but '%s' found at position %d.", implode(', ', $allowedTypes), $itemType, $index)
            );
        });
    }

    /**
     * Determine if the collection is not empty.
     *
     * @phpstan-assert-if-true TValue $this->first()
     * @phpstan-assert-if-true TValue $this->last()
     *
     * @phpstan-assert-if-false null $this->first()
     * @phpstan-assert-if-false null $this->last()
     *
     * @return bool
     */
    public function isNotEmpty()
    {
        return ! $this->isEmpty();
    }

    /**
     * Run a map over each nested chunk of items.
     *
     * @template TMapSpreadValue
     *
     * @param  callable(mixed...): TMapSpreadValue  $callback
     * @return static<TKey, TMapSpreadValue>
     */
    public function mapSpread(callable $callback)
    {
        return $this->map(function ($chunk, $key) use ($callback) {
            $chunk[] = $key;

            return $callback(...$chunk);
        });
    }

    /**
     * Run a grouping map over the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapToGroupsKey of array-key
     * @template TMapToGroupsValue
     *
     * @param  callable(TValue, TKey): array<TMapToGroupsKey, TMapToGroupsValue>  $callback
     * @return static<TMapToGroupsKey, static<int, TMapToGroupsValue>>
     */
    public function mapToGroups(callable $callback)
    {
        $groups = $this->mapToDictionary($callback);

        return $groups->map($this->make(...));
    }

    /**
     * Map a collection and flatten the result by a single level.
     *
     * @template TFlatMapKey of array-key
     * @template TFlatMapValue
     *
     * @param  callable(TValue, TKey): (\Illuminate\Support\Collection<TFlatMapKey, TFlatMapValue>|array<TFlatMapKey, TFlatMapValue>)  $callback
     * @return static<TFlatMapKey, TFlatMapValue>
     */
    public function flatMap(callable $callback)
    {
        return $this->map($callback)->collapse();
    }

    /**
     * Map the values into a new class.
     *
     * @template TMapIntoValue
     *
     * @param  class-string<TMapIntoValue>  $class
     * @return static<TKey, TMapIntoValue>
     */
    public function mapInto($class)
    {
        if (is_subclass_of($class, BackedEnum::class)) {
            return $this->map(fn ($value, $key) => $class::from($value));
        }

        return $this->map(fn ($value, $key) => new $class($value, $key));
    }

    /**
     * Get the min value of a given key.
     *
     * @template TMinResult = mixed
     *
     * @param  (callable(TValue): TMinResult)|string|null  $callback
     * @return ($callback is callable ? ?TMinResult : ($callback is null ? ?TValue : mixed))
     */
    public function min($callback = null)
    {
        $callback = $this->valueRetriever($callback);

        return $this->map(fn ($value) => $callback($value))
            ->reject(fn ($value) => is_null($value))
            ->reduce(fn ($result, $value) => is_null($result) || $value < $result ? $value : $result);
    }

    /**
     * Get the max value of a given key.
     *
     * @template TMaxResult = mixed
     *
     * @param  (callable(TValue): TMaxResult)|string|null  $callback
     * @return ($callback is callable ? ?TMaxResult : ($callback is null ? ?TValue : mixed))
     */
    public function max($callback = null)
    {
        $callback = $this->valueRetriever($callback);

        return $this->reject(fn ($value) => is_null($value))->reduce(function ($result, $item) use ($callback) {
            $value = $callback($item);

            return is_null($result) || $value > $result ? $value : $result;
        });
    }

    /**
     * "Paginate" the collection by slicing it into a smaller collection.
     *
     * @param  int  $page
     * @param  int  $perPage
     * @return static
     */
    public function forPage($page, $perPage)
    {
        $offset = max(0, ($page - 1) * $perPage);

        return $this->slice($offset, $perPage);
    }

    /**
     * Partition the collection into two arrays using the given callback or key.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return static<int<0, 1>, static<TKey, TValue>>
     */
    public function partition($key, $operator = null, $value = null)
    {
        $callback = func_num_args() === 1
            ? $this->valueRetriever($key)
            : $this->operatorForWhere(...func_get_args());

        [$passed, $failed] = Arr::partition($this->getIterator(), $callback);

        return $this->newInstance([$this->newInstance($passed), $this->newInstance($failed)]);
    }

    /**
     * Calculate the percentage of items that pass a given truth test.
     *
     * @param  (callable(TValue, TKey): bool)  $callback
     * @param  int  $precision
     * @return float|null
     */
    public function percentage(callable $callback, int $precision = 2)
    {
        if ($this->isEmpty()) {
            return null;
        }

        return round(
            $this->filter($callback)->count() / $this->count() * 100,
            $precision
        );
    }

    /**
     * Get the sum of the given values.
     *
     * @template TReturnType
     *
     * @param  (callable(TValue, TKey): TReturnType)|string|null  $callback
     * @return ($callback is callable ? TReturnType : mixed)
     */
    public function sum($callback = null)
    {
        $callback = is_null($callback)
            ? $this->identity()
            : $this->valueRetriever($callback);

        return $this->reduce(fn ($result, $item, $key) => $result + $callback($item, $key), 0);
    }

    /**
     * Apply the callback if the collection is empty.
     *
     * @template TWhenEmptyReturnType
     *
     * @param  (callable($this): TWhenEmptyReturnType)  $callback
     * @param  (callable($this): TWhenEmptyReturnType)|null  $default
     * @return $this|TWhenEmptyReturnType
     */
    public function whenEmpty(callable $callback, ?callable $default = null)
    {
        return $this->when($this->isEmpty(), $callback, $default);
    }

    /**
     * Apply the callback if the collection is not empty.
     *
     * @template TWhenNotEmptyReturnType
     *
     * @param  callable($this): TWhenNotEmptyReturnType  $callback
     * @param  (callable($this): TWhenNotEmptyReturnType)|null  $default
     * @return $this|TWhenNotEmptyReturnType
     */
    public function whenNotEmpty(callable $callback, ?callable $default = null)
    {
        return $this->when($this->isNotEmpty(), $callback, $default);
    }

    /**
     * Apply the callback unless the collection is empty.
     *
     * @template TUnlessEmptyReturnType
     *
     * @param  callable($this): TUnlessEmptyReturnType  $callback
     * @param  (callable($this): TUnlessEmptyReturnType)|null  $default
     * @return $this|TUnlessEmptyReturnType
     */
    public function unlessEmpty(callable $callback, ?callable $default = null)
    {
        return $this->whenNotEmpty($callback, $default);
    }

    /**
     * Apply the callback unless the collection is not empty.
     *
     * @template TUnlessNotEmptyReturnType
     *
     * @param  callable($this): TUnlessNotEmptyReturnType  $callback
     * @param  (callable($this): TUnlessNotEmptyReturnType)|null  $default
     * @return $this|TUnlessNotEmptyReturnType
     */
    public function unlessNotEmpty(callable $callback, ?callable $default = null)
    {
        return $this->whenEmpty($callback, $default);
    }

    /**
     * Filter items by the given key value pair.
     *
     * @param  callable|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return static
     */
    public function where($key, $operator = null, $value = null)
    {
        return $this->filter($this->operatorForWhere(...func_get_args()));
    }

    /**
     * Filter items where the value for the given key is null.
     *
     * @param  string|null  $key
     * @return static
     */
    public function whereNull($key = null)
    {
        return $this->whereStrict($key, null);
    }

    /**
     * Filter items where the value for the given key is not null.
     *
     * @param  string|null  $key
     * @return static
     */
    public function whereNotNull($key = null)
    {
        return $this->where($key, '!==', null);
    }

    /**
     * Filter items by the given key value pair using strict comparison.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return static
     */
    public function whereStrict($key, $value)
    {
        return $this->where($key, '===', $value);
    }

    /**
     * Filter items by the given key value pair.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @param  bool  $strict
     * @return static
     */
    public function whereIn($key, $values, $strict = false)
    {
        $values = $this->getArrayableItems($values);

        return $this->filter(fn ($item) => in_array(data_get($item, $key), $values, $strict));
    }

    /**
     * Filter items by the given key value pair using strict comparison.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereInStrict($key, $values)
    {
        return $this->whereIn($key, $values, true);
    }

    /**
     * Filter items such that the value of the given key is between the given values.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereBetween($key, $values)
    {
        return $this->where($key, '>=', reset($values))->where($key, '<=', end($values));
    }

    /**
     * Filter items such that the value of the given key is not between the given values.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereNotBetween($key, $values)
    {
        return $this->filter(
            fn ($item) => data_get($item, $key) < reset($values) || data_get($item, $key) > end($values)
        );
    }

    /**
     * Filter items by the given key value pair.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @param  bool  $strict
     * @return static
     */
    public function whereNotIn($key, $values, $strict = false)
    {
        $values = $this->getArrayableItems($values);

        return $this->reject(fn ($item) => in_array(data_get($item, $key), $values, $strict));
    }

    /**
     * Filter items by the given key value pair using strict comparison.
     *
     * @param  string  $key
     * @param  \Illuminate\Contracts\Support\Arrayable|iterable  $values
     * @return static
     */
    public function whereNotInStrict($key, $values)
    {
        return $this->whereNotIn($key, $values, true);
    }

    /**
     * Filter the items, removing any items that don't match the given type(s).
     *
     * @template TWhereInstanceOf
     *
     * @param  class-string<TWhereInstanceOf>|array<array-key, class-string<TWhereInstanceOf>>  $type
     * @return static<TKey, TWhereInstanceOf>
     */
    public function whereInstanceOf($type)
    {
        return $this->filter(function ($value) use ($type) {
            if (is_array($type)) {
                foreach ($type as $classType) {
                    if ($value instanceof $classType) {
                        return true;
                    }
                }

                return false;
            }

            return $value instanceof $type;
        });
    }

    /**
     * Pass the collection to the given callback and return the result.
     *
     * @template TPipeReturnType
     *
     * @param  callable($this): TPipeReturnType  $callback
     * @return TPipeReturnType
     */
    public function pipe(callable $callback)
    {
        return $callback($this);
    }

    /**
     * Pass the collection into a new class.
     *
     * @template TPipeIntoValue
     *
     * @param  class-string<TPipeIntoValue>  $class
     * @return TPipeIntoValue
     */
    public function pipeInto($class)
    {
        return new $class($this);
    }

    /**
     * Pass the collection through a series of callable pipes and return the result.
     *
     * @param  array<callable>  $callbacks
     * @return mixed
     */
    public function pipeThrough($callbacks)
    {
        return (new Collection($callbacks))->reduce(
            fn ($carry, $callback) => $callback($carry),
            $this,
        );
    }

    /**
     * Reduce the collection to a single value.
     *
     * @template TReduceInitial
     * @template TReduceReturnType
     *
     * @param  callable(TReduceInitial|TReduceReturnType, TValue, TKey): TReduceReturnType  $callback
     * @param  TReduceInitial  $initial
     * @return TReduceReturnType
     */
    public function reduce(callable $callback, $initial = null)
    {
        $result = $initial;

        foreach ($this as $key => $value) {
            $result = $callback($result, $value, $key);
        }

        return $result;
    }

    /**
     * Reduce the collection to multiple aggregate values.
     *
     * @param  callable  $callback
     * @param  mixed  ...$initial
     * @return array
     *
     * @throws \UnexpectedValueException
     */
    public function reduceSpread(callable $callback, ...$initial)
    {
        $result = $initial;

        foreach ($this as $key => $value) {
            $result = call_user_func_array($callback, array_merge($result, [$value, $key]));

            if (! is_array($result)) {
                throw new UnexpectedValueException(sprintf(
                    "%s::reduceSpread expects reducer to return an array, but got a '%s' instead.",
                    class_basename(static::class), gettype($result)
                ));
            }
        }

        return $result;
    }

    /**
     * Reduce an associative collection to a single value.
     *
     * @template TReduceWithKeysInitial
     * @template TReduceWithKeysReturnType
     *
     * @param  callable(TReduceWithKeysInitial|TReduceWithKeysReturnType, TValue, TKey): TReduceWithKeysReturnType  $callback
     * @param  TReduceWithKeysInitial  $initial
     * @return TReduceWithKeysReturnType
     */
    public function reduceWithKeys(callable $callback, $initial = null)
    {
        return $this->reduce($callback, $initial);
    }

    /**
     * Create a collection of all elements that do not pass a given truth test.
     *
     * @param  (callable(TValue, TKey): bool)|bool|TValue  $callback
     * @return static
     */
    public function reject($callback = true)
    {
        $useAsCallable = $this->useAsCallable($callback);

        return $this->filter(function ($value, $key) use ($callback, $useAsCallable) {
            return $useAsCallable
                ? ! $callback($value, $key)
                : $value != $callback;
        });
    }

    /**
     * Pass the collection to the given callback and then return it.
     *
     * @param  callable($this): mixed  $callback
     * @return $this
     */
    public function tap(callable $callback)
    {
        $callback($this);

        return $this;
    }

    /**
     * Return only unique items from the collection array.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $key
     * @param  bool  $strict
     * @return static
     */
    public function unique($key = null, $strict = false)
    {
        $callback = $this->valueRetriever($key);

        $exists = [];

        return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
            if (in_array($id = $callback($item, $key), $exists, $strict)) {
                return true;
            }

            $exists[] = $id;
        });
    }

    /**
     * Return only unique items from the collection array using strict comparison.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $key
     * @return static
     */
    public function uniqueStrict($key = null)
    {
        return $this->unique($key, true);
    }

    /**
     * Collect the values into a collection.
     *
     * @return \Illuminate\Support\Collection<TKey, TValue>
     */
    public function collect()
    {
        return new Collection($this->all());
    }

    /**
     * Get the collection of items as a plain array.
     *
     * @return array<TKey, mixed>
     */
    public function toArray()
    {
        return $this->map(fn ($value) => $value instanceof Arrayable ? $value->toArray() : $value)->all();
    }

    /**
     * Convert the object into something JSON serializable.
     *
     * @return array<TKey, mixed>
     */
    public function jsonSerialize(): array
    {
        return array_map(function ($value) {
            return match (true) {
                $value instanceof JsonSerializable => $value->jsonSerialize(),
                $value instanceof Jsonable => json_decode($value->toJson(), true),
                $value instanceof Arrayable => $value->toArray(),
                default => $value,
            };
        }, $this->all());
    }

    /**
     * Get the collection of items as JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0)
    {
        return json_encode($this->jsonSerialize(), $options);
    }

    /**
     * Get the collection of items as pretty print formatted JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toPrettyJson(int $options = 0)
    {
        return $this->toJson(JSON_PRETTY_PRINT | $options);
    }

    /**
     * Get a CachingIterator instance.
     *
     * @param  int  $flags
     * @return \CachingIterator
     */
    public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
    {
        return new CachingIterator($this->getIterator(), $flags);
    }

    /**
     * Convert the collection to its string representation.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->escapeWhenCastingToString
            ? e($this->toJson())
            : $this->toJson();
    }

    /**
     * Indicate that the model's string representation should be escaped when __toString is invoked.
     *
     * @param  bool  $escape
     * @return $this
     */
    public function escapeWhenCastingToString($escape = true)
    {
        $this->escapeWhenCastingToString = $escape;

        return $this;
    }

    /**
     * Add a method to the list of proxied methods.
     *
     * @param  string  $method
     * @return void
     */
    public static function proxy($method)
    {
        static::$proxies[] = $method;
    }

    /**
     * Dynamically access collection proxies.
     *
     * @param  string  $key
     * @return mixed
     *
     * @throws \Exception
     */
    public function __get($key)
    {
        if (! in_array($key, static::$proxies)) {
            throw new Exception("Property [{$key}] does not exist on this collection instance.");
        }

        return new HigherOrderCollectionProxy($this, $key);
    }

    /**
     * Results array of items from Collection or Arrayable.
     *
     * @param  mixed  $items
     * @return array<TKey, TValue>
     */
    protected function getArrayableItems($items)
    {
        return is_null($items) || is_scalar($items) || $items instanceof UnitEnum
            ? Arr::wrap($items)
            : Arr::from($items);
    }

    /**
     * Get an operator checker callback.
     *
     * @param  callable|string  $key
     * @param  string|null  $operator
     * @param  mixed  $value
     * @return \Closure
     */
    protected function operatorForWhere($key, $operator = null, $value = null)
    {
        if ($this->useAsCallable($key)) {
            return $key;
        }

        if (func_num_args() === 1) {
            $value = true;

            $operator = '=';
        }

        if (func_num_args() === 2) {
            $value = $operator;

            $operator = '=';
        }

        return function ($item) use ($key, $operator, $value) {
            $retrieved = enum_value(data_get($item, $key));
            $value = enum_value($value);

            $strings = array_filter([$retrieved, $value], function ($value) {
                return match (true) {
                    is_string($value) => true,
                    $value instanceof \Stringable => true,
                    default => false,
                };
            });

            if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) {
                return in_array($operator, ['!=', '<>', '!==']);
            }

            switch ($operator) {
                default:
                case '=':
                case '==':  return $retrieved == $value;
                case '!=':
                case '<>':  return $retrieved != $value;
                case '<':   return $retrieved < $value;
                case '>':   return $retrieved > $value;
                case '<=':  return $retrieved <= $value;
                case '>=':  return $retrieved >= $value;
                case '===': return $retrieved === $value;
                case '!==': return $retrieved !== $value;
                case '<=>': return $retrieved <=> $value;
            }
        };
    }

    /**
     * Determine if the given value is callable, but not a string.
     *
     * @param  mixed  $value
     * @return bool
     */
    protected function useAsCallable($value)
    {
        return ! is_string($value) && is_callable($value);
    }

    /**
     * Get a value retrieving callback.
     *
     * @param  callable|string|null  $value
     * @return callable
     */
    protected function valueRetriever($value)
    {
        if ($this->useAsCallable($value)) {
            return $value;
        }

        return fn ($item) => data_get($item, $value);
    }

    /**
     * Make a function to check an item's equality.
     *
     * @param  mixed  $value
     * @return \Closure(mixed): bool
     */
    protected function equality($value)
    {
        return fn ($item) => $item === $value;
    }

    /**
     * Make a function using another function, by negating its result.
     *
     * @param  \Closure  $callback
     * @return \Closure
     */
    protected function negate(Closure $callback)
    {
        return fn (...$params) => ! $callback(...$params);
    }

    /**
     * Make a function that returns what's passed to it.
     *
     * @return \Closure(TValue): TValue
     */
    protected function identity()
    {
        return fn ($value) => $value;
    }
}
<?php

namespace Illuminate\Support\Traits;

use Illuminate\Database\Eloquent\Attributes\UseResource;
use Illuminate\Database\Eloquent\Attributes\UseResourceCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\ResourceCollection;
use LogicException;
use ReflectionClass;

trait TransformsToResourceCollection
{
    /**
     * Create a new resource collection instance for the given resource.
     *
     * @param  class-string<\Illuminate\Http\Resources\Json\JsonResource>|null  $resourceClass
     * @return \Illuminate\Http\Resources\Json\ResourceCollection
     *
     * @throws \Throwable
     */
    public function toResourceCollection(?string $resourceClass = null): ResourceCollection
    {
        if ($resourceClass === null) {
            return $this->guessResourceCollection();
        }

        return $resourceClass::collection($this);
    }

    /**
     * Guess the resource collection for the items.
     *
     * @return \Illuminate\Http\Resources\Json\ResourceCollection
     *
     * @throws \Throwable
     */
    protected function guessResourceCollection(): ResourceCollection
    {
        if ($this->isEmpty()) {
            return new ResourceCollection($this);
        }

        $model = $this->items[0] ?? null;

        throw_unless(is_object($model), LogicException::class, 'Resource collection guesser expects the collection to contain objects.');

        /** @var class-string<Model> $className */
        $className = get_class($model);

        throw_unless(method_exists($className, 'guessResourceName'), LogicException::class, sprintf('Expected class %s to implement guessResourceName method. Make sure the model uses the TransformsToResource trait.', $className));

        $useResourceCollection = $this->resolveResourceCollectionFromAttribute($className);

        if ($useResourceCollection !== null && class_exists($useResourceCollection)) {
            return new $useResourceCollection($this);
        }

        $useResource = $this->resolveResourceFromAttribute($className);

        if ($useResource !== null && class_exists($useResource)) {
            return $useResource::collection($this);
        }

        $resourceClasses = $className::guessResourceName();

        foreach ($resourceClasses as $resourceClass) {
            $resourceCollection = $resourceClass.'Collection';

            if (is_string($resourceCollection) && class_exists($resourceCollection)) {
                return new $resourceCollection($this);
            }
        }

        foreach ($resourceClasses as $resourceClass) {
            if (is_string($resourceClass) && class_exists($resourceClass)) {
                return $resourceClass::collection($this);
            }
        }

        throw new LogicException(sprintf('Failed to find resource class for model [%s].', $className));
    }

    /**
     * Get the resource class from the class attribute.
     *
     * @param  class-string<\Illuminate\Http\Resources\Json\JsonResource>  $class
     * @return class-string<*>|null
     */
    protected function resolveResourceFromAttribute(string $class): ?string
    {
        if (! class_exists($class)) {
            return null;
        }

        $attributes = (new ReflectionClass($class))->getAttributes(UseResource::class);

        return $attributes !== []
            ? $attributes[0]->newInstance()->class
            : null;
    }

    /**
     * Get the resource collection class from the class attribute.
     *
     * @param  class-string<\Illuminate\Http\Resources\Json\ResourceCollection>  $class
     * @return class-string<*>|null
     */
    protected function resolveResourceCollectionFromAttribute(string $class): ?string
    {
        if (! class_exists($class)) {
            return null;
        }

        $attributes = (new ReflectionClass($class))->getAttributes(UseResourceCollection::class);

        return $attributes !== []
            ? $attributes[0]->newInstance()->class
            : null;
    }
}
<?php

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

if (! function_exists('collect')) {
    /**
     * Create a collection from the given value.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|null  $value
     * @return \Illuminate\Support\Collection<TKey, TValue>
     */
    function collect($value = []): Collection
    {
        return new Collection($value);
    }
}

if (! function_exists('data_fill')) {
    /**
     * Fill in data where it's missing.
     *
     * @param  mixed  $target
     * @param  string|array  $key
     * @param  mixed  $value
     * @return mixed
     */
    function data_fill(&$target, $key, $value)
    {
        return data_set($target, $key, $value, false);
    }
}

if (! function_exists('data_has')) {
    /**
     * Determine if a key / property exists on an array or object using "dot" notation.
     *
     * @param  mixed  $target
     * @param  string|array|int|null  $key
     * @return bool
     */
    function data_has($target, $key): bool
    {
        if (is_null($key) || $key === []) {
            return false;
        }

        $key = is_array($key) ? $key : explode('.', $key);

        foreach ($key as $segment) {
            if (Arr::accessible($target) && Arr::exists($target, $segment)) {
                $target = $target[$segment];
            } elseif (is_object($target) && property_exists($target, $segment)) {
                $target = $target->{$segment};
            } else {
                return false;
            }
        }

        return true;
    }
}

if (! function_exists('data_get')) {
    /**
     * Get an item from an array or object using "dot" notation.
     *
     * @param  mixed  $target
     * @param  string|array|int|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    function data_get($target, $key, $default = null)
    {
        if (is_null($key)) {
            return $target;
        }

        $key = is_array($key) ? $key : explode('.', $key);

        foreach ($key as $i => $segment) {
            unset($key[$i]);

            if (is_null($segment)) {
                return $target;
            }

            if ($segment === '*') {
                if ($target instanceof Collection) {
                    $target = $target->all();
                } elseif (! is_iterable($target)) {
                    return value($default);
                }

                $result = [];

                foreach ($target as $item) {
                    $result[] = data_get($item, $key);
                }

                return in_array('*', $key) ? Arr::collapse($result) : $result;
            }

            $segment = match ($segment) {
                '\*' => '*',
                '\{first}' => '{first}',
                '{first}' => array_key_first(Arr::from($target)),
                '\{last}' => '{last}',
                '{last}' => array_key_last(Arr::from($target)),
                default => $segment,
            };

            if (Arr::accessible($target) && Arr::exists($target, $segment)) {
                $target = $target[$segment];
            } elseif (is_object($target) && isset($target->{$segment})) {
                $target = $target->{$segment};
            } else {
                return value($default);
            }
        }

        return $target;
    }
}

if (! function_exists('data_set')) {
    /**
     * Set an item on an array or object using dot notation.
     *
     * @param  mixed  $target
     * @param  string|array  $key
     * @param  mixed  $value
     * @param  bool  $overwrite
     * @return mixed
     */
    function data_set(&$target, $key, $value, $overwrite = true)
    {
        $segments = is_array($key) ? $key : explode('.', $key);

        if (($segment = array_shift($segments)) === '*') {
            if (! Arr::accessible($target)) {
                $target = [];
            }

            if ($segments) {
                foreach ($target as &$inner) {
                    data_set($inner, $segments, $value, $overwrite);
                }
            } elseif ($overwrite) {
                foreach ($target as &$inner) {
                    $inner = $value;
                }
            }
        } elseif (Arr::accessible($target)) {
            if ($segments) {
                if (! Arr::exists($target, $segment)) {
                    $target[$segment] = [];
                }

                data_set($target[$segment], $segments, $value, $overwrite);
            } elseif ($overwrite || ! Arr::exists($target, $segment)) {
                $target[$segment] = $value;
            }
        } elseif (is_object($target)) {
            if ($segments) {
                if (! isset($target->{$segment})) {
                    $target->{$segment} = [];
                }

                data_set($target->{$segment}, $segments, $value, $overwrite);
            } elseif ($overwrite || ! isset($target->{$segment})) {
                $target->{$segment} = $value;
            }
        } else {
            $target = [];

            if ($segments) {
                data_set($target[$segment], $segments, $value, $overwrite);
            } elseif ($overwrite) {
                $target[$segment] = $value;
            }
        }

        return $target;
    }
}

if (! function_exists('data_forget')) {
    /**
     * Remove / unset an item from an array or object using "dot" notation.
     *
     * @param  mixed  $target
     * @param  string|array|int|null  $key
     * @return mixed
     */
    function data_forget(&$target, $key)
    {
        $segments = is_array($key) ? $key : explode('.', $key);

        if (($segment = array_shift($segments)) === '*' && Arr::accessible($target)) {
            if ($segments) {
                foreach ($target as &$inner) {
                    data_forget($inner, $segments);
                }
            }
        } elseif (Arr::accessible($target)) {
            if ($segments && Arr::exists($target, $segment)) {
                data_forget($target[$segment], $segments);
            } else {
                Arr::forget($target, $segment);
            }
        } elseif (is_object($target)) {
            if ($segments && isset($target->{$segment})) {
                data_forget($target->{$segment}, $segments);
            } elseif (isset($target->{$segment})) {
                unset($target->{$segment});
            }
        }

        return $target;
    }
}

if (! function_exists('head')) {
    /**
     * Get the first element of an array. Useful for method chaining.
     *
     * @param  array  $array
     * @return mixed
     */
    function head($array)
    {
        return empty($array) ? false : array_first($array);
    }
}

if (! function_exists('last')) {
    /**
     * Get the last element from an array.
     *
     * @param  array  $array
     * @return mixed
     */
    function last($array)
    {
        return empty($array) ? false : array_last($array);
    }
}

if (! function_exists('value')) {
    /**
     * Return the default value of the given value.
     *
     * @template TValue
     * @template TArgs
     *
     * @param  TValue|\Closure(TArgs): TValue  $value
     * @param  TArgs  ...$args
     * @return TValue
     */
    function value($value, ...$args)
    {
        return $value instanceof Closure ? $value(...$args) : $value;
    }
}

if (! function_exists('when')) {
    /**
     * Return a value if the given condition is true.
     *
     * @template TValue
     * @template TArgs
     * @template TDefault
     *
     * @param  mixed  $condition
     * @param  TValue|\Closure(TArgs): TValue  $value
     * @param  TDefault|\Closure(): TDefault  $default
     * @return ($condition is true|positive-int|non-falsy-string|non-empty-array ? TValue : ($condition is callable ? TValue|TDefault : TDefault))
     */
    function when($condition, $value, $default = null)
    {
        $condition = $condition instanceof Closure ? $condition() : $condition;

        if ($condition) {
            return value($value, $condition);
        }

        return value($default, $condition);
    }
}
<?php

namespace Illuminate\Support;

use ArrayIterator;
use Closure;
use DateInterval;
use DateTimeImmutable;
use DateTimeInterface;
use Generator;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Support\Traits\EnumeratesValues;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use IteratorAggregate;
use stdClass;
use Traversable;

/**
 * @template TKey of array-key
 *
 * @template-covariant TValue
 *
 * @implements \Illuminate\Support\Enumerable<TKey, TValue>
 */
class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
{
    /**
     * @use \Illuminate\Support\Traits\EnumeratesValues<TKey, TValue>
     */
    use EnumeratesValues, Macroable;

    /**
     * The source from which to generate items.
     *
     * @var (Closure(): \Generator<TKey, TValue, mixed, void>)|static|array<TKey, TValue>
     */
    public $source;

    /**
     * Create a new lazy collection instance.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|(Closure(): \Generator<TKey, TValue, mixed, void>)|self<TKey, TValue>|array<TKey, TValue>|null  $source
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($source = null)
    {
        if ($source instanceof Closure || $source instanceof self) {
            $this->source = $source;
        } elseif (is_null($source)) {
            $this->source = static::empty();
        } elseif ($source instanceof Generator) {
            throw new InvalidArgumentException(
                'Generators should not be passed directly to LazyCollection. Instead, pass a generator function.'
            );
        } else {
            $this->source = $this->getArrayableItems($source);
        }
    }

    /**
     * Create a new instance of the collection.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|(Closure(): \Generator<TKey, TValue, mixed, void>)|self<TKey, TValue>|array<TKey, TValue>|null  $items
     * @return static
     */
    protected function newInstance($items = [])
    {
        return new static($items);
    }

    /**
     * Create a new collection instance if the value isn't one already.
     *
     * @template TMakeKey of array-key
     * @template TMakeValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TMakeKey, TMakeValue>|iterable<TMakeKey, TMakeValue>|(Closure(): \Generator<TMakeKey, TMakeValue, mixed, void>)|self<TMakeKey, TMakeValue>|array<TMakeKey, TMakeValue>|null  $items
     * @return static<TMakeKey, TMakeValue>
     */
    public static function make($items = [], ...$args)
    {
        return new static($items, ...$args);
    }

    /**
     * Create a collection with the given range.
     *
     * @param  int  $from
     * @param  int  $to
     * @param  int  $step
     * @return ($step is zero ? never : static<int, int>)
     *
     * @throws \InvalidArgumentException
     */
    public static function range($from, $to, $step = 1, ...$args)
    {
        if ($step == 0) {
            throw new InvalidArgumentException('Step value cannot be zero.');
        }

        return new static(function () use ($from, $to, $step) {
            if ($from <= $to) {
                for (; $from <= $to; $from += abs($step)) {
                    yield $from;
                }
            } else {
                for (; $from >= $to; $from -= abs($step)) {
                    yield $from;
                }
            }
        });
    }

    /**
     * Get all items in the enumerable.
     *
     * @return array<TKey, TValue>
     */
    public function all()
    {
        if (is_array($this->source)) {
            return $this->source;
        }

        return iterator_to_array($this->getIterator());
    }

    /**
     * Eager load all items into a new lazy collection backed by an array.
     *
     * @return static<TKey, TValue>
     */
    public function eager()
    {
        return new static($this->all());
    }

    /**
     * Cache values as they're enumerated.
     *
     * @return static<TKey, TValue>
     */
    public function remember()
    {
        $iterator = $this->getIterator();

        $iteratorIndex = 0;

        $cache = [];

        return new static(function () use ($iterator, &$iteratorIndex, &$cache) {
            for ($index = 0; true; $index++) {
                if (array_key_exists($index, $cache)) {
                    yield $cache[$index][0] => $cache[$index][1];

                    continue;
                }

                if ($iteratorIndex < $index) {
                    $iterator->next();

                    $iteratorIndex++;
                }

                if (! $iterator->valid()) {
                    break;
                }

                $cache[$index] = [$iterator->key(), $iterator->current()];

                yield $cache[$index][0] => $cache[$index][1];
            }
        });
    }

    /**
     * Get the median of a given key.
     *
     * @param  string|array<array-key, string>|null  $key
     * @return float|int|null
     */
    public function median($key = null)
    {
        return $this->collect()->median($key);
    }

    /**
     * Get the mode of a given key.
     *
     * @param  string|array<string>|null  $key
     * @return array<int, float|int>|null
     */
    public function mode($key = null)
    {
        return $this->collect()->mode($key);
    }

    /**
     * Collapse the collection of items into a single array.
     *
     * @return static<int, mixed>
     */
    public function collapse()
    {
        return new static(function () {
            foreach ($this as $values) {
                if (is_array($values) || $values instanceof Enumerable) {
                    foreach ($values as $value) {
                        yield $value;
                    }
                }
            }
        });
    }

    /**
     * Collapse the collection of items into a single array while preserving its keys.
     *
     * @return static<mixed, mixed>
     */
    public function collapseWithKeys()
    {
        return new static(function () {
            foreach ($this as $values) {
                if (is_array($values) || $values instanceof Enumerable) {
                    foreach ($values as $key => $value) {
                        yield $key => $value;
                    }
                }
            }
        });
    }

    /**
     * Determine if an item exists in the enumerable.
     *
     * @param  (callable(TValue, TKey): bool)|TValue|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function contains($key, $operator = null, $value = null)
    {
        if (func_num_args() === 1 && $this->useAsCallable($key)) {
            $placeholder = new stdClass;

            /** @var callable $key */
            return $this->first($key, $placeholder) !== $placeholder;
        }

        if (func_num_args() === 1) {
            $needle = $key;

            foreach ($this as $value) {
                if ($value == $needle) {
                    return true;
                }
            }

            return false;
        }

        return $this->contains($this->operatorForWhere(...func_get_args()));
    }

    /**
     * Determine if an item exists, using strict comparison.
     *
     * @param  (callable(TValue): bool)|TValue|array-key  $key
     * @param  TValue|null  $value
     * @return bool
     */
    public function containsStrict($key, $value = null)
    {
        if (func_num_args() === 2) {
            return $this->contains(fn ($item) => data_get($item, $key) === $value);
        }

        if ($this->useAsCallable($key)) {
            return ! is_null($this->first($key));
        }

        foreach ($this as $item) {
            if ($item === $key) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if an item is not contained in the enumerable.
     *
     * @param  mixed  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function doesntContain($key, $operator = null, $value = null)
    {
        return ! $this->contains(...func_get_args());
    }

    /**
     * Determine if an item is not contained in the enumerable, using strict comparison.
     *
     * @param  mixed  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function doesntContainStrict($key, $operator = null, $value = null)
    {
        return ! $this->containsStrict(...func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function crossJoin(...$arrays)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function countBy($countBy = null)
    {
        $countBy = is_null($countBy)
            ? $this->identity()
            : $this->valueRetriever($countBy);

        return new static(function () use ($countBy) {
            $counts = [];

            foreach ($this as $key => $value) {
                $group = enum_value($countBy($value, $key));

                if (empty($counts[$group])) {
                    $counts[$group] = 0;
                }

                $counts[$group]++;
            }

            yield from $counts;
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function diff($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function diffUsing($items, callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function diffAssoc($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function diffAssocUsing($items, callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function diffKeys($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function diffKeysUsing($items, callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function duplicates($callback = null, $strict = false)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function duplicatesStrict($callback = null)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function except($keys)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Run a filter over each of the items.
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @return static
     */
    public function filter(?callable $callback = null)
    {
        if (is_null($callback)) {
            $callback = fn ($value) => (bool) $value;
        }

        return new static(function () use ($callback) {
            foreach ($this as $key => $value) {
                if ($callback($value, $key)) {
                    yield $key => $value;
                }
            }
        });
    }

    /**
     * Get the first item from the enumerable passing the given truth test.
     *
     * @template TFirstDefault
     *
     * @param  (callable(TValue): bool)|null  $callback
     * @param  TFirstDefault|(\Closure(): TFirstDefault)  $default
     * @return TValue|TFirstDefault
     */
    public function first(?callable $callback = null, $default = null)
    {
        $iterator = $this->getIterator();

        if (is_null($callback)) {
            if (! $iterator->valid()) {
                return value($default);
            }

            return $iterator->current();
        }

        foreach ($iterator as $key => $value) {
            if ($callback($value, $key)) {
                return $value;
            }
        }

        return value($default);
    }

    /**
     * Get a flattened list of the items in the collection.
     *
     * @param  int  $depth
     * @return static<int, mixed>
     */
    public function flatten($depth = INF)
    {
        $instance = new static(function () use ($depth) {
            foreach ($this as $item) {
                if (! is_array($item) && ! $item instanceof Enumerable) {
                    yield $item;
                } elseif ($depth === 1) {
                    yield from $item;
                } else {
                    yield from (new static($item))->flatten($depth - 1);
                }
            }
        });

        return $instance->values();
    }

    /**
     * Flip the items in the collection.
     *
     * @return static<TValue, TKey>
     */
    public function flip()
    {
        return new static(function () {
            foreach ($this as $key => $value) {
                yield $value => $key;
            }
        });
    }

    /**
     * Get an item by key.
     *
     * @template TGetDefault
     *
     * @param  TKey|null  $key
     * @param  TGetDefault|(\Closure(): TGetDefault)  $default
     * @return TValue|TGetDefault
     */
    public function get($key, $default = null)
    {
        if (is_null($key)) {
            return;
        }

        foreach ($this as $outerKey => $outerValue) {
            if ($outerKey == $key) {
                return $outerValue;
            }
        }

        return value($default);
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function groupBy($groupBy, $preserveKeys = false)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function keyBy($keyBy)
    {
        return new static(function () use ($keyBy) {
            $keyBy = $this->valueRetriever($keyBy);

            foreach ($this as $key => $item) {
                $resolvedKey = $keyBy($item, $key);

                if ($resolvedKey instanceof \UnitEnum) {
                    $resolvedKey = enum_value($resolvedKey);
                }

                if (is_object($resolvedKey)) {
                    $resolvedKey = (string) $resolvedKey;
                }

                yield $resolvedKey => $item;
            }
        });
    }

    /**
     * Determine if an item exists in the collection by key.
     *
     * @param  mixed  $key
     * @return bool
     */
    public function has($key)
    {
        $keys = array_flip(is_array($key) ? $key : func_get_args());

        foreach ($this as $key => $value) {
            unset($keys[$key]);

            if (empty($keys)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if any of the keys exist in the collection.
     *
     * @param  mixed  $key
     * @return bool
     */
    public function hasAny($key)
    {
        $keys = array_flip(is_array($key) ? $key : func_get_args());

        foreach ($this as $key => $value) {
            if (array_key_exists($key, $keys)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Concatenate values of a given key as a string.
     *
     * @param  (callable(TValue, TKey): mixed)|string  $value
     * @param  string|null  $glue
     * @return string
     */
    public function implode($value, $glue = null)
    {
        return $this->collect()->implode(...func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function intersect($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function intersectUsing($items, callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function intersectAssoc($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function intersectAssocUsing($items, callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function intersectByKeys($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Determine if the items are empty or not.
     *
     * @return bool
     */
    public function isEmpty()
    {
        return ! $this->getIterator()->valid();
    }

    /**
     * Determine if the collection contains a single item.
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @return bool
     *
     * @deprecated 12.49.0 Use the `hasSole()` method instead.
     */
    public function containsOneItem(?callable $callback = null): bool
    {
        return $this->hasSole($callback);
    }

    /**
     * Determine if the collection contains multiple items.
     *
     * @return bool
     *
     * @deprecated 12.50.0 Use the `hasMany()` method instead.
     */
    public function containsManyItems(): bool
    {
        return $this->hasMany();
    }

    /**
     * Join all items from the collection using a string. The final items can use a separate glue string.
     *
     * @param  string  $glue
     * @param  string  $finalGlue
     * @return string
     */
    public function join($glue, $finalGlue = '')
    {
        return $this->collect()->join(...func_get_args());
    }

    /**
     * Get the keys of the collection items.
     *
     * @return static<int, TKey>
     */
    public function keys()
    {
        return new static(function () {
            foreach ($this as $key => $value) {
                yield $key;
            }
        });
    }

    /**
     * Get the last item from the collection.
     *
     * @template TLastDefault
     *
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @param  TLastDefault|(\Closure(): TLastDefault)  $default
     * @return TValue|TLastDefault
     */
    public function last(?callable $callback = null, $default = null)
    {
        $needle = $placeholder = new stdClass;

        foreach ($this as $key => $value) {
            if (is_null($callback) || $callback($value, $key)) {
                $needle = $value;
            }
        }

        return $needle === $placeholder ? value($default) : $needle;
    }

    /**
     * Get the values of a given key.
     *
     * @param  string|array<array-key, string>  $value
     * @param  string|null  $key
     * @return static<array-key, mixed>
     */
    public function pluck($value, $key = null)
    {
        return new static(function () use ($value, $key) {
            [$value, $key] = $this->explodePluckParameters($value, $key);

            foreach ($this as $item) {
                $itemValue = $value instanceof Closure
                    ? $value($item)
                    : data_get($item, $value);

                if (is_null($key)) {
                    yield $itemValue;
                } else {
                    $itemKey = $key instanceof Closure
                        ? $key($item)
                        : data_get($item, $key);

                    if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
                        $itemKey = (string) $itemKey;
                    }

                    yield $itemKey => $itemValue;
                }
            }
        });
    }

    /**
     * Run a map over each of the items.
     *
     * @template TMapValue
     *
     * @param  callable(TValue, TKey): TMapValue  $callback
     * @return static<TKey, TMapValue>
     */
    public function map(callable $callback)
    {
        return new static(function () use ($callback) {
            foreach ($this as $key => $value) {
                yield $key => $callback($value, $key);
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function mapToDictionary(callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Run an associative map over each of the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TMapWithKeysKey of array-key
     * @template TMapWithKeysValue
     *
     * @param  callable(TValue, TKey): array<TMapWithKeysKey, TMapWithKeysValue>  $callback
     * @return static<TMapWithKeysKey, TMapWithKeysValue>
     */
    public function mapWithKeys(callable $callback)
    {
        return new static(function () use ($callback) {
            foreach ($this as $key => $value) {
                yield from $callback($value, $key);
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function merge($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function mergeRecursive($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Multiply the items in the collection by the multiplier.
     *
     * @param  int  $multiplier
     * @return static
     */
    public function multiply(int $multiplier)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Create a collection by using this collection for keys and another for its values.
     *
     * @template TCombineValue
     *
     * @param  \IteratorAggregate<array-key, TCombineValue>|array<array-key, TCombineValue>|(callable(): \Generator<array-key, TCombineValue>)  $values
     * @return static<TValue, TCombineValue>
     */
    public function combine($values)
    {
        return new static(function () use ($values) {
            $values = $this->makeIterator($values);

            $errorMessage = 'Both parameters should have an equal number of elements';

            foreach ($this as $key) {
                if (! $values->valid()) {
                    trigger_error($errorMessage, E_USER_WARNING);

                    break;
                }

                yield $key => $values->current();

                $values->next();
            }

            if ($values->valid()) {
                trigger_error($errorMessage, E_USER_WARNING);
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function union($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Create a new collection consisting of every n-th element.
     *
     * @param  int  $step
     * @param  int  $offset
     * @return ($step is positive-int ? static : never)
     *
     * @throws \InvalidArgumentException
     */
    public function nth($step, $offset = 0)
    {
        if ($step < 1) {
            throw new InvalidArgumentException('Step value must be at least 1.');
        }

        return new static(function () use ($step, $offset) {
            $position = 0;

            foreach ($this->slice($offset) as $item) {
                if ($position % $step === 0) {
                    yield $item;
                }

                $position++;
            }
        });
    }

    /**
     * Get the items with the specified keys.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string  $keys
     * @return static
     */
    public function only($keys)
    {
        if ($keys instanceof Enumerable) {
            $keys = $keys->all();
        } elseif (! is_null($keys)) {
            $keys = is_array($keys) ? $keys : func_get_args();
        }

        return new static(function () use ($keys) {
            if (is_null($keys)) {
                yield from $this;
            } else {
                $keys = array_flip($keys);

                foreach ($this as $key => $value) {
                    if (array_key_exists($key, $keys)) {
                        yield $key => $value;

                        unset($keys[$key]);

                        if (empty($keys)) {
                            break;
                        }
                    }
                }
            }
        });
    }

    /**
     * Select specific values from the items within the collection.
     *
     * @param  \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string  $keys
     * @return static
     */
    public function select($keys)
    {
        if ($keys instanceof Enumerable) {
            $keys = $keys->all();
        } elseif (! is_null($keys)) {
            $keys = is_array($keys) ? $keys : func_get_args();
        }

        return new static(function () use ($keys) {
            if (is_null($keys)) {
                yield from $this;
            } else {
                foreach ($this as $item) {
                    $result = [];

                    foreach ($keys as $key) {
                        if (Arr::accessible($item) && Arr::exists($item, $key)) {
                            $result[$key] = $item[$key];
                        } elseif (is_object($item) && isset($item->{$key})) {
                            $result[$key] = $item->{$key};
                        }
                    }

                    yield $result;
                }
            }
        });
    }

    /**
     * Push all of the given items onto the collection.
     *
     * @template TConcatKey of array-key
     * @template TConcatValue
     *
     * @param  iterable<TConcatKey, TConcatValue>  $source
     * @return static<TKey|TConcatKey, TValue|TConcatValue>
     */
    public function concat($source)
    {
        return (new static(function () use ($source) {
            yield from $this;
            yield from $source;
        }))->values();
    }

    /**
     * Get one or a specified number of items randomly from the collection.
     *
     * @param  int|null  $number
     * @param  bool  $preserveKeys
     * @return static<int, TValue>|TValue
     *
     * @throws \InvalidArgumentException
     */
    public function random($number = null, $preserveKeys = false)
    {
        $result = $this->collect()->random(...func_get_args());

        return is_null($number) ? $result : new static($result);
    }

    /**
     * Replace the collection items with the given items.
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>  $items
     * @return static
     */
    public function replace($items)
    {
        return new static(function () use ($items) {
            $items = $this->getArrayableItems($items);

            foreach ($this as $key => $value) {
                if (array_key_exists($key, $items)) {
                    yield $key => $items[$key];

                    unset($items[$key]);
                } else {
                    yield $key => $value;
                }
            }

            foreach ($items as $key => $value) {
                yield $key => $value;
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function replaceRecursive($items)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function reverse()
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Search the collection for a given value and return the corresponding key if successful.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TKey|false
     */
    public function search($value, $strict = false)
    {
        /** @var (callable(TValue,TKey): bool) $predicate */
        $predicate = $this->useAsCallable($value)
            ? $value
            : function ($item) use ($value, $strict) {
                return $strict ? $item === $value : $item == $value;
            };

        foreach ($this as $key => $item) {
            if ($predicate($item, $key)) {
                return $key;
            }
        }

        return false;
    }

    /**
     * Get the item before the given item.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TValue|null
     */
    public function before($value, $strict = false)
    {
        $previous = null;

        /** @var (callable(TValue,TKey): bool) $predicate */
        $predicate = $this->useAsCallable($value)
            ? $value
            : function ($item) use ($value, $strict) {
                return $strict ? $item === $value : $item == $value;
            };

        foreach ($this as $key => $item) {
            if ($predicate($item, $key)) {
                return $previous;
            }

            $previous = $item;
        }

        return null;
    }

    /**
     * Get the item after the given item.
     *
     * @param  TValue|(callable(TValue,TKey): bool)  $value
     * @param  bool  $strict
     * @return TValue|null
     */
    public function after($value, $strict = false)
    {
        $found = false;

        /** @var (callable(TValue,TKey): bool) $predicate */
        $predicate = $this->useAsCallable($value)
            ? $value
            : function ($item) use ($value, $strict) {
                return $strict ? $item === $value : $item == $value;
            };

        foreach ($this as $key => $item) {
            if ($found) {
                return $item;
            }

            if ($predicate($item, $key)) {
                $found = true;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function shuffle()
    {
        return $this->passthru(__FUNCTION__, []);
    }

    /**
     * Create chunks representing a "sliding window" view of the items in the collection.
     *
     * @param  positive-int  $size
     * @param  positive-int  $step
     * @return static<int, static>
     *
     * @throws \InvalidArgumentException
     */
    public function sliding($size = 2, $step = 1)
    {
        if ($size < 1) {
            throw new InvalidArgumentException('Size value must be at least 1.');
        } elseif ($step < 1) {
            throw new InvalidArgumentException('Step value must be at least 1.');
        }

        return new static(function () use ($size, $step) {
            $iterator = $this->getIterator();

            $chunk = [];

            while ($iterator->valid()) {
                $chunk[$iterator->key()] = $iterator->current();

                if (count($chunk) == $size) {
                    yield (new static($chunk))->tap(function () use (&$chunk, $step) {
                        $chunk = array_slice($chunk, $step, null, true);
                    });

                    // If the $step between chunks is bigger than each chunk's $size
                    // we will skip the extra items (which should never be in any
                    // chunk) before we continue to the next chunk in the loop.
                    if ($step > $size) {
                        $skip = $step - $size;

                        for ($i = 0; $i < $skip && $iterator->valid(); $i++) {
                            $iterator->next();
                        }
                    }
                }

                $iterator->next();
            }
        });
    }

    /**
     * Skip the first {$count} items.
     *
     * @param  int  $count
     * @return static
     */
    public function skip($count)
    {
        return new static(function () use ($count) {
            $iterator = $this->getIterator();

            while ($iterator->valid() && $count--) {
                $iterator->next();
            }

            while ($iterator->valid()) {
                yield $iterator->key() => $iterator->current();

                $iterator->next();
            }
        });
    }

    /**
     * Skip items in the collection until the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function skipUntil($value)
    {
        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);

        return $this->skipWhile($this->negate($callback));
    }

    /**
     * Skip items in the collection while the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static
     */
    public function skipWhile($value)
    {
        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);

        return new static(function () use ($callback) {
            $iterator = $this->getIterator();

            while ($iterator->valid() && $callback($iterator->current(), $iterator->key())) {
                $iterator->next();
            }

            while ($iterator->valid()) {
                yield $iterator->key() => $iterator->current();

                $iterator->next();
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function slice($offset, $length = null)
    {
        if ($offset < 0 || $length < 0) {
            return $this->passthru(__FUNCTION__, func_get_args());
        }

        $instance = $this->skip($offset);

        return is_null($length) ? $instance : $instance->take($length);
    }

    /**
     * {@inheritDoc}
     *
     * @throws \InvalidArgumentException
     */
    #[\Override]
    public function split($numberOfGroups)
    {
        if ($numberOfGroups < 1) {
            throw new InvalidArgumentException('Number of groups must be at least 1.');
        }

        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     * @throws \Illuminate\Support\MultipleItemsFoundException
     */
    public function sole($key = null, $operator = null, $value = null)
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        return $this
            ->unless($filter == null)
            ->filter($filter)
            ->take(2)
            ->collect()
            ->sole();
    }

    /**
     * Determine if the collection contains a single item or a single item matching the given criteria.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return bool
     */
    public function hasSole($key = null, $operator = null, $value = null): bool
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        return $this
            ->unless($filter == null)
            ->filter($filter)
            ->take(2)
            ->count() === 1;
    }

    /**
     * Get the first item in the collection but throw an exception if no matching items exist.
     *
     * @param  (callable(TValue, TKey): bool)|string|null  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     */
    public function firstOrFail($key = null, $operator = null, $value = null)
    {
        $filter = func_num_args() > 1
            ? $this->operatorForWhere(...func_get_args())
            : $key;

        return $this
            ->unless($filter == null)
            ->filter($filter)
            ->take(1)
            ->collect()
            ->firstOrFail();
    }

    /**
     * Chunk the collection into chunks of the given size.
     *
     * @param  int  $size
     * @param  bool  $preserveKeys
     * @return ($preserveKeys is true ? static<int, static> : static<int, static<int, TValue>>)
     */
    public function chunk($size, $preserveKeys = true)
    {
        if ($size <= 0) {
            return static::empty();
        }

        $add = match ($preserveKeys) {
            true => fn (array &$chunk, Traversable $iterator) => $chunk[$iterator->key()] = $iterator->current(),
            false => fn (array &$chunk, Traversable $iterator) => $chunk[] = $iterator->current(),
        };

        return new static(function () use ($size, $add) {
            $iterator = $this->getIterator();

            while ($iterator->valid()) {
                $chunk = [];

                while (true) {
                    $add($chunk, $iterator);

                    if (count($chunk) < $size) {
                        $iterator->next();

                        if (! $iterator->valid()) {
                            break;
                        }
                    } else {
                        break;
                    }
                }

                yield new static($chunk);

                $iterator->next();
            }
        });
    }

    /**
     * Split a collection into a certain number of groups, and fill the first groups completely.
     *
     * @param  int  $numberOfGroups
     * @return ($numberOfGroups is positive-int ? static<int, static> : never)
     *
     * @throws \InvalidArgumentException
     */
    public function splitIn($numberOfGroups)
    {
        if ($numberOfGroups < 1) {
            throw new InvalidArgumentException('Number of groups must be at least 1.');
        }

        return $this->chunk((int) ceil($this->count() / $numberOfGroups));
    }

    /**
     * Chunk the collection into chunks with a callback.
     *
     * @param  callable(TValue, TKey, Collection<TKey, TValue>): bool  $callback
     * @return static<int, static<TKey, TValue>>
     */
    public function chunkWhile(callable $callback)
    {
        return new static(function () use ($callback) {
            $iterator = $this->getIterator();

            $chunk = new Collection;

            if ($iterator->valid()) {
                $chunk[$iterator->key()] = $iterator->current();

                $iterator->next();
            }

            while ($iterator->valid()) {
                if (! $callback($iterator->current(), $iterator->key(), $chunk)) {
                    yield new static($chunk);

                    $chunk = new Collection;
                }

                $chunk[$iterator->key()] = $iterator->current();

                $iterator->next();
            }

            if ($chunk->isNotEmpty()) {
                yield new static($chunk);
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sort($callback = null)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sortDesc($options = SORT_REGULAR)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sortByDesc($callback, $options = SORT_REGULAR)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sortKeys($options = SORT_REGULAR, $descending = false)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sortKeysDesc($options = SORT_REGULAR)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function sortKeysUsing(callable $callback)
    {
        return $this->passthru(__FUNCTION__, func_get_args());
    }

    /**
     * Take the first or last {$limit} items.
     *
     * @param  int  $limit
     * @return static<TKey, TValue>
     */
    public function take($limit)
    {
        if ($limit < 0) {
            return new static(function () use ($limit) {
                $limit = abs($limit);
                $ringBuffer = [];
                $position = 0;

                foreach ($this as $key => $value) {
                    $ringBuffer[$position] = [$key, $value];
                    $position = ($position + 1) % $limit;
                }

                for ($i = 0, $end = min($limit, count($ringBuffer)); $i < $end; $i++) {
                    $pointer = ($position + $i) % $limit;
                    yield $ringBuffer[$pointer][0] => $ringBuffer[$pointer][1];
                }
            });
        }

        return new static(function () use ($limit) {
            $iterator = $this->getIterator();

            while ($limit--) {
                if (! $iterator->valid()) {
                    break;
                }

                yield $iterator->key() => $iterator->current();

                if ($limit) {
                    $iterator->next();
                }
            }
        });
    }

    /**
     * Take items in the collection until the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static<TKey, TValue>
     */
    public function takeUntil($value)
    {
        /** @var callable(TValue, TKey): bool $callback */
        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);

        return new static(function () use ($callback) {
            foreach ($this as $key => $item) {
                if ($callback($item, $key)) {
                    break;
                }

                yield $key => $item;
            }
        });
    }

    /**
     * Take items in the collection until a given point in time, with an optional callback on timeout.
     *
     * @param  \DateTimeInterface  $timeout
     * @param  callable(TValue|null, TKey|null): mixed|null  $callback
     * @return static<TKey, TValue>
     */
    public function takeUntilTimeout(DateTimeInterface $timeout, ?callable $callback = null)
    {
        $timeout = $timeout->getTimestamp();

        return new static(function () use ($timeout, $callback) {
            if ($this->now() >= $timeout) {
                if ($callback) {
                    $callback(null, null);
                }

                return;
            }

            foreach ($this as $key => $value) {
                yield $key => $value;

                if ($this->now() >= $timeout) {
                    if ($callback) {
                        $callback($value, $key);
                    }

                    break;
                }
            }
        });
    }

    /**
     * Take items in the collection while the given condition is met.
     *
     * @param  TValue|callable(TValue,TKey): bool  $value
     * @return static<TKey, TValue>
     */
    public function takeWhile($value)
    {
        /** @var callable(TValue, TKey): bool $callback */
        $callback = $this->useAsCallable($value) ? $value : $this->equality($value);

        return $this->takeUntil(fn ($item, $key) => ! $callback($item, $key));
    }

    /**
     * Pass each item in the collection to the given callback, lazily.
     *
     * @param  callable(TValue, TKey): mixed  $callback
     * @return static<TKey, TValue>
     */
    public function tapEach(callable $callback)
    {
        return new static(function () use ($callback) {
            foreach ($this as $key => $value) {
                $callback($value, $key);

                yield $key => $value;
            }
        });
    }

    /**
     * Throttle the values, releasing them at most once per the given seconds.
     *
     * @return static<TKey, TValue>
     */
    public function throttle(float $seconds)
    {
        return new static(function () use ($seconds) {
            $microseconds = $seconds * 1_000_000;

            foreach ($this as $key => $value) {
                $fetchedAt = $this->preciseNow();

                yield $key => $value;

                $sleep = $microseconds - ($this->preciseNow() - $fetchedAt);

                $this->usleep((int) $sleep);
            }
        });
    }

    /**
     * Flatten a multi-dimensional associative array with dots.
     *
     * @param  int  $depth
     * @return static
     */
    public function dot($depth = INF)
    {
        return $this->passthru(__FUNCTION__, [$depth]);
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function undot()
    {
        return $this->passthru(__FUNCTION__, []);
    }

    /**
     * Return only unique items from the collection array.
     *
     * @param  (callable(TValue, TKey): mixed)|string|null  $key
     * @param  bool  $strict
     * @return static<TKey, TValue>
     */
    public function unique($key = null, $strict = false)
    {
        $callback = $this->valueRetriever($key);

        return new static(function () use ($callback, $strict) {
            $exists = [];

            foreach ($this as $key => $item) {
                if (! in_array($id = $callback($item, $key), $exists, $strict)) {
                    yield $key => $item;

                    $exists[] = $id;
                }
            }
        });
    }

    /**
     * Reset the keys on the underlying array.
     *
     * @return static<int, TValue>
     */
    public function values()
    {
        return new static(function () {
            foreach ($this as $item) {
                yield $item;
            }
        });
    }

    /**
     * Run the given callback every time the interval has passed.
     *
     * @return static<TKey, TValue>
     */
    public function withHeartbeat(DateInterval|int $interval, callable $callback)
    {
        $seconds = is_int($interval) ? $interval : $this->intervalSeconds($interval);

        return new static(function () use ($seconds, $callback) {
            $start = $this->now();

            foreach ($this as $key => $value) {
                $now = $this->now();

                if (($now - $start) >= $seconds) {
                    $callback();

                    $start = $now;
                }

                yield $key => $value;
            }
        });
    }

    /**
     * Get the total seconds from the given interval.
     */
    protected function intervalSeconds(DateInterval $interval): int
    {
        $start = new DateTimeImmutable();

        return $start->add($interval)->getTimestamp() - $start->getTimestamp();
    }

    /**
     * Zip the collection together with one or more arrays.
     *
     * e.g. new LazyCollection([1, 2, 3])->zip([4, 5, 6]);
     *      => [[1, 4], [2, 5], [3, 6]]
     *
     * @template TZipValue
     *
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, TZipValue>|iterable<array-key, TZipValue>  ...$items
     * @return static<int, static<int, TValue|TZipValue>>
     */
    public function zip($items)
    {
        $iterables = func_get_args();

        return new static(function () use ($iterables) {
            $iterators = (new Collection($iterables))
                ->map(fn ($iterable) => $this->makeIterator($iterable))
                ->prepend($this->getIterator());

            while ($iterators->contains->valid()) {
                yield new static($iterators->map->current());

                $iterators->each->next();
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function pad($size, $value)
    {
        if ($size < 0) {
            return $this->passthru(__FUNCTION__, func_get_args());
        }

        return new static(function () use ($size, $value) {
            $yielded = 0;

            foreach ($this as $index => $item) {
                yield $index => $item;

                $yielded++;
            }

            while ($yielded++ < $size) {
                yield $value;
            }
        });
    }

    /**
     * Get the values iterator.
     *
     * @return \Traversable<TKey, TValue>
     */
    public function getIterator(): Traversable
    {
        return $this->makeIterator($this->source);
    }

    /**
     * Count the number of items in the collection.
     *
     * @return int
     */
    public function count(): int
    {
        if (is_array($this->source)) {
            return count($this->source);
        }

        return iterator_count($this->getIterator());
    }

    /**
     * Make an iterator from the given source.
     *
     * @template TIteratorKey of array-key
     * @template TIteratorValue
     *
     * @param  \IteratorAggregate<TIteratorKey, TIteratorValue>|array<TIteratorKey, TIteratorValue>|(callable(): \Generator<TIteratorKey, TIteratorValue>)  $source
     * @return \Traversable<TIteratorKey, TIteratorValue>
     */
    protected function makeIterator($source)
    {
        if ($source instanceof IteratorAggregate) {
            return $source->getIterator();
        }

        if (is_array($source)) {
            return new ArrayIterator($source);
        }

        if (is_callable($source)) {
            $maybeTraversable = $source();

            return $maybeTraversable instanceof Traversable
                ? $maybeTraversable
                : new ArrayIterator(Arr::wrap($maybeTraversable));
        }

        return new ArrayIterator((array) $source);
    }

    /**
     * Explode the "value" and "key" arguments passed to "pluck".
     *
     * @param  string|string[]  $value
     * @param  string|string[]|null  $key
     * @return array{string[],string[]|null}
     */
    protected function explodePluckParameters($value, $key)
    {
        $value = is_string($value) ? explode('.', $value) : $value;

        $key = is_null($key) || is_array($key) || $key instanceof Closure ? $key : explode('.', $key);

        return [$value, $key];
    }

    /**
     * Pass this lazy collection through a method on the collection class.
     *
     * @param  string  $method
     * @param  array<mixed>  $params
     * @return static
     */
    protected function passthru($method, array $params)
    {
        return new static(function () use ($method, $params) {
            yield from $this->collect()->$method(...$params);
        });
    }

    /**
     * Get the current time.
     *
     * @return int
     */
    protected function now()
    {
        return class_exists(Carbon::class)
            ? Carbon::now()->getTimestamp()
            : time();
    }

    /**
     * Get the precise current time.
     *
     * @return float
     */
    protected function preciseNow()
    {
        return class_exists(Carbon::class)
            ? Carbon::now()->getPreciseTimestamp()
            : microtime(true) * 1_000_000;
    }

    /**
     * Sleep for the given amount of microseconds.
     *
     * @return void
     */
    protected function usleep(int $microseconds)
    {
        if ($microseconds <= 0) {
            return;
        }

        class_exists(Sleep::class)
            ? Sleep::usleep($microseconds)
            : usleep($microseconds);
    }
}
<?php

namespace Illuminate\Support;

use ArgumentCountError;
use ArrayAccess;
use Closure;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use JsonSerializable;
use Random\Randomizer;
use SortDirection;
use Traversable;
use WeakMap;

class Arr
{
    use Macroable;

    /**
     * Determine whether the given value is array accessible.
     *
     * @param  mixed  $value
     * @return bool
     */
    public static function accessible($value)
    {
        return is_array($value) || $value instanceof ArrayAccess;
    }

    /**
     * Determine whether the given value is arrayable.
     *
     * @param  mixed  $value
     * @return ($value is array
     *     ? true
     *     : ($value is \Illuminate\Contracts\Support\Arrayable
     *         ? true
     *         : ($value is \Traversable
     *             ? true
     *             : ($value is \Illuminate\Contracts\Support\Jsonable
     *                 ? true
     *                 : ($value is \JsonSerializable ? true : false)
     *             )
     *         )
     *     )
     * )
     */
    public static function arrayable($value)
    {
        return is_array($value)
            || $value instanceof Arrayable
            || $value instanceof Traversable
            || $value instanceof Jsonable
            || $value instanceof JsonSerializable;
    }

    /**
     * Add an element to an array using "dot" notation if it doesn't exist.
     *
     * @param  array  $array
     * @param  string|int|float  $key
     * @param  mixed  $value
     * @return array
     */
    public static function add($array, $key, $value)
    {
        if (is_null(static::get($array, $key))) {
            static::set($array, $key, $value);
        }

        return $array;
    }

    /**
     * Get an array item from an array using "dot" notation.
     *
     * @throws \InvalidArgumentException
     */
    public static function array(ArrayAccess|array $array, string|int|null $key, ?array $default = null): array
    {
        $value = Arr::get($array, $key, $default);

        if (! is_array($value)) {
            throw new InvalidArgumentException(
                sprintf('Array value for key [%s] must be an array, %s found.', $key, gettype($value))
            );
        }

        return $value;
    }

    /**
     * Get a boolean item from an array using "dot" notation.
     *
     * @throws \InvalidArgumentException
     */
    public static function boolean(ArrayAccess|array $array, string|int|null $key, ?bool $default = null): bool
    {
        $value = Arr::get($array, $key, $default);

        if (! is_bool($value)) {
            throw new InvalidArgumentException(
                sprintf('Array value for key [%s] must be a boolean, %s found.', $key, gettype($value))
            );
        }

        return $value;
    }

    /**
     * Collapse an array of arrays into a single array.
     *
     * @param  iterable  $array
     * @return array
     */
    public static function collapse($array)
    {
        $results = [];

        foreach ($array as $values) {
            if ($values instanceof Collection) {
                $results[] = $values->all();
            } elseif (is_array($values)) {
                $results[] = $values;
            }
        }

        return array_merge([], ...$results);
    }

    /**
     * Cross join the given arrays, returning all possible permutations.
     *
     * @template TValue
     *
     * @param  iterable<TValue>  ...$arrays
     * @return array<int, array<array-key, TValue>>
     */
    public static function crossJoin(...$arrays)
    {
        $results = [[]];

        foreach ($arrays as $index => $array) {
            $append = [];

            foreach ($results as $product) {
                foreach ($array as $item) {
                    $product[$index] = $item;

                    $append[] = $product;
                }
            }

            $results = $append;
        }

        return $results;
    }

    /**
     * Divide an array into two arrays. One with keys and the other with values.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  array<TKey, TValue>  $array
     * @return array{TKey[], TValue[]}
     */
    public static function divide($array)
    {
        return [array_keys($array), array_values($array)];
    }

    /**
     * Flatten a multi-dimensional associative array with dots.
     *
     * @param  iterable  $array
     * @param  string  $prepend
     * @param  int  $depth
     * @return array
     */
    public static function dot($array, $prepend = '', $depth = INF)
    {
        $results = [];

        $flatten = function ($data, $prefix, $currentDepth) use (&$results, &$flatten, $depth): void {
            foreach ($data as $key => $value) {
                $newKey = $prefix.$key;

                if (is_array($value) && ! empty($value) && $currentDepth < $depth) {
                    $flatten($value, $newKey.'.', $currentDepth + 1);
                } else {
                    $results[$newKey] = $value;
                }
            }
        };

        $flatten($array, $prepend, 0);

        // Destroy self-referencing closure to avoid memory leak...
        $flatten = null;

        return $results;
    }

    /**
     * Convert a flatten "dot" notation array into an expanded array.
     *
     * @param  iterable  $array
     * @return array
     */
    public static function undot($array)
    {
        $results = [];

        foreach ($array as $key => $value) {
            static::set($results, $key, $value);
        }

        return $results;
    }

    /**
     * Get all of the given array except for a specified array of keys.
     *
     * @param  array  $array
     * @param  array|string|int|float  $keys
     * @return array
     */
    public static function except($array, $keys)
    {
        static::forget($array, $keys);

        return $array;
    }

    /**
     * Get all of the given array except for a specified array of values.
     *
     * @param  array  $array
     * @param  mixed  $values
     * @param  bool  $strict
     * @return array
     */
    public static function exceptValues($array, $values, $strict = false)
    {
        $values = (array) $values;

        return array_filter($array, function ($value) use ($values, $strict) {
            return ! in_array($value, $values, $strict);
        });
    }

    /**
     * Determine if the given key exists in the provided array.
     *
     * @param  \ArrayAccess|array  $array
     * @param  string|int|float  $key
     * @return bool
     */
    public static function exists($array, $key)
    {
        if ($array instanceof Enumerable) {
            return $array->has($key);
        }

        if ($array instanceof ArrayAccess) {
            return $array->offsetExists($key);
        }

        if (is_float($key) || is_null($key)) {
            $key = (string) $key;
        }

        return array_key_exists($key, $array);
    }

    /**
     * Return the first element in an iterable passing a given truth test.
     *
     * @template TKey
     * @template TValue
     * @template TFirstDefault
     *
     * @param  iterable<TKey, TValue>  $array
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @param  TFirstDefault|(\Closure(): TFirstDefault)  $default
     * @return TValue|TFirstDefault
     */
    public static function first($array, ?callable $callback = null, $default = null)
    {
        if (is_null($callback)) {
            if (empty($array)) {
                return value($default);
            }

            if (is_array($array)) {
                return array_first($array);
            }

            foreach ($array as $item) {
                return $item;
            }

            return value($default);
        }

        $array = static::from($array);

        $key = array_find_key($array, $callback);

        return $key !== null ? $array[$key] : value($default);
    }

    /**
     * Return the last element in an array passing a given truth test.
     *
     * @template TKey
     * @template TValue
     * @template TLastDefault
     *
     * @param  iterable<TKey, TValue>  $array
     * @param  (callable(TValue, TKey): bool)|null  $callback
     * @param  TLastDefault|(\Closure(): TLastDefault)  $default
     * @return TValue|TLastDefault
     */
    public static function last($array, ?callable $callback = null, $default = null)
    {
        if (is_null($callback)) {
            return empty($array) ? value($default) : array_last($array);
        }

        return static::first(array_reverse($array, true), $callback, $default);
    }

    /**
     * Take the first or last {$limit} items from an array.
     *
     * @param  array  $array
     * @param  int  $limit
     * @return array
     */
    public static function take($array, $limit)
    {
        if ($limit < 0) {
            return array_slice($array, $limit, abs($limit));
        }

        return array_slice($array, 0, $limit);
    }

    /**
     * Flatten a multi-dimensional array into a single level.
     *
     * @param  iterable  $array
     * @param  int  $depth
     * @return array
     */
    public static function flatten($array, $depth = INF)
    {
        $result = [];

        foreach ($array as $item) {
            $item = $item instanceof Collection ? $item->all() : $item;

            if (! is_array($item)) {
                $result[] = $item;
            } else {
                $values = $depth === 1
                    ? array_values($item)
                    : static::flatten($item, $depth - 1);

                foreach ($values as $value) {
                    $result[] = $value;
                }
            }
        }

        return $result;
    }

    /**
     * Get a float item from an array using "dot" notation.
     *
     * @throws \InvalidArgumentException
     */
    public static function float(ArrayAccess|array $array, string|int|null $key, ?float $default = null): float
    {
        $value = Arr::get($array, $key, $default);

        if (! is_float($value)) {
            throw new InvalidArgumentException(
                sprintf('Array value for key [%s] must be a float, %s found.', $key, gettype($value))
            );
        }

        return $value;
    }

    /**
     * Remove one or many array items from a given array using "dot" notation.
     *
     * @param  array  $array
     * @param  array|string|int|float  $keys
     * @return void
     */
    public static function forget(&$array, $keys)
    {
        $original = &$array;

        $keys = (array) $keys;

        if ($keys === []) {
            return;
        }

        foreach ($keys as $key) {
            // if the exact key exists in the top-level, remove it
            if (static::exists($array, $key)) {
                unset($array[$key]);

                continue;
            }

            $parts = explode('.', $key);

            // clean up before each pass
            $array = &$original;

            while (count($parts) > 1) {
                $part = array_shift($parts);

                if (isset($array[$part]) && static::accessible($array[$part])) {
                    $array = &$array[$part];
                } else {
                    continue 2;
                }
            }

            unset($array[array_shift($parts)]);
        }
    }

    /**
     * Get the underlying array of items from the given argument.
     *
     * @template TKey of array-key = array-key
     * @template TValue = mixed
     *
     * @param  array<TKey, TValue>|Enumerable<TKey, TValue>|Arrayable<TKey, TValue>|WeakMap<object, TValue>|Traversable<TKey, TValue>|Jsonable|JsonSerializable|object  $items
     * @return ($items is WeakMap ? list<TValue> : array<TKey, TValue>)
     *
     * @throws \InvalidArgumentException
     */
    public static function from($items)
    {
        return match (true) {
            is_array($items) => $items,
            $items instanceof Enumerable => $items->all(),
            $items instanceof Arrayable => $items->toArray(),
            $items instanceof WeakMap => iterator_to_array($items, false),
            $items instanceof Traversable => iterator_to_array($items),
            $items instanceof Jsonable => json_decode($items->toJson(), true),
            $items instanceof JsonSerializable => (array) $items->jsonSerialize(),
            is_object($items) => (array) $items,
            default => throw new InvalidArgumentException('Items cannot be represented by a scalar value.'),
        };
    }

    /**
     * Get an item from an array using "dot" notation.
     *
     * @param  \ArrayAccess|array  $array
     * @param  string|int|null  $key
     * @param  mixed  $default
     * @return mixed
     */
    public static function get($array, $key, $default = null)
    {
        if (! static::accessible($array)) {
            return value($default);
        }

        if (is_null($key)) {
            return $array;
        }

        if (static::exists($array, $key)) {
            return $array[$key];
        }

        if (! str_contains($key, '.')) {
            return value($default);
        }

        foreach (explode('.', $key) as $segment) {
            if (static::accessible($array) && static::exists($array, $segment)) {
                $array = $array[$segment];
            } else {
                return value($default);
            }
        }

        return $array;
    }

    /**
     * Check if an item or items exist in an array using "dot" notation.
     *
     * @param  \ArrayAccess|array  $array
     * @param  string|array  $keys
     * @return bool
     */
    public static function has($array, $keys)
    {
        $keys = (array) $keys;

        if (! $array || $keys === []) {
            return false;
        }

        foreach ($keys as $key) {
            $subKeyArray = $array;

            if (static::exists($array, $key)) {
                continue;
            }

            foreach (explode('.', $key) as $segment) {
                if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
                    $subKeyArray = $subKeyArray[$segment];
                } else {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Determine if all keys exist in an array using "dot" notation.
     *
     * @param  \ArrayAccess|array  $array
     * @param  string|array  $keys
     * @return bool
     */
    public static function hasAll($array, $keys)
    {
        $keys = (array) $keys;

        if (! $array || $keys === []) {
            return false;
        }

        foreach ($keys as $key) {
            if (! static::has($array, $key)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Determine if any of the keys exist in an array using "dot" notation.
     *
     * @param  \ArrayAccess|array  $array
     * @param  string|array  $keys
     * @return bool
     */
    public static function hasAny($array, $keys)
    {
        if (is_null($keys)) {
            return false;
        }

        $keys = (array) $keys;

        if (! $array) {
            return false;
        }

        if ($keys === []) {
            return false;
        }

        foreach ($keys as $key) {
            if (static::has($array, $key)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determine if all items pass the given truth test.
     *
     * @param  iterable  $array
     * @param  (callable(mixed, array-key): bool)  $callback
     * @return bool
     */
    public static function every($array, callable $callback)
    {
        return array_all($array, $callback);
    }

    /**
     * Determine if some items pass the given truth test.
     *
     * @param  iterable  $array
     * @param  (callable(mixed, array-key): bool)  $callback
     * @return bool
     */
    public static function some($array, callable $callback)
    {
        return array_any($array, $callback);
    }

    /**
     * Get an integer item from an array using "dot" notation.
     *
     * @throws \InvalidArgumentException
     */
    public static function integer(ArrayAccess|array $array, string|int|null $key, ?int $default = null): int
    {
        $value = Arr::get($array, $key, $default);

        if (! is_int($value)) {
            throw new InvalidArgumentException(
                sprintf('Array value for key [%s] must be an integer, %s found.', $key, gettype($value))
            );
        }

        return $value;
    }

    /**
     * Determines if an array is associative.
     *
     * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
     *
     * @param  array  $array
     * @return ($array is list ? false : true)
     */
    public static function isAssoc(array $array)
    {
        return ! array_is_list($array);
    }

    /**
     * Determines if an array is a list.
     *
     * An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between.
     *
     * @param  array  $array
     * @return ($array is list ? true : false)
     */
    public static function isList($array)
    {
        return array_is_list($array);
    }

    /**
     * Join all items using a string. The final items can use a separate glue string.
     *
     * @param  array  $array
     * @param  string  $glue
     * @param  string  $finalGlue
     * @return string
     */
    public static function join($array, $glue, $finalGlue = '')
    {
        if ($finalGlue === '') {
            return implode($glue, $array);
        }

        if (count($array) === 0) {
            return '';
        }

        if (count($array) === 1) {
            return array_last($array);
        }

        $finalItem = array_pop($array);

        return implode($glue, $array).$finalGlue.$finalItem;
    }

    /**
     * Key an associative array by a field or using a callback.
     *
     * @param  iterable  $array
     * @param  callable|array|string  $keyBy
     * @return array
     */
    public static function keyBy($array, $keyBy)
    {
        return (new Collection($array))->keyBy($keyBy)->all();
    }

    /**
     * Prepend the key names of an associative array.
     *
     * @param  array  $array
     * @param  string  $prependWith
     * @return array
     */
    public static function prependKeysWith($array, $prependWith)
    {
        return static::mapWithKeys($array, fn ($item, $key) => [$prependWith.$key => $item]);
    }

    /**
     * Get a subset of the items from the given array.
     *
     * @param  array  $array
     * @param  array|string  $keys
     * @return array
     */
    public static function only($array, $keys)
    {
        return array_intersect_key($array, array_flip((array) $keys));
    }

    /**
     * Get a subset of the items from the given array by value.
     *
     * @param  array  $array
     * @param  mixed  $values
     * @param  bool  $strict
     * @return array
     */
    public static function onlyValues($array, $values, $strict = false)
    {
        $values = (array) $values;

        return array_filter($array, function ($value) use ($values, $strict) {
            return in_array($value, $values, $strict);
        });
    }

    /**
     * Select an array of values from an array.
     *
     * @param  array  $array
     * @param  array|string  $keys
     * @return array
     */
    public static function select($array, $keys)
    {
        $keys = static::wrap($keys);

        return static::map($array, function ($item) use ($keys) {
            $result = [];

            foreach ($keys as $key) {
                if (Arr::accessible($item) && Arr::exists($item, $key)) {
                    $result[$key] = $item[$key];
                } elseif (is_object($item) && isset($item->{$key})) {
                    $result[$key] = $item->{$key};
                }
            }

            return $result;
        });
    }

    /**
     * Pluck an array of values from an array.
     *
     * @param  iterable  $array
     * @param  string|array|int|Closure|null  $value
     * @param  string|array|Closure|null  $key
     * @return array
     */
    public static function pluck($array, $value, $key = null)
    {
        $results = [];

        [$value, $key] = static::explodePluckParameters($value, $key);

        foreach ($array as $item) {
            $itemValue = $value instanceof Closure
                ? $value($item)
                : data_get($item, $value);

            // If the key is "null", we will just append the value to the array and keep
            // looping. Otherwise we will key the array using the value of the key we
            // received from the developer. Then we'll return the final array form.
            if (is_null($key)) {
                $results[] = $itemValue;
            } else {
                $itemKey = $key instanceof Closure
                    ? $key($item)
                    : data_get($item, $key);

                if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
                    $itemKey = (string) $itemKey;
                }

                $results[$itemKey] = $itemValue;
            }
        }

        return $results;
    }

    /**
     * Explode the "value" and "key" arguments passed to "pluck".
     *
     * @param  Closure|array|string  $value
     * @param  string|array|Closure|null  $key
     * @return array
     */
    protected static function explodePluckParameters($value, $key)
    {
        $value = is_string($value) ? explode('.', $value) : $value;

        $key = is_null($key) || is_array($key) || $key instanceof Closure ? $key : explode('.', $key);

        return [$value, $key];
    }

    /**
     * Run a map over each of the items in the array.
     *
     * @param  array  $array
     * @param  callable  $callback
     * @return array
     */
    public static function map(array $array, callable $callback)
    {
        $keys = array_keys($array);

        try {
            $items = array_map($callback, $array, $keys);
        } catch (ArgumentCountError) {
            $items = array_map($callback, $array);
        }

        return array_combine($keys, $items);
    }

    /**
     * Run an associative map over each of the items.
     *
     * The callback should return an associative array with a single key/value pair.
     *
     * @template TKey
     * @template TValue
     * @template TMapWithKeysKey of array-key
     * @template TMapWithKeysValue
     *
     * @param  array<TKey, TValue>  $array
     * @param  callable(TValue, TKey): array<TMapWithKeysKey, TMapWithKeysValue>  $callback
     * @return array
     */
    public static function mapWithKeys(array $array, callable $callback)
    {
        $result = [];

        foreach ($array as $key => $value) {
            $assoc = $callback($value, $key);

            foreach ($assoc as $mapKey => $mapValue) {
                $result[$mapKey] = $mapValue;
            }
        }

        return $result;
    }

    /**
     * Run a map over each nested chunk of items.
     *
     * @template TKey
     * @template TValue
     *
     * @param  array<TKey, array>  $array
     * @param  callable(mixed...): TValue  $callback
     * @return array<TKey, TValue>
     */
    public static function mapSpread(array $array, callable $callback)
    {
        return static::map($array, function ($chunk, $key) use ($callback) {
            $chunk[] = $key;

            return $callback(...$chunk);
        });
    }

    /**
     * Push an item onto the beginning of an array.
     *
     * @param  array  $array
     * @param  mixed  $value
     * @param  mixed  $key
     * @return array
     */
    public static function prepend($array, $value, $key = null)
    {
        if (func_num_args() == 2) {
            array_unshift($array, $value);
        } else {
            $array = [$key => $value] + $array;
        }

        return $array;
    }

    /**
     * Get a value from the array, and remove it.
     *
     * @param  array  $array
     * @param  string|int  $key
     * @param  mixed  $default
     * @return mixed
     */
    public static function pull(&$array, $key, $default = null)
    {
        $value = static::get($array, $key, $default);

        static::forget($array, $key);

        return $value;
    }

    /**
     * Convert the array into a query string.
     *
     * @param  array  $array
     * @return string
     */
    public static function query($array)
    {
        return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
    }

    /**
     * Get one or a specified number of random values from an array.
     *
     * @param  array  $array
     * @param  int|null  $number
     * @param  bool  $preserveKeys
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    public static function random($array, $number = null, $preserveKeys = false)
    {
        $requested = is_null($number) ? 1 : $number;

        $count = count($array);

        if ($requested > $count) {
            throw new InvalidArgumentException(
                "You requested {$requested} items, but there are only {$count} items available."
            );
        }

        if (empty($array) || (! is_null($number) && $number <= 0)) {
            return is_null($number) ? null : [];
        }

        $keys = (new Randomizer)->pickArrayKeys($array, $requested);

        if (is_null($number)) {
            return $array[$keys[0]];
        }

        $results = [];

        if ($preserveKeys) {
            foreach ($keys as $key) {
                $results[$key] = $array[$key];
            }
        } else {
            foreach ($keys as $key) {
                $results[] = $array[$key];
            }
        }

        return $results;
    }

    /**
     * Set an array item to a given value using "dot" notation.
     *
     * If no key is given to the method, the entire array will be replaced.
     *
     * @param  array  $array
     * @param  string|int|null  $key
     * @param  mixed  $value
     * @return array
     */
    public static function set(&$array, $key, $value)
    {
        if (is_null($key)) {
            return $array = $value;
        }

        $keys = explode('.', $key);

        foreach ($keys as $i => $key) {
            if (count($keys) === 1) {
                break;
            }

            unset($keys[$i]);

            // If the key doesn't exist at this depth, we will just create an empty array
            // to hold the next value, allowing us to create the arrays to hold final
            // values at the correct depth. Then we'll keep digging into the array.
            if (! isset($array[$key]) || ! is_array($array[$key])) {
                $array[$key] = [];
            }

            $array = &$array[$key];
        }

        $array[array_shift($keys)] = $value;

        return $array;
    }

    /**
     * Push an item into an array using "dot" notation.
     *
     * @param  \ArrayAccess|array  $array
     * @param  string|int|null  $key
     * @param  mixed  $values
     * @return array
     */
    public static function push(ArrayAccess|array &$array, string|int|null $key, mixed ...$values): array
    {
        $target = static::array($array, $key, []);

        array_push($target, ...$values);

        return static::set($array, $key, $target);
    }

    /**
     * Shuffle the given array and return the result.
     *
     * @param  array  $array
     * @return array
     */
    public static function shuffle($array)
    {
        return (new Randomizer)->shuffleArray($array);
    }

    /**
     * Get the first item in the array, but only if exactly one item exists. Otherwise, throw an exception.
     *
     * @param  array  $array
     * @param  (callable(mixed, array-key): array)|null  $callback
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     * @throws \Illuminate\Support\MultipleItemsFoundException
     */
    public static function sole($array, ?callable $callback = null)
    {
        if ($callback) {
            $array = static::where($array, $callback);
        }

        $count = count($array);

        if ($count === 0) {
            throw new ItemNotFoundException;
        }

        if ($count > 1) {
            throw new MultipleItemsFoundException($count);
        }

        return static::first($array);
    }

    /**
     * Sort the array using the given callback or "dot" notation.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  iterable<TKey, TValue>  $array
     * @param  callable|string|null|array<int, (callable(TValue, TValue): -1|0|1)|array{string, SortDirection|'asc'|'desc'}>  $callback
     * @return array<TKey, TValue>
     */
    public static function sort($array, $callback = null)
    {
        return (new Collection($array))->sortBy($callback)->all();
    }

    /**
     * Sort the array in descending order using the given callback or "dot" notation.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  iterable<TKey, TValue>  $array
     * @param  callable|string|null|array<int, (callable(TValue, TValue): -1|0|1)|array{string, 'asc'|'desc'}>  $callback
     * @return array<TKey, TValue>
     */
    public static function sortDesc($array, $callback = null)
    {
        return (new Collection($array))->sortByDesc($callback)->all();
    }

    /**
     * Recursively sort an array by keys and values.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  array<TKey, TValue>  $array
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @param  SortDirection|bool  $descending
     * @return array<TKey, TValue>
     */
    public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false)
    {
        foreach ($array as &$value) {
            if (is_array($value)) {
                $value = static::sortRecursive($value, $options, $descending);
            }
        }

        if (! array_is_list($array)) {
            match ($descending) {
                false, SortDirection::Ascending => ksort($array, $options),
                true, SortDirection::Descending => krsort($array, $options),
            };
        } else {
            match ($descending) {
                false, SortDirection::Ascending => sort($array, $options),
                true, SortDirection::Descending => rsort($array, $options),
            };
        }

        return $array;
    }

    /**
     * Recursively sort an array by keys and values in descending order.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  array<TKey, TValue>  $array
     * @param  int-mask-of<SORT_REGULAR|SORT_NUMERIC|SORT_STRING|SORT_LOCALE_STRING|SORT_NATURAL|SORT_FLAG_CASE>  $options
     * @return array<TKey, TValue>
     */
    public static function sortRecursiveDesc($array, $options = SORT_REGULAR)
    {
        return static::sortRecursive($array, $options, SortDirection::Descending);
    }

    /**
     * Get a string item from an array using "dot" notation.
     *
     * @throws \InvalidArgumentException
     */
    public static function string(ArrayAccess|array $array, string|int|null $key, ?string $default = null): string
    {
        $value = Arr::get($array, $key, $default);

        if (! is_string($value)) {
            throw new InvalidArgumentException(
                sprintf('Array value for key [%s] must be a string, %s found.', $key, gettype($value))
            );
        }

        return $value;
    }

    /**
     * Conditionally compile classes from an array into a CSS class list.
     *
     * @param  array<string, bool>|array<int, string|int>|string  $array
     * @return ($array is array<string, false> ? '' : ($array is '' ? '' : ($array is array{} ? '' : non-empty-string)))
     */
    public static function toCssClasses($array)
    {
        $classList = static::wrap($array);

        $classes = [];

        foreach ($classList as $class => $constraint) {
            if (is_numeric($class)) {
                $classes[] = $constraint;
            } elseif ($constraint) {
                $classes[] = $class;
            }
        }

        return implode(' ', $classes);
    }

    /**
     * Conditionally compile styles from an array into a style list.
     *
     * @param  array<string, bool>|array<int, string|int>|string  $array
     * @return ($array is array<string, false> ? '' : ($array is '' ? '' : ($array is array{} ? '' : non-empty-string)))
     */
    public static function toCssStyles($array)
    {
        $styleList = static::wrap($array);

        $styles = [];

        foreach ($styleList as $class => $constraint) {
            if (is_numeric($class)) {
                $styles[] = Str::finish($constraint, ';');
            } elseif ($constraint) {
                $styles[] = Str::finish($class, ';');
            }
        }

        return implode(' ', $styles);
    }

    /**
     * Filter the array using the given callback.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  array<TKey, TValue>  $array
     * @param  callable(TValue, TKey): bool  $callback
     * @return array<TKey, TValue>
     */
    public static function where($array, callable $callback)
    {
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
    }

    /**
     * Filter the array using the negation of the given callback.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  array<TKey, TValue>  $array
     * @param  callable(TValue, TKey): bool  $callback
     * @return array<TKey, TValue>
     */
    public static function reject($array, callable $callback)
    {
        return static::where($array, fn ($value, $key) => ! $callback($value, $key));
    }

    /**
     * Partition the array into two arrays using the given callback.
     *
     * @template TKey of array-key
     * @template TValue of mixed
     *
     * @param  iterable<TKey, TValue>  $array
     * @param  callable(TValue, TKey): bool  $callback
     * @return array<int<0, 1>, array<TKey, TValue>>
     */
    public static function partition($array, callable $callback)
    {
        $passed = [];
        $failed = [];

        foreach ($array as $key => $item) {
            if ($callback($item, $key)) {
                $passed[$key] = $item;
            } else {
                $failed[$key] = $item;
            }
        }

        return [$passed, $failed];
    }

    /**
     * Filter items where the value is not null.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  array<TKey, TValue|null>  $array
     * @return array<TKey, TValue>
     */
    public static function whereNotNull($array)
    {
        return static::where($array, fn ($value) => ! is_null($value));
    }

    /**
     * If the given value is not an array and not null, wrap it in one.
     *
     * @template TKey of array-key = array-key
     * @template TValue
     *
     * @param  array<TKey, TValue>|TValue|null  $value
     * @return ($value is null ? array{} : ($value is array ? array<TKey, TValue> : array{TValue}))
     */
    public static function wrap($value)
    {
        if (is_null($value)) {
            return [];
        }

        return is_array($value) ? $value : [$value];
    }
}
9p#B|wjQ]!셋ҹ+
n%d0fa7>GjX*V m   GBMB