Repository: xiCO2k/laravel-vue-i18n (ts)

Issue:
Issue with translation enums php langs generation
I'm trying to translate enums, but keep getting stuck because the php langs generation outputs undefined. Could this be a bug with the php generation? 

php_en.json
```
{
  "enums.undefined.undefined": "Certified",
  "enums.registrationStatus.undefined": "Finished"
}
```

lang/en/enums.php
```
<?php

return [

    \App\Enums\DiveSchool\GroupCertificationStatus::class => [
        \App\Enums\DiveSchool\GroupCertificationStatus::OPEN => 'Open',
        \App\Enums\DiveSchool\GroupCertificationStatus::PARTIALLY_CERTIFIED => 'Partially certified',
        \App\Enums\DiveSchool\GroupCertificationStatus::CERTIFIED => 'Certified',
    ],

    'registrationStatus' => [
        \App\Enums\DiveSchool\RegistrationStatus::NEW->value => 'New',
        \App\Enums\DiveSchool\RegistrationStatus::IN_PROGRESS->value => 'In progress',
        \App\Enums\DiveSchool\RegistrationStatus::FINISHED->value => 'Finished',
    ],
];
```

RegistrationStatus.php
```
<?php

namespace App\Enums\DiveSchool;

use Filament\Support\Contracts\HasLabel;
use Illuminate\Support\Facades\Lang;

enum RegistrationStatus: string implements HasLabel
{
    case NEW = 'new';
    case IN_PROGRESS = 'in_progress';
    case FINISHED = 'finished';

    public function getLabel(): ?string
    {

        $localizedStringKey ='enums.registrationStatus.'.$this->value;

        if (Lang::has($localizedStringKey)) {

            return __($localizedStringKey);
        }

        return $this->value;
    }

    public static function array(): array
    {
        $result = [];
        foreach (self::cases() as $case) {
            $result[$case->name] = $case->getLabel();
        }
        return $result;
    }
}
```


Pull request description:
fix: Add `Enum`  and `class-name` support
Closes #190

Patch:
diff --git a/src/loader.ts b/src/loader.ts
index b0bb14a..4e4bd06 100644
--- a/src/loader.ts
+++ b/src/loader.ts
@@ -3,6 +3,14 @@ import path from 'path'
 import { Engine } from 'php-parser'
 import { ParsedLangFileInterface } from './interfaces/parsed-lang-file'
 
