Store the data in UTF-8 in the database.
Use multi byte string funtions in PHP
Data drive it with a schema similar to this one.....
-- =============================================================================
-- Diagram Name: cms
-- Created on: 02/07/2009 19:31:19
-- Diagram Version:
-- (Quickly knocked up in Micro Olap)
-- =============================================================================
SET FOREIGN_KEY_CHECKS=0;
-- Drop table CmsTextType
DROP TABLE IF EXISTS CmsTextType;
CREATE TABLE CmsTextType (
id int(11) NOT NULL,
type varchar(50),
PRIMARY KEY(id)
)
ENGINE=INNODB
CHARACTER SET utf8 ;
-- Drop table Language
DROP TABLE IF EXISTS Language;
CREATE TABLE Language (
id int(11) NOT NULL,
name varchar(100),
PRIMARY KEY(id)
)
ENGINE=INNODB
CHARACTER SET utf8 ;
-- Drop table CmsTextIndex
DROP TABLE IF EXISTS CmsTextIndex;
CREATE TABLE CmsTextIndex (
id int(11) NOT NULL,
cms_text_type_id int(11) NOT NULL DEFAULT '0',
page int(11) NOT NULL,
name varchar(50) NOT NULL,
template_tag varchar(50) NOT NULL,
PRIMARY KEY(id),
UNIQUE INDEX un_cms_text(page, name, template_tag),
CONSTRAINT FK_CmsTextIndex_CmsTextType FOREIGN KEY (cms_text_type_id)
REFERENCES CmsTextType(id)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE=INNODB
CHARACTER SET utf8 ;
-- Drop table CmsTextItem
DROP TABLE IF EXISTS CmsTextItem;
CREATE TABLE CmsTextItem (
id int(11) NOT NULL,
cms_text_id int(11) NOT NULL DEFAULT '0',
language_id int(11) NOT NULL,
text text,
PRIMARY KEY(id),
CONSTRAINT FK_CmsTextItem_Language FOREIGN KEY (language_id)
REFERENCES Language(id)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT FK_CmsTextItem_CmsText FOREIGN KEY (cms_text_id)
REFERENCES CmsTextIndex(id)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE=INNODB
CHARACTER SET utf8 ;
SET FOREIGN_KEY_CHECKS=1;
CmsTextType can be used to determine if something is just a label( input type text ) or requires a BB Editor thingy for a form
CmsTextIndex can be used to generate the navigation for the the area that can be edited(such as navigation, home etc ). It also contains thetage to replace in the relevant template etc.
CmsTextItem can be used to gererate language specific editor forms when combined with CmsTextIndex and Language. Add a language/new CmsTextIndex it will manage itself. Can also be interrogated using sql to determine watch things have not been created in what languages.
The problem with googling this stuff is a lot of inneficiant answers come up. Using arrays/constants is inefficient as every time you want to add a new field/ language/ change text it relies on a developer to go in and make x changes. X= number of languages, anything with that maintenance deficit should never be produced except as a form of self punishment. Data drive it and it is a case of adding a thing to a template somewhere and adding something to CmsTextIndex or for just a new language a new language id.
Then someone who actually speaks the language can go in and make changes leaving you to do more worth while things. Especially as you cannot even catch simple copy problems.