Exemplo n.º 1
0
function getLanguages($use_cache = true, $favor_utf8 = true)
{
    global $context, $settings, $modSettings;
    // Either we don't use the cache, or its expired.
    if (!$use_cache || ($context['languages'] = CacheAPI::getCache('known_languages' . ($favor_utf8 ? '' : '_all'), !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600)) == null) {
        // If we don't have our theme information yet, lets get it.
        if (empty($settings['default_theme_dir'])) {
            loadTheme(0, false);
        } else {
            $settings['actual_theme_url'] = $settings['theme_url'];
            $settings['actual_images_url'] = $settings['images_url'];
            $settings['actual_theme_dir'] = $settings['theme_dir'];
        }
        // Default language directories to try.
        $language_directories = array($settings['default_theme_dir'] . '/languages', $settings['actual_theme_dir'] . '/languages');
        // We possibly have a base theme directory.
        if (!empty($settings['base_theme_dir'])) {
            $language_directories[] = $settings['base_theme_dir'] . '/languages';
        }
        // Remove any duplicates.
        $language_directories = array_unique($language_directories);
        foreach ($language_directories as $language_dir) {
            // Can't look in here... doesn't exist!
            if (!file_exists($language_dir)) {
                continue;
            }
            $dir = dir($language_dir);
            while ($entry = $dir->read()) {
                // Look for the index language file....
                if (!preg_match('~^index\\.(.+)\\.php$~', $entry, $matches)) {
                    continue;
                }
                $context['languages'][$matches[1]] = array('name' => commonAPI::ucwords(strtr($matches[1], array('_' => ' '))), 'selected' => false, 'filename' => $matches[1], 'location' => $language_dir . '/index.' . $matches[1] . '.php');
            }
            $dir->close();
        }
        // Favoring UTF8? Then prevent us from selecting non-UTF8 versions.
        if ($favor_utf8) {
            foreach ($context['languages'] as $lang) {
                if (substr($lang['filename'], strlen($lang['filename']) - 5, 5) != '-utf8' && isset($context['languages'][$lang['filename'] . '-utf8'])) {
                    unset($context['languages'][$lang['filename']]);
                }
            }
        }
        // Lets cash in on this deal.
        if (!empty($modSettings['cache_enable'])) {
            CacheAPI::putCache('known_languages' . ($favor_utf8 ? '' : '_all'), $context['languages'], !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
        }
    }
    return $context['languages'];
}
Exemplo n.º 2
0
function template_package_list()
{
    global $context, $settings, $options, $txt, $scripturl, $smcFunc;
    echo '
	<div id="admincenter">
		<div class="cat_bar">
			<h3>' . $context['page_title'] . '</h3>
		</div>
		<div class="blue_container">
			<div class="content">';
    // No packages, as yet.
    if (empty($context['package_list'])) {
        echo '
				<ul>
					<li>', $txt['no_packages'], '</li>
				</ul>';
    } else {
        echo '
				<ul id="package_list">';
        foreach ($context['package_list'] as $i => $packageSection) {
            echo '
					<li>
						<strong><img id="ps_img_', $i, '" src="', $settings['images_url'], '/upshrink.png" alt="*" style="display: none;" /> ', $packageSection['title'], '</strong>';
            if (!empty($packageSection['text'])) {
                echo '
						<div class="information">', $packageSection['text'], '</div>';
            }
            echo '
						<', $context['list_type'], ' id="package_section_', $i, '" class="packages">';
            $alt = false;
            foreach ($packageSection['items'] as $id => $package) {
                echo '
							<li>';
                // Textual message. Could be empty just for a blank line...
                if ($package['is_text']) {
                    echo '
								', empty($package['name']) ? '&nbsp;' : $package['name'];
                } elseif ($package['is_line']) {
                    echo '
							<hr class="hrcolor" />';
                } elseif ($package['is_remote']) {
                    echo '
							<strong>', $package['link'], '</strong>';
                } elseif ($package['is_heading'] || $package['is_title']) {
                    echo '
							<strong>', $package['name'], '</strong>';
                } else {
                    // 1. Some mod [ Download ].
                    echo '
							<strong><img id="ps_img_', $i, '_pkg_', $id, '" src="', $settings['images_url'], '/upshrink.png" alt="*" style="display: none;" /> ', $package['can_install'] ? '<strong>' . $package['name'] . '</strong> <a href="' . $package['download']['href'] . '">[ ' . $txt['download'] . ' ]</a>' : $package['name'];
                    // Mark as installed and current?
                    if ($package['is_installed'] && !$package['is_newer']) {
                        echo '<img src="', $settings['images_url'], '/icons/package_', $package['is_current'] ? 'installed' : 'old', '.gif" width="12" height="11" align="middle" style="margin-left: 2ex;" alt="', $package['is_current'] ? $txt['package_installed_current'] : $txt['package_installed_old'], '" />';
                    }
                    echo '
							</strong>
							<ul id="package_section_', $i, '_pkg_', $id, '" class="package_section">';
                    // Show the mod type?
                    if ($package['type'] != '') {
                        echo '
								<li class="package_section">', $txt['package_type'], ':&nbsp; ', commonAPI::ucwords(commonAPI::strtolower($package['type'])), '</li>';
                    }
                    // Show the version number?
                    if ($package['version'] != '') {
                        echo '
								<li class="package_section">', $txt['mod_version'], ':&nbsp; ', $package['version'], '</li>';
                    }
                    // How 'bout the author?
                    if (!empty($package['author']) && $package['author']['name'] != '' && isset($package['author']['link'])) {
                        echo '
								<li class="package_section">', $txt['mod_author'], ':&nbsp; ', $package['author']['link'], '</li>';
                    }
                    // The homepage....
                    if ($package['author']['website']['link'] != '') {
                        echo '
								<li class="package_section">', $txt['author_website'], ':&nbsp; ', $package['author']['website']['link'], '</li>';
                    }
                    // Desciption: bleh bleh!
                    // Location of file: http://someplace/.
                    echo '
								<li class="package_section">', $txt['file_location'], ':&nbsp; <a href="', $package['href'], '">', $package['href'], '</a></li>
								<li class="package_section"><div class="information">', $txt['package_description'], ':&nbsp; ', $package['description'], '</div></li>
							</ul>';
                }
                $alt = !$alt;
                echo '
						</li>';
            }
            echo '
					</', $context['list_type'], '>
						</li>';
        }
        echo '
				</ul>';
    }
    echo '
			</div>
		</div>
		<div class="padding smalltext floatleft">
			', $txt['package_installed_key'], '
			<img src="', $settings['images_url'], '/icons/package_installed.gif" alt="" align="middle" style="margin-left: 1ex;" /> ', $txt['package_installed_current'], '
			<img src="', $settings['images_url'], '/icons/package_old.gif" alt="" align="middle" style="margin-left: 2ex;" /> ', $txt['package_installed_old'], '
		</div>
	</div>
	<br class="clear" />

		';
    // Now go through and turn off all the sections.
    if (!empty($context['package_list'])) {
        $section_count = count($context['package_list']);
        echo '
			<script type="text/javascript"><!-- // --><![CDATA[';
        foreach ($context['package_list'] as $section => $ps) {
            echo '';
            foreach ($ps['items'] as $id => $package) {
                if (!$package['is_text'] && !$package['is_line'] && !$package['is_remote']) {
                    echo '';
                }
            }
        }
        echo '
			// ]]></script>';
    }
}
Exemplo n.º 3
0
function ModifyLanguage()
{
    global $settings, $context, $txt, $modSettings, $boarddir, $sourcedir, $language;
    loadLanguage('ManageSettings');
    // Select the languages tab.
    $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'edit';
    $context['page_title'] = $txt['edit_languages'];
    $context['sub_template'] = 'modify_language_entries';
    $context['lang_id'] = $_GET['lid'];
    list($theme_id, $file_id) = empty($_REQUEST['tfid']) || strpos($_REQUEST['tfid'], '+') === false ? array(1, '') : explode('+', $_REQUEST['tfid']);
    // Clean the ID - just in case.
    preg_match('~([A-Za-z0-9_-]+)~', $context['lang_id'], $matches);
    $context['lang_id'] = $matches[1];
    // Get all the theme data.
    $request = smf_db_query('
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE id_theme != {int:default_theme}
			AND id_member = {int:no_member}
			AND variable IN ({string:name}, {string:theme_dir})', array('default_theme' => 1, 'no_member' => 0, 'name' => 'name', 'theme_dir' => 'theme_dir'));
    $themes = array(1 => array('name' => $txt['dvc_default'], 'theme_dir' => $settings['default_theme_dir']));
    while ($row = mysql_fetch_assoc($request)) {
        $themes[$row['id_theme']][$row['variable']] = $row['value'];
    }
    mysql_free_result($request);
    // This will be where we look
    $lang_dirs = array();
    // Check we have themes with a path and a name - just in case - and add the path.
    foreach ($themes as $id => $data) {
        if (count($data) != 2) {
            unset($themes[$id]);
        } elseif (is_dir($data['theme_dir'] . '/languages')) {
            $lang_dirs[$id] = $data['theme_dir'] . '/languages';
        }
        // How about image directories?
        if (is_dir($data['theme_dir'] . '/images/' . $context['lang_id'])) {
            $images_dirs[$id] = $data['theme_dir'] . '/images/' . $context['lang_id'];
        }
    }
    $current_file = $file_id ? $lang_dirs[$theme_id] . '/' . $file_id . '.' . $context['lang_id'] . '.php' : '';
    // Now for every theme get all the files and stick them in context!
    $context['possible_files'] = array();
    foreach ($lang_dirs as $theme => $theme_dir) {
        // Open it up.
        $dir = dir($theme_dir);
        while ($entry = $dir->read()) {
            // We're only after the files for this language.
            if (preg_match('~^([A-Za-z]+)\\.' . $context['lang_id'] . '\\.php$~', $entry, $matches) == 0) {
                continue;
            }
            //!!! Temp!
            if ($matches[1] == 'EmailTemplates') {
                continue;
            }
            if (!isset($context['possible_files'][$theme])) {
                $context['possible_files'][$theme] = array('id' => $theme, 'name' => $themes[$theme]['name'], 'files' => array());
            }
            $context['possible_files'][$theme]['files'][] = array('id' => $matches[1], 'name' => isset($txt['lang_file_desc_' . $matches[1]]) ? $txt['lang_file_desc_' . $matches[1]] : $matches[1], 'selected' => $theme_id == $theme && $file_id == $matches[1]);
        }
        $dir->close();
    }
    // We no longer wish to speak this language.
    if (!empty($_POST['delete_main']) && $context['lang_id'] != 'english') {
        checkSession();
        // !!! Todo: FTP Controls?
        require_once $sourcedir . '/lib/Subs-Package.php';
        // First, Make a backup?
        if (!empty($modSettings['package_make_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['lang_id'] . '$$$')) {
            $_SESSION['last_backup_for'] = $context['lang_id'] . '$$$';
            package_create_backup('backup_lang_' . $context['lang_id']);
        }
        // Second, loop through the array to remove the files.
        foreach ($lang_dirs as $curPath) {
            foreach ($context['possible_files'][1]['files'] as $lang) {
                if (file_exists($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php')) {
                    unlink($curPath . '/' . $lang['id'] . '.' . $context['lang_id'] . '.php');
                }
            }
            // Check for the email template.
            if (file_exists($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php')) {
                unlink($curPath . '/EmailTemplates.' . $context['lang_id'] . '.php');
            }
        }
        // Third, the agreement file.
        if (file_exists($boarddir . '/agreement.' . $context['lang_id'] . '.txt')) {
            unlink($boarddir . '/agreement.' . $context['lang_id'] . '.txt');
        }
        // Fourth, a related images folder?
        foreach ($images_dirs as $curPath) {
            if (is_dir($curPath)) {
                deltree($curPath);
            }
        }
        // Members can no longer use this language.
        smf_db_query('
			UPDATE {db_prefix}members
			SET lngfile = {string:empty_string}
			WHERE lngfile = {string:current_language}', array('empty_string' => '', 'current_language' => $context['lang_id']));
        // Fifth, update getLanguages() cache.
        if (!empty($modSettings['cache_enable'])) {
            CacheAPI::putCache('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
            CacheAPI::putCache('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600);
        }
        // Sixth, if we deleted the default language, set us back to english?
        if ($context['lang_id'] == $language) {
            require_once $sourcedir . '/lib/Subs-Admin.php';
            $language = 'english';
            updateSettingsFile(array('language' => '\'' . $language . '\''));
        }
        // Seventh, get out of here.
        redirectexit('action=admin;area=languages;sa=edit;' . $context['session_var'] . '=' . $context['session_id']);
    }
    // Saving primary settings?
    $madeSave = false;
    if (!empty($_POST['save_main']) && !$current_file) {
        checkSession();
        // Read in the current file.
        $current_data = implode('', file($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php'));
        // These are the replacements. old => new
        $replace_array = array('~\\$txt\\[\'lang_character_set\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_character_set\'] = \'' . addslashes($_POST['character_set']) . '\';', '~\\$txt\\[\'lang_locale\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_locale\'] = \'' . addslashes($_POST['locale']) . '\';', '~\\$txt\\[\'lang_dictionary\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_dictionary\'] = \'' . addslashes($_POST['dictionary']) . '\';', '~\\$txt\\[\'lang_spelling\'\\]\\s=\\s(\'|")[^\\r\\n]+~' => '$txt[\'lang_spelling\'] = \'' . addslashes($_POST['spelling']) . '\';', '~\\$txt\\[\'lang_rtl\'\\]\\s=\\s[A-Za-z0-9]+;~' => '$txt[\'lang_rtl\'] = ' . (!empty($_POST['rtl']) ? 'true' : 'false') . ';');
        $current_data = preg_replace(array_keys($replace_array), array_values($replace_array), $current_data);
        $fp = fopen($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php', 'w+');
        fwrite($fp, $current_data);
        fclose($fp);
        $madeSave = true;
    }
    // Quickly load index language entries.
    $old_txt = $txt;
    require $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php';
    $context['lang_file_not_writable_message'] = is_writable($settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php') ? '' : sprintf($txt['lang_file_not_writable'], $settings['default_theme_dir'] . '/languages/index.' . $context['lang_id'] . '.php');
    // Setup the primary settings context.
    $context['primary_settings'] = array('name' => commonAPI::ucwords(strtr($context['lang_id'], array('_' => ' ', '-utf8' => ''))), 'character_set' => $txt['lang_character_set'], 'locale' => $txt['lang_locale'], 'dictionary' => $txt['lang_dictionary'], 'spelling' => $txt['lang_spelling'], 'rtl' => $txt['lang_rtl']);
    // Restore normal service.
    $txt = $old_txt;
    // Are we saving?
    $save_strings = array();
    if (isset($_POST['save_entries']) && !empty($_POST['entry'])) {
        checkSession();
        // Clean each entry!
        foreach ($_POST['entry'] as $k => $v) {
            // Only try to save if it's changed!
            if ($_POST['entry'][$k] != $_POST['comp'][$k]) {
                $save_strings[$k] = cleanLangString($v, false);
            }
        }
    }
    // If we are editing a file work away at that.
    if ($current_file) {
        $context['entries_not_writable_message'] = is_writable($current_file) ? '' : sprintf($txt['lang_entries_not_writable'], $current_file);
        $entries = array();
        // We can't just require it I'm afraid - otherwise we pass in all kinds of variables!
        $multiline_cache = '';
        foreach (file($current_file) as $line) {
            // Got a new entry?
            if ($line[0] == '$' && !empty($multiline_cache)) {
                preg_match('~\\$(helptxt|txt)\\[\'(.+)\'\\]\\s=\\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches);
                if (!empty($matches[3])) {
                    $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]);
                    $multiline_cache = '';
                }
            }
            $multiline_cache .= $line . "\n";
        }
        // Last entry to add?
        if ($multiline_cache) {
            preg_match('~\\$(helptxt|txt)\\[\'(.+)\'\\]\\s=\\s(.+);~', strtr($multiline_cache, array("\n" => '', "\t" => '')), $matches);
            if (!empty($matches[3])) {
                $entries[$matches[2]] = array('type' => $matches[1], 'full' => $matches[0], 'entry' => $matches[3]);
            }
        }
        // These are the entries we can definitely save.
        $final_saves = array();
        $context['file_entries'] = array();
        foreach ($entries as $entryKey => $entryValue) {
            // Ignore some things we set separately.
            $ignore_files = array('lang_character_set', 'lang_locale', 'lang_dictionary', 'lang_spelling', 'lang_rtl');
            if (in_array($entryKey, $ignore_files)) {
                continue;
            }
            // These are arrays that need breaking out.
            $arrays = array('days', 'days_short', 'months', 'months_titles', 'months_short');
            if (in_array($entryKey, $arrays)) {
                // Get off the first bits.
                $entryValue['entry'] = substr($entryValue['entry'], strpos($entryValue['entry'], '(') + 1, strrpos($entryValue['entry'], ')') - strpos($entryValue['entry'], '('));
                $entryValue['entry'] = explode(',', strtr($entryValue['entry'], array(' ' => '')));
                // Now create an entry for each item.
                $cur_index = 0;
                $save_cache = array('enabled' => false, 'entries' => array());
                foreach ($entryValue['entry'] as $id => $subValue) {
                    // Is this a new index?
                    if (preg_match('~^(\\d+)~', $subValue, $matches)) {
                        $cur_index = $matches[1];
                        $subValue = substr($subValue, strpos($subValue, '\''));
                    }
                    // Clean up some bits.
                    $subValue = strtr($subValue, array('"' => '', '\'' => '', ')' => ''));
                    // Can we save?
                    if (isset($save_strings[$entryKey . '-+- ' . $cur_index])) {
                        $save_cache['entries'][$cur_index] = strtr($save_strings[$entryKey . '-+- ' . $cur_index], array('\'' => ''));
                        $save_cache['enabled'] = true;
                    } else {
                        $save_cache['entries'][$cur_index] = $subValue;
                    }
                    $context['file_entries'][] = array('key' => $entryKey . '-+- ' . $cur_index, 'value' => $subValue, 'rows' => 1);
                    $cur_index++;
                }
                // Do we need to save?
                if ($save_cache['enabled']) {
                    // Format the string, checking the indexes first.
                    $items = array();
                    $cur_index = 0;
                    foreach ($save_cache['entries'] as $k2 => $v2) {
                        // Manually show the custom index.
                        if ($k2 != $cur_index) {
                            $items[] = $k2 . ' => \'' . $v2 . '\'';
                            $cur_index = $k2;
                        } else {
                            $items[] = '\'' . $v2 . '\'';
                        }
                        $cur_index++;
                    }
                    // Now create the string!
                    $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = array(' . implode(', ', $items) . ');');
                }
            } else {
                // Saving?
                if (isset($save_strings[$entryKey]) && $save_strings[$entryKey] != $entryValue['entry']) {
                    // !!! Fix this properly.
                    if ($save_strings[$entryKey] == '') {
                        $save_strings[$entryKey] = '\'\'';
                    }
                    // Set the new value.
                    $entryValue['entry'] = $save_strings[$entryKey];
                    // And we know what to save now!
                    $final_saves[$entryKey] = array('find' => $entryValue['full'], 'replace' => '$' . $entryValue['type'] . '[\'' . $entryKey . '\'] = ' . $save_strings[$entryKey] . ';');
                }
                $editing_string = cleanLangString($entryValue['entry'], true);
                $context['file_entries'][] = array('key' => $entryKey, 'value' => $editing_string, 'rows' => (int) (strlen($editing_string) / 38) + substr_count($editing_string, "\n") + 1);
            }
        }
        // Any saves to make?
        if (!empty($final_saves)) {
            checkSession();
            $file_contents = implode('', file($current_file));
            foreach ($final_saves as $save) {
                $file_contents = strtr($file_contents, array($save['find'] => $save['replace']));
            }
            // Save the actual changes.
            $fp = fopen($current_file, 'w+');
            fwrite($fp, $file_contents);
            fclose($fp);
            $madeSave = true;
        }
        // Another restore.
        $txt = $old_txt;
    }
    // If we saved, redirect.
    if ($madeSave) {
        redirectexit('action=admin;area=languages;sa=editlang;lid=' . $context['lang_id']);
    }
}
Exemplo n.º 4
0
function timeformat_static($log_time, $show_today = true, $offset_type = false)
{
    global $context, $user_info, $txt, $modSettings;
    static $non_twelve_hour = null;
    // Offset the time.
    if (!$offset_type) {
        $time = $log_time + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600;
    } elseif ($offset_type == 'forum') {
        $time = $log_time + $modSettings['time_offset'] * 3600;
    } else {
        $time = $log_time;
    }
    // We can't have a negative date (on Windows, at least.)
    if ($log_time < 0) {
        $log_time = 0;
    }
    // Today and Yesterday?
    // Get the current time.
    $nowtime = forum_time();
    $now = @getdate($nowtime);
    if ($modSettings['todayMod'] >= 1 && $show_today === true) {
        $then = @getdate($time);
        $now = @getdate($nowtime);
        // Try to make something of a time format string...
        $s = strpos($user_info['time_format'], '%S') === false ? '' : ':%S';
        if (strpos($user_info['time_format'], '%H') === false && strpos($user_info['time_format'], '%T') === false) {
            $h = strpos($user_info['time_format'], '%l') === false ? '%I' : '%l';
            $today_fmt = $h . ':%M' . $s . ' %p';
        } else {
            $today_fmt = '%H:%M' . $s;
        }
        // Same day of the year, same year.... Today!
        if ($then['yday'] == $now['yday'] && $then['year'] == $now['year']) {
            return $txt['today'] . timeformat($log_time, $today_fmt, $offset_type);
        }
        // Day-of-year is one less and same year, or it's the first of the year and that's the last of the year...
        if ($modSettings['todayMod'] == '2' && ($then['yday'] == $now['yday'] - 1 && $then['year'] == $now['year'] || $now['yday'] == 0 && $then['year'] == $now['year'] - 1 && $then['mon'] == 12 && $then['mday'] == 31)) {
            return $txt['yesterday'] . timeformat($log_time, $today_fmt, $offset_type);
        }
    }
    $str = !is_bool($show_today) ? $show_today : $user_info['time_format'];
    if (setlocale(LC_TIME, $txt['lang_locale'])) {
        if (is_null($non_twelve_hour)) {
            $non_twelve_hour = trim(strftime('%p')) === '';
        }
        if ($non_twelve_hour && strpos($str, '%p') !== false) {
            $str = str_replace('%p', strftime('%H', $time) < 12 ? $txt['time_am'] : $txt['time_pm'], $str);
        }
        foreach (array('%a', '%A', '%b', '%B') as $token) {
            if (strpos($str, $token) !== false) {
                $str = str_replace($token, !empty($txt['lang_capitalize_dates']) ? commonAPI::ucwords(strftime($token, $time)) : strftime($token, $time), $str);
            }
        }
    } else {
        // Do-it-yourself time localization.  Fun.
        foreach (array('%a' => 'days_short', '%A' => 'days', '%b' => 'months_short', '%B' => 'months') as $token => $text_label) {
            if (strpos($str, $token) !== false) {
                $str = str_replace($token, $txt[$text_label][(int) strftime($token === '%a' || $token === '%A' ? '%w' : '%m', $time)], $str);
            }
        }
        if (strpos($str, '%p') !== false) {
            $str = str_replace('%p', strftime('%H', $time) < 12 ? $txt['time_am'] : $txt['time_pm'], $str);
        }
    }
    // Windows doesn't support %e; on some versions, strftime fails altogether if used, so let's prevent that.
    if ($context['server']['is_windows'] && strpos($str, '%e') !== false) {
        $str = str_replace('%e', ltrim(strftime('%d', $time), '0'), $str);
    }
    return strftime($str, $time);
}