My task was to take a php i18n language file and convert it to a ColdFusion struct. Here is a portion of the input
...
"ASK_DELETE" => "<em>D</em>elete", // 'd' is the accesskey identifier
"BACKUP_OF" => 'Backup of',
"PAGE_TITLE" => "Page Title",
...
The code below does work for the php language file that I have been handed. The issue is, the code looks like the beginning of spaghetti code. Some of the things I don't like are
The code looks like the beginning of spaghetti code. What kinds of things should be done about this?
<cffunction name="readPropertiesFile" returnType="Struct" hint="Read a properties file and return a structure">
<cfargument name="propertiesFile" type="string" required="true" hint="path to properties file">
<cfscript>
VAR stProperties = {};
VAR phpText = "";
VAR key = "";
VAR value = "";
VAR line = "";
var propertiesFilePath = "#GetDirectoryFromPath(GetBaseTemplatePath())##arguments.propertiesfile#";
if (NOT FileExists(propertiesFilePath))
return stProperties;
</cfscript>
<!--- read props file --->
<cffile action="read" file="#propertiesFilePath#" variable="phpText">
<!--- remove any whitespace at top and tail --->
<cfset phpText = trim(phpText)>
<!--- remove comments and blank lines --->
<cfset phpText = ReReplace(phpText,"(?m)\##.*?$", "","all")>
<cfset phpText = ReReplace(phpText,"[#Chr(10)#]{2,}", "#Chr(10)#","all")>
<cfset phpText = ReplaceList(phpText, '",', '"')>
<!--- loop over each line, ignore comments (#...) and insert keys/values into return struct --->
<cfloop list="#phpText#" index="line" delimiters="#CHR(10)#">
<cfscript>
line = trim(line);
splitAt = Find("=>", line);
CommentAt = Find("//", line);
if (splitAt != 0) {
key = replacelist(trim(Left(line, splitAt - 1)), '"', "");
if (CommentAt == 0)
value = replacelist(trim(Mid(line, splitAt + 2, 1000)), '"', '');
else
value = replacelist(trim(Mid(line, splitAt + 2, CommentAt - (splitAt + 2))), '"', '');
// Remove trailing ,
if (right(value, 1) == ",")
value = mid(value, 1, len(value) - 1);
if (right(value, 1) == "'")
value = mid(value, 1, len(value) - 1);
if (left(value, 1) == "'")
value = mid(value, 2, 1000);
stProperties[key] = value;
} // end if
</cfscript>
</cfloop>
<cfreturn stProperties>
This would be my approach. You can of course make this more resilient or add error trapping to catch inconsistent file parsing. I'm assuming there won't be quotes in the key values.
<!--- Going on the Assumption there isn't commas or quotations inside the values of the key --->
<cfsavecontent variable="fileData">
"ASK_DELETE" => "<em>D</em>elete", // 'd' is the accesskey identifier
"BACKUP_OF" => 'Backup of',
"PAGE_TITLE" => "Page Title"
</cfsavecontent>
<cfset i18n = structNew()>
<!--- Remove // Comments --->
<cfset fileData = REReplace(fileData,"//.*?\n","","ALL")>
<!--- Simplify Delimiter --->
<cfset fileData = Replace(fileData,"=>","|","ALL")>
<cfloop list="#fileData#" delimiters="," index="thisEntry">
<!--- Strip Quotes and Pull Entries --->
<cfset key = REReplace(ListFirst(thisEntry,"|"),"[""']","","ALL")>
<cfset value = REReplace(ListLast(thisEntry,"|"),"[""']","","ALL")>
<cfset structInsert(i18n,trim(key),trim(value))>
</cfloop>
<cfdump var="#i18n#">