Member Avatar for diafol

Hi folks, I'm looking for a function, similar to str_replace that replaces just the first occurance of a specified string. I have found such a function:

http://www.help2go.com/Tutorials/Programming/PHP_:_How_to_replace_only_the_first_occurrence_in_a_string_with_str_replace.html

However, this does not take into consideration of 'search from an initial position'.

My interest is with regard to replacing strings within a php array (for translation purposes) in phpBB language files:

....
'THIS_KEY' => 'My string',
'THIS_KEY_1' => 'My string 1',
'THIS_KEY_2' => 'My string 2',
....

I want to find the key within the file (I load the whole file into a string via file-get_contents), and from that point replace the English value (e.g. 'My string') with another. It is very important that only that particular value is replaced as further replacements could cause havoc.

For example the value 'View' could have a number of different translations in a language, depending on context.

Any 'views' on this would be most welcome! I admit to being a complete fool when it comes to regex.

Recommended Answers

All 16 Replies

I would suggest using the following:

str_replace("'THIS_KEY' => 'My string',","'THIS_KEY' => 'My new value'",$file_input);
Member Avatar for diafol

I would suggest using the following:

str_replace("'THIS_KEY' => 'My string',","'THIS_KEY' => 'My new value'",$file_input);

Ah CW - to the rescue again!

Yes, I thought about this, but the spaces between key and => is variable, so whole line not so easy to find. My DB holds the info thus:

id (PK)
array_key
filename (should be FK I know, but relative path for now)
en_value
cy_value
status (complete or not)

I assumed I'd be able to search for the key - use the end of that as my starting point for the single replace search.

Then it would be as follows.

preg_replace("@'THIS_KEY'.*=>.*'My string',@Us","'THIS_KEY' => 'My new value'",$file_input);
Member Avatar for diafol

Then it would be as follows.

preg_replace("@'THIS_KEY'.*=>.*'My string',@Us","'THIS_KEY' => 'My new value'",$file_input);

A million thanks once again CW. I shall give it a whirl. p_r gives me a nosebleed!

A million thanks once again CW. I shall give it a whirl. p_r gives me a nosebleed!

You know, as long as I have been developing I have this phobia of regular expressions. Sometimes you just can't avoid them because often times they are the best solution but they are so cryptic to me. Here is another option with probably slightly more overhead but greater understanding and in my case, more control.

<?php
$arrArray = array("first"=>"this is my name", "second"=>"this is your name", "third"=>"this is his name");
$strString = "first hello second world third my first name second is third blah";

$arrParts = array();
foreach($arrArray as $key=>$value)
{
    $arrParts = explode($key, $strString);

    if(count($arrParts) > 1)
    {
        $strString = "";
        $strString .= $arrParts[0] . $value . $arrParts[1];
        array_shift($arrParts);
        array_shift($arrParts);
        $strString .= implode($key, $arrParts);
    }

    $arrParts = array();
}
?>

This should replace the first occurrence of each key with its associated value. It's not tested but I'm pretty sure that it is bug free.

Member Avatar for diafol

Hello all, this isn't a bump (I don't think). Just a note to say I really appreciate all the code.

At this point I'm pursuing CW's code as I've been fiddling with it for about 6 hours off and on! That's not to say I don't appreciate other suggestions.

My code at the moment is returning an empty file (string). I#m sure this is my doing.

The following is an example of how to use my example.

$key='THIS_KEY';
$value='New value';
preg_replace("@'$key'.*=>.*\n@Us","'$key' => '$value'\n",$file_input);
Member Avatar for diafol

Thanks! I was getting really bogged down with that one...

$f = file_get_contents("common.php");
$sql = mysql_query("SELECT * FROM pl_terms WHERE filename = 'common.php'");
while($d = mysql_fetch_array($sql)){
   $key = $d['key'];
   $cy = $d['cy'];
	$f = preg_replace("@'$key'.*=>.*\n@Us","'$key' => '$cy',\n",$f);
}
file_put_contents("common.php",$f);

Seems to work very well, although a few niggles with certain key-value lines. Won't mark as solved quite yet, but pretty close.

Seems to work very well, although a few niggles with certain key-value lines. Won't mark as solved quite yet, but pretty close.

