public static function fromString($str)
    {
        $stringset = new Stringset();

        $entry = array();
        $state = null;
        $line = 1;

        foreach (explode("\n", $str) as $line) {
            $line = trim($line);
            if (strlen($line) === 0) {
                if (count($entry) > 0) {
                    $stringset->add($entry);
                    $entry = array();
                    $state = null;
                }
                continue;
            }

            if ($line[0] === '#' && $line[1] === ',') {
                $entry['flags'] = array_map('trim', explode(',', substr($line, 2)));
            } else if ($line[0] !== '#') {
                // non-comment
                list($key, $rest) = explode(' ', $line, 2);
                switch ($key) {
                    case 'msgid':
                    case 'msgid_plural':
                    case 'msgstr':
                    case 'msgctxt':
                        if (strpos($state, 'msgstr') === 0 && $key !== 'msgstr' && count($entry) > 0) {
                            $stringset->add($entry);
                            $entry = array();
                        }
                        $state = $key;
                        $entry[$key] = self::parseString($rest);
                        break;
                    default:
                        if (strpos($key, 'msgstr[') === 0) {
                            $state = $key;
                            $entry[$key] = self::parseString($rest);
                        } else {
                            $entry[$state] .= self::parseString(trim($line));
                        }
                }
            }
            $line += 1;
        }
        return $stringset;
    }