Heute früh direkt bemerkt: Google hat eine kleine Designänderung auf der Mainpage:

Modern, einfach, Google 🙂

Auch an der Suchseite und den Suchergebnissen wurde gearbeitet:

Die linke Sidebar hat sich verändert: Abstände, Linien(farben) und Positionen der Elemente wurden überarbeitet. Die Icons links sind ebenfalls neu und farblos; darüber lässt sich streiten finde ich, Google ist bei mir grundsätzlich eher bunt. Der ganze Seitenheader ist ein wenig neu arrangiert und designed. Die Suchergebnisse haben jetzt angenehmere Abstände (wodurch aber weniger Ergebnisse ins Sichtfeld passen), das Grün der Links ist (meiner Meinung nach) angenehmer und die Links stehen jetzt direkt unter dem Seitentitel.

Das wären so die auffälligsten Änderungen. Momentan sehe ich das neue Google Design nur im Chrome, im Firefox ist das alte Design noch aktiv. Ich kann also noch sehr gut Vorher-Nachher-Bilder zeigen 🙂

Ich möchte hier den grundlegenden Aufbau einer mehrsprachigen Internetseite zeigen. Das Grundgerüst wird mit HTML, CSS und PHP realisiert.

Features

  • Browser-Spracherkennung
  • Sprachüberprüfung
  • Sprachspeicherung mit Cookies
  • Cookie-Löschfunktion
  • Anzeige der Cookie-Lebensdauer
  • Abfangen unbekannter Sprachen, Setzen einer Ausweichsprache
  • Debuginformationen in einer Box


Funktionsweise

  • Beim ersten Besuch der Zielseite startet die automatische Spracherkennung. Das System prüft den Browser auf mitgegebene Sprachinformationen im HTTP Header und nimmt die bevorzugte Sprache des Browsers als Seitensprache (falls Informationen mitgegeben und Sprache verfügbar).
  • Der Benutzer kann manuell durch Anklicken von Länderfahnen/Links eine andere verfügbare Sprache wählen.
  • Wird eine verfügbare Sprache vom Browser erkannt, vom Benutzer angeklickt oder anderweitig gewählt (z.B. manuelle URL Eingabe) so wird ein Cookie erstellt (falls möglich), in dem die Sprache gespeichert wird. Der Besucher wird bei seinem nächsten Webseitenbesuch also gleich die gewünschte Sprache sehen.
  • Die Cookielaufzeit beträgt 1 Jahr. Bei jeder Aktion auf der Zielseite wird die Lebensdauer wieder auf 1 Jahr gesetzt. Der Tod des Cookies wird in der Debugbox ausgegeben. Durch einen Klick des Benutzers auf einen Button/Link lässt sich das Cookie löschen.
  • Wird die Sprache (durch Browsererkennung, Wahl oder Eingabe) nicht erkannt oder ist für die erkannte Sprache kein übersetzter Inhalt vorhanden so wird eine Ausweichsprache (Standardsprache) gesetzt.
Code

Code anzeigenDen Code könnt ihr bequem mit den Links/Rechts Pfeiltasten horizontal bewegen.

<?php
/*
   ######################
    PHP Multilanguage
   ######################
   Desc: This page detects your browserlanguage, cookie or chosen language with PHP and displays the right content.
   Author: Hannes Schurig
   Date: 15.06.2011
   Edited: 16.06.2011 (v1.4)
   Changelog:
   1.1: komplett umgeschrieben... Funktion langanalyse geschrieben, gekürzt, optimiert
   1.2: + Debugmeldung (echo Ausgabe) bei unbekannter Sprache, mehr Kommentare
   1.3: + Cookie löschen Feature
   1.4: + Cookie Lebensdaueranzeige, Lebensdaueroptimierung (exakt 1 Jahr), besseres Deutsch in der Debugbox
   1.5: * Code minified
   1.6: + header(Location) URL correction, no more .php?lang=?? after choosing lang (only in minified version, link below)
   ###################
    minified version
   ###################
   !URL minified productive version: http://hannes-schurig.de/21/06/2011/php-mehrsprachigkeitssystem-minified/
 */