Could you give examples of the keys that won't work. Perhaps I could fix that for you.

Member Avatar for diafol

OK the problem occurs where there are duplicate keys. The main array has subarrays and sometimes these subarray keys have the same key name as the main array, if that makes sense. What happens is that the duplicate array values are overwritten twice. I think a fix for this would be to include the English language values in the regex 'find'.

To be honest, I've been playing kids' taxi service all weekend, so haven't had an opportunity to do much with it, but appreciate all the help.

Try the following - it will only replace the first instance of that key

$key='THIS_KEY';
$value='New value';
preg_replace("@'$key'.*=>.*\n@Us","'$key' => '$value'\n",$file_input,1);

As for replacing the second instance of the key, how do you plan to identify the second key or in other words separate the first key from the second. It's like having two variables with the same name.

Member Avatar for diafol

Try the following - it will only replace the first instance of that key

$key='THIS_KEY';
$value='New value';
preg_replace("@'$key'.*=>.*\n@Us","'$key' => '$value'\n",$file_input,1);

As for replacing the second instance of the key, how do you plan to identify the second key or in other words separate the first key from the second. It's like having two variables with the same name.

Quite! In actual fact, I flattened the array when reading the values into the DB (so mutlidim arrays were stored thus:

'key,subkey,subsubkey', e.g. VIEW,DATE,DAY for

array(
   'VIEW'  => array(
       'DATE' => array(
         'DAY' => 'dayvalue',
          ...

I was going to use some smart way of searching for DAY following DATE following VIEW, but this hasn't worked out.

My solution so far is to include the original English value so we search for a specific key-value pair as opposed to just the key. This, in theory should work.

$fl = "viewforum.php";
$f = file_get_contents($fl);
$sql = mysql_query("SELECT * FROM pl_terms WHERE filename = '$fl'");
while($d = mysql_fetch_array($sql)){
   $key = $d['langkey'];
   $cy = $d['cy'];
   $en = $d['en'];
	$f = preg_replace("@'$key'.*=>.*'$en',\n@Us","'$key' => '$cy',\n",$f,1);
}
file_put_contents($fl,$f);

THis works really well for language files without subarrays. Subarray keys will not match due to the 'parentarraykey,...' format and I end up with a blank file.
I'm gonna try rewriting the subarray keys to just the key and see what happens. Like I said, I've been busy this weekend (too much beer and rugby after driving kids around!), so I haven't been able to give it my full attention. Thanks again.

Well could you post as an attachment a sample text file this script may read. Then I may be able to do a better regex for you.

Member Avatar for diafol

Well could you post as an attachment a sample text file this script may read. Then I may be able to do a better regex for you.

WOW! Any further help would be greatly appreciated. I've included a zip with backup.sql (clone of my lang items table), common.php (phpbb lang file), translate.php (regex).

To date, as mentioned, I've got mostly success, but some terms (values with symbols seem to cause a problem), in addition to empty values - some rewriting seems to happen on the first key-value in the file.

Really kind of you. If you find that it's too much trouble, a few pointers may suffice.

I have completed the script and is as follows:

<?php
session_start();
$dbhost = 'localhost';
$dbname = 'mydatabase';
$dbuser = 'root';
$dbpasswd = '';
$link_id = mysql_connect($dbhost, $dbuser, $dbpasswd);
mysql_select_db($dbname, $link_id);

$fl = "common.php";
$f = file_get_contents($fl);

$sql = mysql_query("SELECT langkey,cy,en FROM pl_terms2 WHERE filename = '$fl'");
$f = str_replace(array("\t",'  ','  ','  '),array(' ',' ',' ',' '),$f);
while($d = mysql_fetch_assoc($sql)){
   $key = $d['langkey'];
   $cy = $d['cy'];
   $en = $d['en'];
   $f=str_replace(' \''.$key.'\' => \''.$en.'\',',"    '".$key.'\''.str_repeat(' ',(40-strlen($key))).'=> \''.$cy.'\',',$f);
}

$f = str_replace("\r\n","\n",$f);
file_put_contents($fl,$f);
?>
commented: To the rescue once again! +5
Member Avatar for diafol

You're an absolute hero sir. Thank you very much. You've saved me the few hairs I've got left on my head!

Attribution given on the protosite.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.