public GettextFilesystemFactory(string poDirectory, LocaleFileOrganizationEnum fileOrganization)
            : this()
        {
            if (poDirectory == null) throw new ArgumentNullException("poDirectory");
            this.poDirectory = poDirectory;
            this.fileOrganization = fileOrganization;
            if (string.IsNullOrWhiteSpace(poDirectory)) throw new GettextException("Missing directory parameter");

            var d = new DirectoryInfo(poDirectory);
            if (!d.Exists) throw new GettextException("Directory doesn't exist!");

            // initial load
            {
                var c = LoadAllLanguages(d, fileOrganization);

                lock (lockObject)
                {
                    LoadIntoCatalogs(c, catalogs);
                }
            }

            // filesystem watcher
            {
                var includeSubdirectories = false;
                var filePattern = "*.po";

                if (fileOrganization == LocaleFileOrganizationEnum.DirectoryPerLocale)
                {
                    filePattern = "messages.po";
                    includeSubdirectories = true;
                }

                // init
                fileSystemWatcher = new FileSystemWatcher(d.FullName, filePattern);
                fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                fileSystemWatcher.IncludeSubdirectories = includeSubdirectories;

                fileSystemWatcher.Changed += FileSystemWatcherEventHandler;
                fileSystemWatcher.Created += FileSystemWatcherEventHandler;
                fileSystemWatcher.Deleted += FileSystemWatcherEventHandler;
                fileSystemWatcher.Renamed += FileSystemWatcherEventHandler;

                fileSystemWatcher.EnableRaisingEvents = true;
            }
        }
        private static LanguageTranslation LoadCatalog(FileInfo f, LocaleFileOrganizationEnum fileOrganization)
        {
            if (f == null) throw new ArgumentNullException("f");
            if (!f.Exists) throw new GettextException("File " + f.FullName + " doesn't exist anymore!");

            string langId = null;
            if (fileOrganization == LocaleFileOrganizationEnum.FilePerLocale)
            {
                langId = f.Name.Replace(".po", "").Trim();
            } else
            {
                if (f.Directory != null) langId = f.Directory.Name.Trim();
            }

            if (langId == null) throw new GettextException("Language id for file " + f.FullName + " can't be determined.");

            using (var fs = f.OpenRead())
            {
                var catalog = GettextCatalog.ParseFromStream(fs);

                CultureInfo cultureInfo;
                try
                {
                    cultureInfo = CultureInfo.GetCultureInfo(langId);
                }
                catch (Exception)
                {
                    cultureInfo = CultureInfo.InvariantCulture;
                }

                var lt = new LanguageTranslation(langId, new Gettext(catalog), cultureInfo);

                return lt;
            }
        }
        private static List<LanguageTranslation> LoadAllLanguages(DirectoryInfo d, LocaleFileOrganizationEnum fileOrganization)
        {
            if (d == null) throw new ArgumentNullException("d");
            if (!d.Exists) throw new GettextException("Directory " + d.FullName + " doesn't exist!");

            var f = d.GetFiles(fileOrganization == LocaleFileOrganizationEnum.FilePerLocale ? "*.po" : "messages.po",
                               fileOrganization == LocaleFileOrganizationEnum.FilePerLocale ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories);

            return f.Select(info => LoadCatalog(info, fileOrganization)).ToList();
        }