$lang = detectlang();
// Spracherkennung
// GET abfragen; wird geliefert wenn ein Sprachlink geklickt wird
if(isset($_GET["lang"])) { 
	$lang = langanalyse($_GET["lang"],"get");
}
// POST abfragen; wird in meinem Beispiel nicht benutzt
elseif(isset($_POST["lang"])) {
	$lang = langanalyse($_POST["lang"],"post");
}
// Cookie abfragen; ist ab dem 2. Besuch gesetzt (wenn Cookies aktiviert sind)
elseif(isset($_COOKIE["lang"])) {
	$lang = langanalyse($_COOKIE["lang"],"cookie");
}
// keine Sprache gefunden; Browsersprache erkennen, die Sprache mit der höchsten Priorität auswählen
else {
	$cutstring = explode("-", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
	$detectlang = $cutstring[0];
	$lang = langanalyse($detectlang,"browser");
}
// Überprüfe ob für die Sprache verfügbar ist
function langanalyse($new_lang, $methode) {
	switch($new_lang) {
		// die erlaubten Sprachen hier hintereinander auflisten
		case ("de"): 
		case ("en"): 
			$lang = $new_lang; 
			setcookie("lang", $lang, time()+31536000);
			break;
		// Cookie löschen Funktion als Pseudo-Sprache
		case ("delete"):
			setcookie("lang", $lang, time()-3600); 
			break;
		// für die erkannte Sprache sind keine Übersetzungen vorhanden oder die Sprache ist gänzlich unbekannt
		default:
			$unknown_lang = 1;
			// die Standardsprache:
			$lang = "en"; 
			setcookie("lang", $lang, time()+31536000);
	}
	// Methode erkennen, Debugbox öffnen und Informationen ausgeben
	switch($methode) {
		case ("get"): echo('<div id="langdebug">Methode = get<br/>'); break;
		case ("post"): echo('<div id="langdebug">Methode = post<br/>'); break;
		case ("cookie"): echo('<div id="langdebug">Methode = cookie<br/>'); break;
		case ("browser"): echo('<div id="langdebug">Methode = browserdetect<br/>
	(kein GET, POST und COOKIE gefunden)<br/>
	Browserlang: '.$_SERVER["HTTP_ACCEPT_LANGUAGE"].'<br/>'); break;
		default: echo('<div id="langdebug">Methode = Unbekannt oder Fehler<br/>'); break;
	}
	// Hinweis im Debugbox wenn Sprache unbekannt
	if($unknown_lang == 1) {
		echo('!! Sprache "'.$new_lang.'" unbekannt. Auf "'.$lang.'" gesetzt<br/>');
		$unknown_lang = 0;
	}
	return $lang;
}
// ein paar zusätzliche Debuginformationen und die manuelle Sprachwahl
echo('aktuelle Sprache = '.$lang.'<br/>
Cookie Sprache = '.$_COOKIE["lang"].'<br/>
Cookie Tod = '. date("d.m.Y G:i",time()+31536000) .'<br/>
Sprache setzen:<br/>
<a href="'.$_SERVER['SCRIPT_NAME'].'?lang=de">Deutsch</a>   
<a href="'.$_SERVER['SCRIPT_NAME'].'?lang=en">Englisch</a><br/>  
<a href="'.$_SERVER['SCRIPT_NAME'].'?lang=delete">Cookie löschen</a>  
</div>');

// PHP Array mit den eigentlichen Inhalten der erlaubten Sprachen
$content["de"]["text"]="Hallo, dies ist nur ein Test";
$content["en"]["text"]="Hello, this is just a test";
$content["de"]["menu"]="
<ul>
 <li>Autos</li>
 <li>Frauen</li>
 <li>Alkohol</li>
</ul>";
$content["en"]["menu"]="
<ul>
 <li>Sex</li>
 <li>Drugs</li>
 <li>Rock'n'Roll</li>
</ul>";
$content["de"]["info"]="Zu Ihrer Information:<br/>
News 1: bla<br/>
News 2: bla<br/>
Test";
$content["en"]["info"]="For Your Information:<br/>
News 1: Foo<br/>
News 2: Bar<br/>
foobar";

?>
<html>
 <head>
  <title>Mehrsprachigkeit mit PHP, Array und COOKIES</title>
  <style type="text/css">
  div {
    margin: 20px;
	padding: 15px;
	float: left; }
  #langdebug {
    border: 1px solid black;
    font-size: 0.8em; }
  </style>
 </head>
<body>
 
 <div id="menu">
  <? echo($content[$lang]["menu"]); ?>
 </div>
 <div id="text">
  <? echo($content[$lang]["text"]); ?>
 </div>
 <div id="info">
  <? echo($content[$lang]["info"]); ?>
 </div>

</body>
</html>
Demo

Demo Link

Download

latest [.zip]

alte Versionen

Changelog


v1.1: komplett umgeschrieben… Funktion langanalyse geschrieben, gekürzt, optimiert
v1.2: + Debugmeldung (echo Ausgabe) bei unbekannter Sprache, mehr Kommentare
v1.3: + Cookie löschen Feature
v1.4: + Cookie Lebensdaueranzeige, Lebensdaueroptimierung (exakt 1 Jahr), besseres Deutsch in der Debugbox
*v1.5: minified/productive version available: Link
*v1.6: + header(Location) URL Korrektur nach Sprachwahl, keine lästigen .php?lang=?? Parameter mehr (nur in der Produktivversion verfügbar)

Ich wünsche euch allen frohe Pfingsten! Ein freier Tag, ein Tag der Entspannung, kein technisches Gelaber heute. Stattdessen schmeiße ich heute mal 3 Gutscheine in die Runde, die seit einigen Tagen hier auf meinem Tisch rumliegen. Ich als treuer Lovefilm Kunde habe nämlich Post bekommen. 2x 30 Tage und 2x 60 Tage kostenlos Filme leihen; online, bequem auf Lovefilm.de.

Die zwei 60-Tage-Gutscheine sind ziemlich cool gemacht mit einer Art Chipkarte aber im Endeffekt steht auch dort nur ein Gutscheincode drauf. Ich werde also alle 4 Gutscheincodes per E-Mail verschicken, so könnt ihr schon am Tag der Gewinnerziehung loslegen 😉

Teilnahme:
Ich möchte von euch wissen welche Filme in den letzten Monaten eure Highlights waren, welche Filme sollte ich unbedingt gesehen haben?? Und welche Filme stehen noch auf eurer To-Do-Liste oder kommen erst noch in die Kinos? Gerne könnt ihr auch Flops anprangern, die ich vielleicht meiden sollte.
Mit euren Kommentaren kann ich dann auch meine Lovefilm Filmliste wieder füllen 🙂

Meine Highlights der letzten Zeit waren auf jeden Fall Tron, Fast and Furious 5, Ip Man (1), Sucker Punch, Ich einfach unverbesserlich, Scott Pilgrim, Step Up 3… joah. Die Flops, entgegen vieler Meinungen, waren für mich Machete, Kick Ass, Drive Angry, Russian Transporter und Kiss and Kill.

Die Ziehung der Gewinner ist am Samstag den 25.06.

Problem:
Office 2003 installiert, Installationsdateien wurden auf einer beliebigen Nicht-System-Partition (z.B. D:\) im Ordner MSOCache abgelegt. Image des Computers gemacht, auf einen anderen Computer gespielt, wo eine solche Partition (z.B. D:\) nicht existiert, dieser Fehler wird bei jedem Start jeder Office Komponente erscheinen.

Lösung:
Die Office Local Installation Source (LIS) deaktivieren, neu erstellen oder einen neuen Ort für den MSOCache Ordner festlegen und diesen durch 1 Office Start neu erzeugen lassen. Danach erscheint der Fehler nicht mehr. Infos auch bei Microsoft.

Microsoft hat dafür bereits ein kleines Tool parat, das Local Installation Source Tool für Office 2003.
Mit dem Tool lässt sich dieses Feature aktivieren (MSOCache Ordner erstellen), der Ordner verschieben oder das Feature deaktivieren.

Alternativ kann man den Pfad auch in der Registry setzen:

HKEY_LOCAL_MACHINE\Software\Microsoft\Office\11.0\Delivery\{CLSID}

Dort muss beim Key „LocalCacheDrive“ der Laufwerkbuchstabe der gewünschten Partition rein.
Das ist dann natürlich sinnvoll für die Verbreitung eines neuen Pfades in einem größeren Netzwerk oder via Script.
Dann muss auf dieser Partition in der 1. Ordnerebene der MSOCache vorhanden sein, mit der typischen MSOCache Ordnerstruktur und vielen Cabs. Alternativ MSOCache durch einen Office Start nach dem Setzen des Keys neu erstellen lassen.

Okay, folgendes Ziel:
Wir wollen mit einem Batch Script aus einer Textdatei eine Textzeile löschen oder filtern (alles andere löschen).

Praktisches Beispiel:
Das im letzten Post beschriebene Thunderbird Problem soll auf allen Computern eines Netzwerks behoben werden. Die Zeile muss also aus der Einstellungsdatei jedes Nutzers gelöscht werden. Also ein Anmeldescript.

Der Vorgang besteht aus 2 Schritten:
1. Die gewünschte Zeile finden.
2. Diese Zeile oder alle anderen Zeilen löschen.

Text finden:

findstr /b /v /i /c:user_pref(\"print.print_printer\" c:\pfad\zur\prefs.js

Damit wird die komplette Zeile mit dem Anfang

user_pref("print.print_printer"

gefunden.

Zeile löschen (mit Loggingfunktion):

@echo off
title Reset Thunderbird Default Printer
set logdir=\\server\pfad\
cd /d "%appdata%\Thunderbird\Profiles\"
cd *.default
if exist prefs_backup.js del prefs_backup.js
if errorlevel 1 goto fehler
ping 127.0.0.1 >> nul
ren prefs.js prefs_backup.js
if errorlevel 1 goto fehler
findstr /b /v /i /c:user_pref(\"print.print_printer\" prefs_backup.js > prefs.js
if errorlevel 1 goto fehler
echo %date% %time% %computername% - Reset erfolgreich >> %logdir%\log.txt
goto end
:fehler
echo %date% %time% %computername% - Reset fehlerhaft >> %logdir%\log.txt
:end

Zeile löschen (pure):

@echo off
cd /d "%appdata%\Thunderbird\Profiles\"
cd *.default
if exist prefs_backup.js del prefs_backup.js
ren prefs.js prefs_backup.js
findstr /b /v /i /c:user_pref(\"print.print_printer\" prefs_backup.js > prefs.js

Und falls man einen Überblick über alle verwendeten Thunderbird drucken haben möchte:

Zeile filtern:

@echo off
cd /d "%appdata%\Thunderbird\Profiles\"
cd *.default
findstr /b /l /i /c:user_pref(\"print.print_printer\" prefs.js >> \\server\pfad\all_prefs.txt


Die Funktionalität des filterns beschränkt sich tatsäch nur darauf, diese 1 Zeile aller Benutzer, auf die das Anmeldescript angewendet wird, zusammenzutragen. Das ließe sich natürlich mit entsprachenden echo Befehlen noch detaillierter loggen.

Die genauere Erklärung der

findstr

Parameter erhaltet ihr in der cmd mit

findstr /?

, ist eigentlich alles sehr eindeutig.

Folgendes Phänomen ist mir letzte Woche zum ersten Mal aufgefallen: Thunderbird nutzt gar nicht den Standarddrucker von Windows als seinen eigenen Standarddrucker sondern hat dort einen ganz anderen ausgewählt. Standarddrucker neu setzen, neustarten, hilft alles nichts.

Lösung:
In der prefs.js im Profilordner des Nutzers ist der von Thunderbird gesetzte Standarddrucker eingetragen.
Die Datei befindet sich hier (Win7):

c:\Users\[username]\AppData\Roaming\Thunderbird\Profiles\[rand.stuff].default\prefs.js

In dieser Datei findet sich, vermutlich relativ am Ende, folgende Zeile:

user_pref("print.print_printer", "Netzdrucker EG");

2 Möglichkeiten:
1. Zeile löschen setzt den Thunderbird Drucker auf den Windows Standarddrucker.
2. Die Zeile auf einen gewünschten Drucker abändern geht natürlich auch.

So heißt eine Komponente der neuen Google Anwendung „Google Correlate„.
Google Correlate kann die Aktivität von Suchanfragen grafisch darstellen. So kann man die Häufigkeit und Popularität einer Suchanfrage seit 2004 mit anderen Suchanfragen vergleichen oder kann Suchanfragen mit ähnlicher Aktivität von Google finden lassen.
Intelligente Menschen können aus diesen Zusammenhängen sicher eine Menge machen, für mich ist es erstmal nur grundlegend interessant 😀

Aber noch besser: „Search by Drawing“
Ihr braucht Suchbegriffe, Events oder andere Dinge mit einer ganz bestimmten zeitlichen Aktivität? Ein Suchbegriff, der Anfang 2005 aktiv war, dann erst Mitte 2009 wieder aufkam und nach 2010 nie wieder gesehen wurde? Google findet es 🙂
Malt selber eine Aktivitätskurve und Google ermittelt Suchbegriffe, die diese Kurve hatten, so gut es geht.

via