From 3fadc169035294af7cada5ecb6409f74744825f6 Mon Sep 17 00:00:00 2001
From: Jake Barnby <jakeb994@gmail.com>
Date: Tue, 16 Jan 2024 20:39:34 +1300
Subject: [PATCH] Properly handle non-ascii characters for all languages enum
 keys

---
 src/SDK/Language.php                          | 38 ++++++++++++++-----
 src/SDK/Language/Kotlin.php                   |  1 -
 src/SDK/Language/Swift.php                    |  1 -
 templates/deno/src/enums/enum.ts.twig         |  2 +-
 templates/node/lib/enums/enum.js.twig         |  2 +-
 templates/python/package/enums/enum.py.twig   |  2 +-
 .../ruby/lib/container/enums/enum.rb.twig     |  2 +-
 7 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/src/SDK/Language.php b/src/SDK/Language.php
index 68a90cfbe8..0e806b4979 100644
--- a/src/SDK/Language.php
+++ b/src/SDK/Language.php
@@ -86,24 +86,42 @@ public function getFilters(): array
 
     protected function toPascalCase(string $value): string
     {
-        return ucfirst($this->toCamelCase($value));
+        return \ucfirst($this->toCamelCase($value));
     }
 
     protected function toCamelCase($str): string
     {
-        $str = preg_replace('/[^a-z0-9' . implode("", []) . ']+/i', ' ', $str);
-        $str = trim($str);
-        $str = ucwords($str);
-        $str = str_replace(" ", "", $str);
-        return lcfirst($str);
+        // Normalize the string to decompose accented characters
+        $str = \Normalizer::normalize($str, \Normalizer::FORM_D);
+
+        // Remove accents and other residual non-ASCII characters
+        $str = \preg_replace('/\p{M}/u', '', $str);
+
+        $str = \preg_replace('/[^a-zA-Z0-9]+/', ' ', $str);
+        $str = \trim($str);
+        $str = \ucwords($str);
+        $str = \str_replace(' ', '', $str);
+        $str = \lcfirst($str);
+
+        return $str;
     }
 
     protected function toSnakeCase($str): string
     {
-        $str = \preg_replace('/([a-z])([A-Z])/', '$1 $2', $str);
-        $str = \explode(' ', $str);
-        $str = \implode('_', $str);
-        return \strtolower($str);
+        // Normalize the string to decompose accented characters
+        $str = \Normalizer::normalize($str, \Normalizer::FORM_D);
+
+        // Remove accents and other residual non-ASCII characters
+        $str = \preg_replace('/\p{M}/u', '', $str);
+
+        // Remove apostrophes before replacing non-word characters with underscores
+        $str = \str_replace("'", '', $str);
+        $str = \preg_replace('/[^a-zA-Z0-9]+/', '_', $str);
+        $str = \preg_replace('/_+/', '_', $str);
+        $str = \trim($str, '_');
+        $str = \strtolower($str);
+
+        return $str;
     }
 
     protected function toUpperSnakeCase($str): string
diff --git a/src/SDK/Language/Kotlin.php b/src/SDK/Language/Kotlin.php
index bde9513cdd..02661d5a7d 100644
--- a/src/SDK/Language/Kotlin.php
+++ b/src/SDK/Language/Kotlin.php
@@ -443,7 +443,6 @@ public function getFilters(): array
                 if (isset($this->getIdentifierOverrides()[$value])) {
                     $value = $this->getIdentifierOverrides()[$value];
                 }
-                $value = \preg_replace('/[^a-zA-Z0-9]/', '', $value);
                 return $this->toUpperSnakeCase($value);
             }),
         ];
diff --git a/src/SDK/Language/Swift.php b/src/SDK/Language/Swift.php
index db69689cd9..2abbf8f99c 100644
--- a/src/SDK/Language/Swift.php
+++ b/src/SDK/Language/Swift.php
@@ -471,7 +471,6 @@ public function getFilters(): array
                 if (isset($this->getIdentifierOverrides()[$value])) {
                     $value = $this->getIdentifierOverrides()[$value];
                 }
-                $value = \preg_replace('/[^a-zA-Z0-9]/', '', $value);
                 return $this->toCamelCase($value);
             }),
         ];
diff --git a/templates/deno/src/enums/enum.ts.twig b/templates/deno/src/enums/enum.ts.twig
index 34724aba06..31aeaf6e8b 100644
--- a/templates/deno/src/enums/enum.ts.twig
+++ b/templates/deno/src/enums/enum.ts.twig
@@ -1,6 +1,6 @@
 export enum {{ enum.name | caseUcfirst | overrideIdentifier }} {
     {%~ for value in enum.enum %}
     {%~ set key = enum.keys is empty ? value : enum.keys[loop.index0] %}
-    {{ key | caseUcfirst | replace({'-': ''}) }} = '{{ value }}',
+    {{ key | caseEnumKey }} = '{{ value }}',
     {%~ endfor %}
 }
\ No newline at end of file
diff --git a/templates/node/lib/enums/enum.js.twig b/templates/node/lib/enums/enum.js.twig
index a3e61e6472..fd6c2c23d5 100644
--- a/templates/node/lib/enums/enum.js.twig
+++ b/templates/node/lib/enums/enum.js.twig
@@ -1,7 +1,7 @@
 const {{ enum.name | caseUcfirst | overrideIdentifier }} = {
 {% for value in enum.enum %}
 {% set key = enum.keys is empty ? value : enum.keys[loop.index0] %}
-    {{ key | replace({'-': '',' ': ''}) | caseEnumKey }}: '{{value}}' {% if not loop.last %},{% endif %}
+    {{ key | caseEnumKey }}: '{{value}}' {% if not loop.last %},{% endif %}
 
 {% endfor %}
 }
diff --git a/templates/python/package/enums/enum.py.twig b/templates/python/package/enums/enum.py.twig
index e8883e9143..dedb905f0b 100644
--- a/templates/python/package/enums/enum.py.twig
+++ b/templates/python/package/enums/enum.py.twig
@@ -3,5 +3,5 @@ from enum import Enum
 class {{ enum.name | caseUcfirst | overrideIdentifier }}(Enum):
 {% for value in enum.enum %}
 {% set key = enum.keys is empty ? value : enum.keys[loop.index0] %}
-    {{ key | caseUpper | replace({'-': '',' ':'_', '(': '', ')': '', '.': ''})}} = "{{ value }}"
+    {{ key | caseEnumKey }} = "{{ value }}"
 {% endfor %}
\ No newline at end of file
diff --git a/templates/ruby/lib/container/enums/enum.rb.twig b/templates/ruby/lib/container/enums/enum.rb.twig
index c640146e45..47d9ea4702 100644
--- a/templates/ruby/lib/container/enums/enum.rb.twig
+++ b/templates/ruby/lib/container/enums/enum.rb.twig
@@ -3,7 +3,7 @@ module {{ spec.title | caseUcfirst }}
         module {{ enum.name | caseUcfirst | overrideIdentifier }}
             {%~ for value in enum.enum %}
             {%~ set key = enum.keys is empty ? value : enum.keys[loop.index0] %}
-            {{ key | caseUpper | replace({'-': '_', ' ':'_', '(': '', ')': '', '.': ''}) }} = '{{ value }}'
+            {{ key | caseEnumKey }} = '{{ value }}'
             {%~ endfor %}
         end
     end