+const toCamelCase = (str: string): string => {
+  if (str === str.toUpperCase()) {
+    return str.toLowerCase()
+  }
+
+  return str.replace(/^\w/, (c) => c.toLowerCase())
+}
+
 export const hasPhpTranslations = (folderPath: string): boolean => {
   folderPath = folderPath.replace(/[\\/]$/, '') + path.sep
 
@@ -51,14 +59,16 @@ export const parseAll = (folderPath: string): ParsedLangFileInterface[] => {
   }
 
   // If data contains an object with folder name 'vendor'
-  const vendorIndex = data.findIndex(({ folder }) => folder === 'vendor');
+  const vendorIndex = data.findIndex(({ folder }) => folder === 'vendor')
 
   if (vendorIndex !== -1) {
-    const vendorTranslations = data[vendorIndex].translations;
-    data.splice(vendorIndex, 1);
+    const vendorTranslations = data[vendorIndex].translations
+    data.splice(vendorIndex, 1)
 
-    data.forEach(langFile =>
-      langFile.translations = mergeVendorTranslations(langFile.folder, langFile.translations, vendorTranslations));
+    data.forEach(
+      (langFile) =>
+        (langFile.translations = mergeVendorTranslations(langFile.folder, langFile.translations, vendorTranslations))
+    )
   }
 
   return data
@@ -75,16 +85,18 @@ export const parseAll = (folderPath: string): ParsedLangFileInterface[] => {
 
 function mergeVendorTranslations(folder: string, translations: any, vendorTranslations: any) {
   // Filter the translations from the vendor file that match the current folder
-  const langTranslationsFromVendor = Object
-    .entries(vendorTranslations)
+  const langTranslationsFromVendor = Object.entries(vendorTranslations)
     .filter(([key]) => key.includes(`.${folder}.`))
-    .reduce((acc, [key, value]) => ({
-      ...acc,
-      [key.replace(`.${folder}.`, '::')]: value,
-    }), {});
+    .reduce(
+      (acc, [key, value]) => ({
+        ...acc,
+        [key.replace(`.${folder}.`, '::')]: value
+      }),
+      {}
+    )
 
   // Merge the vendor translations that matched the folder with the current translations
-  return { ...translations, ...langTranslationsFromVendor };
+  return { ...translations, ...langTranslationsFromVendor }
 }
 
 export const parse = (content: string) => {
@@ -121,7 +133,19 @@ const parseItem = (expr) => {
   }
 
   if (expr.key) {
-    return { [expr.key.value]: parseItem(expr.value) }
+    let key = expr.key.value
+
+    if (expr.key.kind === 'staticlookup') {
+      if (expr.key.offset.name === 'class') {
+        key = toCamelCase(expr.key.what.name)
+      } else {
+        key = toCamelCase(expr.key.offset.name)
+      }
+    } else if (expr.key.kind === 'propertylookup') {
+      key = toCamelCase(expr.key.what.offset.name)
+    }
+
+    return { [key]: parseItem(expr.value) }
   }
 
   return parseItem(expr.value)
@@ -181,7 +205,7 @@ export const readThroughDir = (dir) => {
 }
 
 export const prepareExtendedParsedLangFiles = (langPaths: string[]): ParsedLangFileInterface[] =>
-  langPaths.flatMap(langPath => parseAll(langPath));
+  langPaths.flatMap((langPath) => parseAll(langPath))
 
 export const generateFiles = (langPath: string, data: ParsedLangFileInterface[]): ParsedLangFileInterface[] => {
   data = mergeData(data)


Test patch:
diff --git a/test/fixtures/lang/en/classnames.php b/test/fixtures/lang/en/classnames.php
new file mode 100644
index 0000000..fdb373d
--- /dev/null
+++ b/test/fixtures/lang/en/classnames.php
@@ -0,0 +1,11 @@
+<?php
+
+class SomeClass
+{
+    const NAME = 'name';
+}
+
+return [
+    SomeClass::class => 'Some Class',
+    SomeClass::NAME => 'Name',
+];
diff --git a/test/fixtures/lang/en/enums.php b/test/fixtures/lang/en/enums.php
new file mode 100644
index 0000000..3dc22ed
--- /dev/null
+++ b/test/fixtures/lang/en/enums.php
@@ -0,0 +1,16 @@
+<?php
+
+enum Status
+{
+    case New = 'new';
+    case InProgress = 'in_progress';
+    case Finished = 'finished';
+}
+
+return [
+    Status::class => [
+        Status::New->value => 'New',
+        Status::InProgress->value => 'In Progress',
+        Status::Finished->value => 'Finished',
+    ],
+];
diff --git a/test/loader.test.ts b/test/loader.test.ts
index f8fddbf..38cf1fe 100644
--- a/test/loader.test.ts
+++ b/test/loader.test.ts
@@ -126,6 +126,21 @@ it('transforms simple index array to .json', () => {
     expect(lang['arr.1']).toBe('bar');
 });
 
+it('transforms enum values to .json', () => {
+    const lang = parse(fs.readFileSync(isolatedFixtures + '/lang/en/enums.php').toString());
+
+    expect(lang['status.new']).toBe('New');
+    expect(lang['status.inProgress']).toBe('In Progress');
+    expect(lang['status.finished']).toBe('Finished');
+});
+
+it('transforms class names and consts to .json', () => {
+    const lang = parse(fs.readFileSync(isolatedFixtures + '/lang/en/classnames.php').toString());
+
+    expect(lang['someClass']).toBe('Some Class');
+    expect(lang['name']).toBe('Name');
+});
+
 it('ignores empty `array` or `null` translations', () => {
     const lang = parse(fs.readFileSync(isolatedFixtures + '/lang/en/ignore.php').toString());